首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >javascript中的Init函数及其工作方式

javascript中的Init函数及其工作方式
EN

Stack Overflow用户
提问于 2010-11-18 14:17:24
回答 7查看 129.7K关注 0票数 56

我经常看到下面的代码:

代码语言:javascript
运行
复制
(function () {
  // init part
})();

但是我从来不知道它是怎么工作的。我发现最后一个括号特别令人困惑。有人能从执行上下文(EC)和变量对象(VO)方面解释一下它是如何工作的吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-11-18 14:43:35

该模式将创建一个新的执行上下文( EC ),其中任何局部变量对象(VO)都将存在,并且同样会在EC退出时终止。这个生命周期唯一的例外是VO,它会成为closure的一部分。

请注意,JavaScript没有神奇的"init“函数。您可能会将此模式与之联系起来,因为几乎所有自重的JS库(jQuery、YUI等)都是如此。会这样做,这样他们就不会对全球网络造成超过他们需要的污染。

演示:

代码语言:javascript
运行
复制
var x = 1; // global VO
(function(){        
    var x = 2; // local VO
})();
x == 1; // global VO, unchanged by the local VO

第二组“括号”(实际上称为括号,或一组括号)只是调用紧跟在它前面的函数表达式(由前一组括号定义)。

票数 50
EN

Stack Overflow用户

发布于 2010-11-18 14:44:00

我通常向人们解释这一点的方法是展示它与其他JavaScript模式的相似之处。

首先,您应该知道声明函数有两种方法(实际上,至少有五种,但这是两个主要原因):

function foo() {/*code*/}

var foo = function() {/*code*/};

即使这种结构看起来很奇怪,但在附加事件时可能会一直使用它:

window.onload=function(){/*code*/};

您应该注意到,第二种形式与常规变量声明没有太大不同:

代码语言:javascript
运行
复制
var bar = 5;
var baz = 'some string';
var foo = function() {/*code*/};

但在JavaScript中,您始终可以选择直接使用值或通过变量使用值。如果bar5,则接下来的两个语句等价:

代码语言:javascript
运行
复制
var myVal = bar * 100; // use 'bar'
var myVal = 5 * 100;   // don't use 'bar'

那么,如果您可以单独使用5,为什么不能单独使用function() {\*code*\}呢?事实上,你可以。这就是匿名函数。所以这两个例子也是等价的:

代码语言:javascript
运行
复制
var foo = function() {/*code*/}; // use 'foo'
foo();                           

(function(){/*code*/})();        // don't use 'foo' 

您应该看到的唯一区别是额外的括号。这很简单,因为如果您以关键字function开始一行,解析器将认为您正在使用此答案顶部的第一个模式声明函数,并抛出语法错误异常。因此,将整个匿名函数包装在一对大括号中,问题就解决了。

换句话说,以下三种说法是有效的:

代码语言:javascript
运行
复制
5;                        // pointless and stupid
'some string';            // pointless and stupid
(function(){/*code*/})(); // wonderfully powerful

2020年编辑

我的答案的前一个版本推荐了Douglas Crockford对这些“立即调用的匿名函数”的括号包装形式。User @RayLoveless在2012年推荐使用现在显示的版本。当时,在使用ES6和箭头函数之前,没有明显的习惯用法区别;您只需防止语句以function关键字开头。事实上,有很多方法可以做到这一点。但是使用括号,这两个语句在句法和习语上是等价的:

代码语言:javascript
运行
复制
( function() { /* code */}() );
( function() { /* code */} )();

但是user @zentechinc下面的评论提醒我,箭头函数改变了这一切。所以现在只有一种说法是正确的。

代码语言:javascript
运行
复制
( () => { /* code */ }() ); // Syntax error
( () => { /* code */ } )();

这到底为什么重要呢?实际上,它很容易演示。记住,箭头函数有两种基本形式:

代码语言:javascript
运行
复制
() => { return 5; };       // With a function body
() => { console.log(5); };

() => 5;                   // Or with a single expression
() => console.log(5);

如果没有括号来包装第二种类型的箭头函数,您最终会得到一个惯用的混乱:

代码语言:javascript
运行
复制
() => 5();              // How do you invoke a 5?
() => console.log(5)(); // console.log does not return a function!
票数 81
EN

Stack Overflow用户

发布于 2010-11-18 14:22:54

代码创建一个匿名函数,然后立即运行它。类似于:

代码语言:javascript
运行
复制
var temp = function() {
  // init part
}
temp();

此构造的目的是为函数内部的代码创建一个作用域。您可以在作用域中声明变量和函数,这些变量和函数将是该作用域的局部变量。这样,它们就不会打乱全局范围,从而最大限度地降低了与其他脚本冲突的风险。

票数 26
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/4212149

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档