3

我有一个 Javascript 主文件,它被一个立即调用的闭包包围(以免污染“全局”:

(function () {
"use strict";
   var closureVariable = [];
...
}());

从函数头中删除变量时,我犯了一个简单的、令人头疼的编码错误,以至于我的代码使用逗号而不是分号:

function fred () {
    var i,

    closureVariable = [1,2,3,4];
    confused();
}
function confused () {
    console.log(closureVariable);     // Prints '[]'
}

当然,“var i”行上缺少的分号是问题所在。但是我认为应该发生的行为是我现在本地定义的变量 'closureVariable' 应该已经隐藏了更高级别的范围定义,并且我的本地定义变量的值应该可以用于范围链中较低的函数(也就是说,函数'confused'应该打印出'[1,2,3,4]';

我在这里对 Javascript 范围链有什么不了解的地方?

4

3 回答 3

3
var i,

    closureVariable = [1,2,3,4];

使两个新变量在fred函数和此范围内定义的函数中可用。

这些变量与范围外定义的任何变量完全不同fred,即使它们碰巧具有相同的名称。

在这里,阴影意味着您的变量命名"closureVariable"阻止对外部范围内具有相同名称的变量的任何直接访问。

于 2014-02-25T14:58:07.267 回答
3

您所期望的称为动态范围。这是一种有效的语言设计选择,尽管今天被广泛认为是次要的。这不是 Javascript 所做的。像许多流行语言一样,Javascript 使用词法作用域。这意味着confused' 范围不被视为fred' 的子范围,因为它的定义不在 的定义内fredfred调用的事实confused没有任何效果。

于 2014-02-25T14:59:02.777 回答
1

当您通过省略分号重新定义closureVariable 时,它​​仅在fred 函数的上下文中重新定义。混淆函数存在于您的闭包的上下文中,因此它仍然可以看到原始的闭包变量。如果您在 fred 函数中定义了混淆函数,它将看到新的closureVariable 并打印 [1,2,3,4]

(function () {
  "use strict";
  var closureVariable = [];
  function fred () {
   var i,

   closureVariable = [1,2,3,4];

   function confused () {
      console.log(closureVariable);     
   }

   confused();  // print [1,2,3,4]
  }
 })();

或者,如果您想从 fred() 外部调用混淆

(function () {
  "use strict";
  var closureVariable = [];
  var confused;

  function fred () {
   var i,

   closureVariable = [1,2,3,4];

   confused = function () {
      console.log(closureVariable);     
   }  
  }

  confused();  // print [1,2,3,4]
 })();
于 2014-02-25T15:00:31.620 回答