这个JavaScript代码段是怎么回事?

时间:2013-11-10 04:47:30

标签: javascript

来自http://dmitry.baranovskiy.com/post/91403200

if (!("a" in window)) {
    var a = 1;
}
alert(a);

以下是我得到的结果:

  • Chrome控制台 - [对象对象]
  • Firebug - undefined
  • Safari控制台 - 未定义
  • Jsfiddle - 1

发生了什么事?我期望未定义,因为“if”应该返回false(因为窗口中的“a”应该为false,并且!false应该为true,因此变量a永远不会得到值)。我错过了什么?

编辑:好的,我意识到首先执行var语句,并且窗口中的“a”只返回是否存在这样的变量。但是为什么Firebug和jsfiddle会给出不同的答案?

1 个答案:

答案 0 :(得分:2)

这个代码被javascript解释器看作:

var a;
if (!("a" in window)) {
    a = 1;
}
alert(a);

根据全局范围内是否已存在a以及代码是在全局范围内还是在本地范围内运行,您对此代码有四种排列。

如果代码在本地函数范围内运行,那么它基本上如下所示:

function whatever() {
    var a;
    if (!("a" in window)) {
        a = 1;
    }
    alert(a);
}

所以,这是排列:

global a exists already      scope code runs in       value of alert(a)
-----------------------------------------------------------------------
yes, has value of 2          global                   2
yes exists, value undefined  global                   undefined
no                           global                   1
yes, has value of 2          local                    undefined
yes exists, value undefined  local                    undefined
no                           local                    1

因此,您获得的答案的变化是因为此代码运行的范围在每种情况下都不同。

在jsFiddle中,您必须小心左上角的设置。如果设置为onload,则jsFiddle在本地函数范围(onload处理函数)中运行。

这里发生的是,如果此代码正在运行全局范围,那么("a" in window)将始终为真,因为代码的var a部分悬挂在执行代码之上,因此{{1}在全局范围内始终执行,因此总是var a。因此,("a" in window)在全局范围内运行时永远不会执行,a = 1只输出全局alert(a)的值。如果它之前有一个定义的值,那就是你将看到的。如果之前没有定义的值,那么它只会提醒a,因为(认为它存在),它没有被赋值。

如果此代码在本地范围内运行,则undefined将始终在alert(a)中看到本地定义的a。因此,如果没有全局alert(a),您会看到1作为值,因为a将在本地a = 1上执行。或者,如果存在全局a,则a将永远不会执行,因此本地定义的a = 1将始终为a,这就是警报将显示的内容。