【问题标题】:Why does this closure-scoped variable lose its value?为什么这个闭包范围的变量会失去它的价值?
【发布时间】:2011-04-21 05:57:35
【问题描述】:

我在这里看到了这个 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/

【问题讨论】:

    标签: javascript closures


    【解决方案1】:

    之所以会这样,是因为这个功能:

    (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 语句时,它会被作为简单的赋值语句处理。

    变量对象也是使闭包起作用的东西,顺便说一句。 More here,但基本上,当一个函数被创建时,它会在此时获得对作用域链中所有 变量对象 的持久引用。这就是它用来查找它关闭的变量的方法。这很重要,因为闭包不仅具有对其实际使用的变量的持久引用,而且对定义它的范围内的所有变量(无论是否使用它们)都有持久引用,这可能对这些变量的生命周期产生影响.

    【讨论】:

    • 很好的解释。另一个明确的情况是,如果我们将 (function(){a=b; var b=3;})() 作为内部函数。那会和(function(){var b; a=b; b=3;})() 一样,对吧?
    • @Sam:(谢谢。)完美,是的。就是这样。也是很好的例子。
    • Wait..then这也意味着如果你有一个var声明下面一个函数,然后返回那个函数,闭包会包含那个var?跨度>
    • @Sam:是的,有两个原因:1. 因为var 在任何分步代码之前处理,2. 因为闭包引用变量对象,而不是单个变量。跨度>
    【解决方案2】:

    一个很好的解释,但简单的答案是“a”变量没有在内部函数内部声明。因此,它变成了全局作用域,超过了外部作用域的值。

    a = "未定义"; // 全局作用域

    var = 1; // 相对于它的作用域

    【讨论】:

      猜你喜欢
      • 2012-01-24
      • 2011-11-24
      • 2021-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多