高级javascript:为什么这个函数用括号括起来?

Advanced JavaScript: Why is this function wrapped in parentheses?

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
What is the (function() { } )() construct in JavaScript?

我遇到了这段javascript代码,但我不知道该怎么做。为什么运行此代码时得到"1"?(1)的这个奇怪的小附录是什么?为什么用括号括起来的函数?

1
2
3
4
(function(x){
    delete x;
    return x;
})(1);

这里发生了一些事情。首先是立即调用的函数表达式(IIFE)模式:

1
2
3
(function() {
  // Some code
})();

这提供了一种在自己的范围内执行一些JavaScript代码的方法。它通常用于在函数中创建的任何变量都不会影响全局范围。你可以用这个来代替:

1
2
3
4
function foo() {
  // Some code
}
foo();

但这需要为函数命名,这并不总是必要的。使用一个命名的函数也意味着在将来的某个时候,可以再次调用这个函数,这可能是不可取的。通过以这种方式使用匿名函数,可以确保只执行一次。

此语法无效:

1
2
3
function() {
  // Some code
}();

因为您必须将函数括在括号中,以便将其作为表达式进行解析。更多信息请访问:http://benalman.com/news/2010/11/immediate-invoked-function-expression/

因此,要快速回顾一下生命周期模式:

1
2
3
(function() {
  // Some code
})();

允许立即执行"some code",就好像它刚被内联写入,但也在它自己的范围内,这样就不会影响全局命名空间(因此可能会干扰或被其他脚本干扰)。

例如,可以像传递普通函数一样将参数传递给函数,

1
2
3
(function(x) {
  // Some code
})(1);

因此,我们将值"1"作为第一个参数传递给函数,该函数将其作为局部作用域变量(名为x)接收。

其次,您有函数代码本身的勇气:

1
2
delete x;
return x;

删除操作符将从对象中删除属性。它不会删除变量。所以;

1
2
3
var foo = {'bar':4, 'baz':5};
delete foo.bar;
console.log(foo);

记录结果:

1
{'baz':5}

然而,

1
2
3
var foo = 4;
delete foo;
console.log(foo);

将记录值4,因为foo是变量而不是属性,因此无法删除。

许多人认为删除可以删除变量,这是因为autoglobals的工作方式。如果在不首先声明变量的情况下为其赋值,则它实际上不会成为变量,而是全局对象上的属性:

1
2
3
bar = 4; // Note the lack of 'var'. Bad practice! Don't ever do this!
delete bar;
console.log(bar); // Error - bar is not defined.

这次删除有效,因为您没有删除变量,而是删除全局对象的属性。实际上,前面的代码片段相当于:

1
2
3
window.bar = 4;
delete window.bar;
console.log(window.bar);

现在您可以看到它是如何类似于foo对象示例而不是foo变量示例的。


这意味着您创建了一个匿名函数,并使用参数1调用它。

它与以下内容相同:

1
2
3
4
5
function foo(x) {
    delete x;
    return x;
}
foo(1);


人们通常称之为"立即调用的函数表达式"或"自执行函数"。

这样做的目的是函数内部声明的变量不会泄漏到外部。


返回1的原因是delete关键字用于删除对象的属性。其余的正如其他人所评论的,括号中的任何内容都作为函数执行,第二组括号是传递给该块的参数。

这里是用于删除的MDN引用,以及用于闭包的MDN引用,其中还讨论了匿名函数。