6

我遇到了一个非常奇怪的(对我来说)var关键字问题。我已将它缩减为一个相当小的测试用例,并发现它在 Node.js(因此是 V8 和 Chrome)、Safari 4 的检查器(因此是 Nitro)和 FireBug(显然是 SpiderMonkey)中都有展示。我最初是在准备一份错误报告,但由于它的展示如此广泛,我将假设我完全误解了 JavaScript 应该如何界定和查找变量。

测试用例非常小,在 GitHub 上:http: //gist.github.com/260067。第一个示例和第二个示例之间的唯一区别是包含var关键字。

这里也是一个类似的测试用例,它以不同的方式展示了相同的“问题”:https ://gist.github.com/698b977ee0de2f0ee54a

编辑:为了排除任何试图解释级联作用域如何工作的答案,我对此非常熟悉。我的问题是我不明白为什么以下代码“有效”(因为它alert()是“外部”,然后是“内部”,然后是“外部”):

(function(){
  var foo = 'outer';
  alert("Outer `foo`: " + foo);

  (function(){
    foo = 'inner';
    alert("Inner `foo`: " + foo);

    var foo;
  })();

  alert("Outer `foo`: " + foo);
})();

var foo;发生在与重新分配完全无关的位置foo;那么为什么它会以非常重要的方式影响这项任务呢?

4

3 回答 3

14

问题是,与其他语言不同,JavaScript 在函数的开头创建所有变量。这意味着代码:

(function(){
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        var myVar = 5;
    }
})();

实际上被编译并解释为

(function(){
    var myVar;
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        myVar = 5;
    }
})();

要创建一个变量并使其仅在 if 或循环块中可用,您必须使用let,这是一个新的 JavaScript 功能。我不确定有多少浏览器实现了它(如果你使用 Firefox 3.5 会实现<script type="text/javascript;version=1.7">)。

(function(){
    if(myVar == undefined){
        alert(myVar);
    }
    if(myVar == undefined){
        let myVar = 5;
    }
})();
于 2009-12-19T13:44:50.397 回答
2

var exports与许多语言中的局部变量不完全一样。它在整个函数中声明exports为局部变量,而不仅仅是封闭块(即使它出现在第一次使用之后),因此具有相同名称的函数参数被隐藏。

编辑:let关键字更常规地工作(它只为包含块声明一个变量),但它并非在所有版本的 JavaScript 中都可用。

于 2009-12-19T13:32:36.563 回答
1

包含 var 意味着 {} 的赋值是对局部变量导出而不是全局变量导出完成的,这意味着它没有效果。

于 2009-12-19T13:30:51.113 回答