JavaScript范围和闭包

时间:2009-03-10 16:44:47

标签: javascript scope closures

我正试着把头包裹起来(那里有一个笑话)然后我碰到了这个:

(function () { /* do cool stuff */ })();

这是如何工作的?将功能放入parens的目的是什么?之后为什么空洞呢?

7 个答案:

答案 0 :(得分:30)

关键在于,在酷炫的东西中声明的任何变量都不会在全局命名空间中创建。 javascript中的任何函数都将创建这样的范围。假设您有一些想要运行的JavaScript。如果你这样做:

var b = 1; 
// stuff using b

其他一些代码使用b,它会让你的剩余价值。 (或者,更糟糕的是,如果某些其他代码在代码运行之前设置了b,那么稍后尝试获取其旧值,那么在此期间您已经更改了它。)

另一方面,如果你有这个代码,它声明然后调用一个函数:

function a() { 
     var b = 1;
}

a();

稍后其他一些代码使用b,它将看不到你的值,因为b是函数的本地代码。当然,问题在于你仍然在创建一个全局名称 - 在这种情况下是“a”。所以,我们想要一个没有名字的函数 - 这就是你得到你描述的代码的原因。它声明了一个没有名字的函数,然后调用它。

不幸的是,你不能只说:

function() { ... }()

因为这将被解析为函数声明语句,然后出现语法错误。通过将函数声明包装在括号中,您将获得一个函数 expression ,然后可以调用它。您可以像使用第二组parens一样将其称为任何其他函数表达式(如上图所示)。例如,如果函数接受了参数,那么你将它们传递给那里:

(function(a) { ... })(1)

答案 1 :(得分:6)

创建一个函数,调用它并丢弃它。

如果你这样看它可能会更清楚:

var throwaway = function(){
    // do cool stuff
};
throwaway();

这样做是为了创建一个私有命名空间。函数中的代码可以包含函数和变量,而不必担心与页面中加载的其他代码冲突。

答案 2 :(得分:2)

我最近刚看到这篇文章。这种类型的功能定义&呼叫称为自我调用功能

(function(){  //code })();

函数内部的代码将在定义后立即执行。

答案 3 :(得分:1)

该构造意味着声明一个匿名函数并立即运行它。将代码放在函数体中的原因是因为您在其中定义的变量保持在函数的本地,而不是全局变量。但是,它们仍然可以在此函数中定义的闭包中看到。

答案 4 :(得分:1)

函数周围的parens表明函数是一个表达式。之后的parens是对函数的调用。

请注意,该函数没有名称。

答案 5 :(得分:1)

一种闭包方法是将变量传递给函数:

errorlog

答案 6 :(得分:0)

将函数声明放在parens中会创建一个表达式,该表达式计算其中的匿名函数。因此,第一个括号评估函数。

最后的“空的parens”调用定义的函数,所以“// do cool stuff”立即执行。

这是一种即时执行代码同时保持变量不在全局范围内的方法。

然而,这里所说明的与闭包无关 - 至少不是直接的。闭包是关于在父函数退出后保持词法范围。