4

我想检查窗口中是否存在属性,所以我这样做了:

此代码有效:

if (window.foo) {
    alert("exists");
}
else {
    alert("doesn't exist");
}

输出

不存在

我认为下一个代码也应该可以工作,因为据我所知,当您定义变量并且您不在函数内部时,它们是作为“窗口”对象的属性创建的,因此这应该是等效的:

if (foo) { //it fails here "foo is not defined"
    alert("exists");
} else {
    alert("doesn't exist");
}

令我惊讶的是,它没有用。我的问题是,如果我不预先添加窗口,为什么它不起作用?

4

2 回答 2

7

第一个版本是属性访问,它找不到属性,所以它返回未定义。第二个是试图访问未定义的变量。

使用 elclanrs 的建议:

if(typeof foo === "undefined"){
    alert("exists");
} else {
    alert("doesn't exist");
}

为什么?

这是因为GetValue语言规范中指定的。

.3. 如果 IsUnresolvableReference(V),则抛出 ReferenceError 异常。

这就是这种情况下发生的if(foo)情况,因为foo之前没有定义。

另一方面,如果它是一个对象,则会发生以下情况:

  1. 设 base 为调用 GetBase(V) 的结果。
  2. 令 O 为 ToObject(base)。
  3. 令 desc 为使用属性名称 P 调用 O 的 [[GetProperty]] 内部方法的结果。
  4. 如果 desc 未定义,则返回未定义。

所以window.foo返回虚假的原始语言值undefined

于 2013-07-03T22:26:04.073 回答
0

Window对象视为一个“巨大的闭包”,它封装了所有其他对象。现在想一想:

var ext = "test";
function myScope() {
    var ext = "foo"; //new variable in myScope's scope
    console.log(ext); //foo
}
function changeExt() {
    ext = "bar";//ext is not defined in this scope, so JS will look in the chain of scopes and set the value to the defined var in the global scope
    console.log(ext);
}
myScope();
console.log(ext); //test
changeExt();
console.log(ext); //ext has been changed by changeExt to bar

为什么会这样?因为通过使用window.property,您试图访问window对象的未定义属性,而不是引用未声明的var。

如果您尝试在不使用var全局闭包中的关键字的情况下做同样的事情,您将得到相同的结果,因为它是作用域链的最后一个。

现在让我们把它想象成一个巨大的物体:

var myObj = {prop: 'defined'};

假设这myObj是“全局对象”,如果您尝试访问propJS 会将您重定向到myObj.prop(或者它会尝试这样做),如果foo未声明属性(例如命名),您将获得您的ReferenceError.

于 2013-07-03T22:28:34.487 回答