1

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

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

这是我得到的结果:

  • Chrome 控制台 - [对象对象]
  • 萤火虫 - 未定义
  • Safari 控制台 - 未定义
  • Jsfiddle - 1

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

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

4

1 回答 1

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代码的一部分被提升到执行代码之上,因此var a在全局范围内总是被执行,所以总是有("a" in window). 因此a = 1,在全局范围内运行时永远不会执行,并且alert(a)无论 global 的值是什么,都会简单地输出a。如果它以前有一个定义的值,那就是你将看到的。如果它以前没有定义的值,那么它只会发出警报undefined,因为(认为它存在)它没有被分配一个值。

如果此代码在本地范围内运行,那么alert(a)将始终看到. 因此,如果没有 global ,您将看到该值,因为 then将在 local 上执行。或者,如果有一个 global ,那么永远不会执行,因此本地定义的将永远是,这就是警报将显示的内容。aalert(a)1aa = 1aaa = 1aundefined

于 2013-11-10T05:26:49.960 回答