迷惑JavaScript`var`关键字的操作

时间:2009-12-19 13:26:34

标签: javascript v8 spidermonkey

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

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

这里也是一个类似的测试案例,它以不同的方式表现出同样的“问题”:https://gist.github.com/698b977ee0de2f0ee54a

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

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

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

    var foo;
  })();

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

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

3 个答案:

答案 0 :(得分: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或loop块中使用它,您必须使用let,这是一个新的JavaScript功能。我不确定有多少浏览器实现它(如果你使用<script type="text/javascript;version=1.7">,Firefox 3.5会这样做。)

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

答案 1 :(得分:2)

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

编辑:let关键字更常规地工作(它仅为包含块声明一个变量),但它并不适用于所有版本的JavaScript。

答案 2 :(得分:1)

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