JavaScript范围和closures

我试图把头绕在closures(有一个笑话在那里),我跑过这个:

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

这个怎么用? 将函数放在父项中的目的是什么? 为什么之后的空洞?

这个问题的关键是,在酷炫的东西中声明的variables将不会在全局命名空间中创build。 JavaScript中的任何函数都将创build这样一个范围。 假设你有一些JavaScript你想运行。 如果你这样做:

 var b = 1; // stuff using b 

而其他一些代码使用b,它会得到你的左值。 (或者,更糟的是,如果其他代码在您的代码运行之前设置了b,则稍后尝试获取其旧值,同时您将更改它。

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

 function a() { var b = 1; } a(); 

而其他一些代码稍后使用b,它不会看到你的值,因为b是函数的本地。 当然,问题在于,你仍然在制造一个全球性的名字 – “a”,在这种情况下。 所以,我们需要一个没有名字的函数 – 这就是为什么你得到你描述的代码。 它声明一个没有名字的函数,然后调用它。

不幸的是,你不能只说:

 function() { ... }() 

因为这将被parsing为函数声明语句 ,然后是语法错误。 通过将函数声明包装在括号中,您将得到一个函数expression式 ,然后可以调用它。 你可以像使用第二组parens一样将其称为任何其他函数expression式(如上面的a)。 例如,如果该函数带有参数,则可以通过它们:

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

创build一个函数,调用它,并放弃它。

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

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

这是为了创build一个私人的名字空间。 函数中的代码可以有函数和variables,而不用担心与页面中加载的其他代码冲突。

我刚刚碰到这个post。 这种types的函数定义&调用称为自调用函数

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

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

函数周围的parens明确表示该函数是一个expression式。 之后的parens是对这个函数的调用。

注意这个函数没有名字。

一个closures方法是将variables传递给函数:

 (function($, var_1, var_2) { // use JQuery, var_1 and var_2 as local variables })($, var_1, var_2); 

该构造意味着声明一个匿名函数并立即运行它。 你把你的代码放在一个函数体内的原因是你在里面定义的variables是局部的而不是全局variables。 但是,它们仍然可以在此函数中定义的闭包中看到。

将函数声明放在parens中创build一个expression式,其内部的匿名函数将被计算。 因此,第一个括号就是一个函数。

最后的“空parens”调用定义的函数,所以“//很酷的东西”立即执行。

这是一种在运行中执行代码的方法,同时也将variables保持在全局范围之外。

然而,这里所说明的与封闭无关 – 至less不是直接的。 在父function已经退出之后,闭包关于保持词法范围。