我经常看到下面的代码:
(function () {
// init part
})();但是我从来不知道它是怎么工作的。我发现最后一个括号特别令人困惑。有人能从执行上下文(EC)和变量对象(VO)方面解释一下它是如何工作的吗?
发布于 2010-11-18 14:43:35
该模式将创建一个新的执行上下文( EC ),其中任何局部变量对象(VO)都将存在,并且同样会在EC退出时终止。这个生命周期唯一的例外是VO,它会成为closure的一部分。
请注意,JavaScript没有神奇的"init“函数。您可能会将此模式与之联系起来,因为几乎所有自重的JS库(jQuery、YUI等)都是如此。会这样做,这样他们就不会对全球网络造成超过他们需要的污染。
演示:
var x = 1; // global VO
(function(){
var x = 2; // local VO
})();
x == 1; // global VO, unchanged by the local VO第二组“括号”(实际上称为括号,或一组括号)只是调用紧跟在它前面的函数表达式(由前一组括号定义)。
发布于 2010-11-18 14:44:00
我通常向人们解释这一点的方法是展示它与其他JavaScript模式的相似之处。
首先,您应该知道声明函数有两种方法(实际上,至少有五种,但这是两个主要原因):
function foo() {/*code*/}
和
var foo = function() {/*code*/};
即使这种结构看起来很奇怪,但在附加事件时可能会一直使用它:
window.onload=function(){/*code*/};
您应该注意到,第二种形式与常规变量声明没有太大不同:
var bar = 5;
var baz = 'some string';
var foo = function() {/*code*/};但在JavaScript中,您始终可以选择直接使用值或通过变量使用值。如果bar为5,则接下来的两个语句等价:
var myVal = bar * 100; // use 'bar'
var myVal = 5 * 100; // don't use 'bar'那么,如果您可以单独使用5,为什么不能单独使用function() {\*code*\}呢?事实上,你可以。这就是匿名函数。所以这两个例子也是等价的:
var foo = function() {/*code*/}; // use 'foo'
foo();
(function(){/*code*/})(); // don't use 'foo' 您应该看到的唯一区别是额外的括号。这很简单,因为如果您以关键字function开始一行,解析器将认为您正在使用此答案顶部的第一个模式声明函数,并抛出语法错误异常。因此,将整个匿名函数包装在一对大括号中,问题就解决了。
换句话说,以下三种说法是有效的:
5; // pointless and stupid
'some string'; // pointless and stupid
(function(){/*code*/})(); // wonderfully powerful2020年编辑
我的答案的前一个版本推荐了Douglas Crockford对这些“立即调用的匿名函数”的括号包装形式。User @RayLoveless在2012年推荐使用现在显示的版本。当时,在使用ES6和箭头函数之前,没有明显的习惯用法区别;您只需防止语句以function关键字开头。事实上,有很多方法可以做到这一点。但是使用括号,这两个语句在句法和习语上是等价的:
( function() { /* code */}() );
( function() { /* code */} )();但是user @zentechinc下面的评论提醒我,箭头函数改变了这一切。所以现在只有一种说法是正确的。
( () => { /* code */ }() ); // Syntax error
( () => { /* code */ } )();这到底为什么重要呢?实际上,它很容易演示。记住,箭头函数有两种基本形式:
() => { return 5; }; // With a function body
() => { console.log(5); };
() => 5; // Or with a single expression
() => console.log(5);如果没有括号来包装第二种类型的箭头函数,您最终会得到一个惯用的混乱:
() => 5(); // How do you invoke a 5?
() => console.log(5)(); // console.log does not return a function!发布于 2010-11-18 14:22:54
代码创建一个匿名函数,然后立即运行它。类似于:
var temp = function() {
// init part
}
temp();此构造的目的是为函数内部的代码创建一个作用域。您可以在作用域中声明变量和函数,这些变量和函数将是该作用域的局部变量。这样,它们就不会打乱全局范围,从而最大限度地降低了与其他脚本冲突的风险。
https://stackoverflow.com/questions/4212149
复制相似问题