如果未在“window”前加上“window.”,则检查属性是否存在会失败

4

我想检查一个属性是否存在于window对象中,所以我做了这个:

这段代码可以工作:

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

输出:

不存在

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

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

令我惊讶的是它没有起作用。我的问题是,如果我不在前面加上window,为什么它不起作用?

1
你在哪里看到未在函数中定义的变量会自动添加到 window 对象中的信息? - Mike
3
如果(typeof foo !== 'undefined'),则表示: - elclanrs
1
@Mike 变量 myName = "Alfredo Osorio"; alert(window.myName); //Alfredo Osorio - Alfredo Osorio
那么你的问题是什么? - fehnomenal
@BenjaminGruenbaum 很好,那应该就是答案了。 - Alfredo Osorio
2个回答

7
第一个版本是属性访问,它无法找到该属性,因此返回undefined。第二个版本尝试访问未定义的变量。
使用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 未定义,则返回 undefined。
所以 window.foo 返回原始语言值 undefined,它是假值。

1
+1 - OP 对于属性访问和标识符解析感到困惑。 - RobG

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 myObj = {prop: 'defined'};

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接