为什么这个闭包范围的变量会失去它的价值?

时间:2011-04-21 05:57:36

标签: javascript closures

我在这里看到了这个Javascript测验:http://www.netfxharmonics.com/2008/01/NetFX-Harmonics-JavaScript-Quiz

我无法弄清楚这个问题:

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

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

    console.log('a:'+ a);  // => "a:undefined"
    console.log('b:'+ b);  // => "b:2"
})()

但是,如果您从内部函数中删除var b;声明,那么就像您期望的那样a == 2

为什么会这样?

(你可以在这里玩:http://jsfiddle.net/gnhMZ/

2 个答案:

答案 0 :(得分:8)

这是因为这个功能正在发生:

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

...将undefined分配给avar takes effect as of the beginning of the scope in which it's written它在逐步代码中的位置。当您声明变量时,其初始值为undefined。所以上面写的更明确,但具有完全相同的功能,看起来像这样:

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

具体来说,当执行进入执行上下文时,会发生以下情况:

  1. 为执行上下文创建幕后变量对象,并将其置于范围链的顶部(用于解析不合格的变量对象链)参考文献)。
  2. 对于在上下文中声明的每个var,在该变量对象上创建属性,而不管var语句在何处。每个变量的初始值为undefined。此时不处理初始化程序。
  3. 在上下文中声明的每个函数(带有函数声明,而不是函数表达式)的变量对象上创建属性,无论函数声明在何处。
  4. 处理函数声明并将结果分配给这些函数的属性。
  5. 继续执行上下文中的第一行分步代码。遇到带有初始化程序的var语句时,它将作为简单赋值语句处理。
  6. 顺便说一句,变量对象也是使闭包工作的东西。 More here,但基本上,当创建一个函数时,它会在该点获得对作用域链中所有变量对象的持久引用。这就是它用来查找它关闭的变量的用途。这很重要,因为闭包不仅对它实际使用的变量有持久的引用,而且对它定义的范围内的所有变量都有持久的引用,无论它是否使用它们,这可能对这些变量的生命周期有影响。

答案 1 :(得分:1)

一个很好的解释,但简单的答案是“a”变量未在内部函数内声明。因此,它成为超越外部范围值的全球范围。

a =“undefined”; //全局范围

var = 1; //相对于其范围