2

为什么当我尝试访问不存在的变量时,javascript 会抛出异常,但是当我尝试访问对象中不存在的属性时,javascript 会返回一个undefined值?

例如,这种情况下返回一个undefined值:

function Foo(){
    console.log(this.bar);
}

Foo();

但是,在另一个示例中,javascript 抛出异常:

function Foo(){
    console.log(bar);
}

Foo();

ReferenceError: bar 未定义

4

3 回答 3

3

由于 JavaScript 中的每个对象都是一个字典,在其他语言中也称为 map,this.bar相当于this['bar'],即通过键访问值。在大多数语言中,例如在 Java 中,返回nullNULLundefined允许您有条件地创建此插槽(如果它尚不存在),而无需处理异常或任何其他副作用。

但是,如果您只是编写console.log(bar)而不为 指定上下文bar,则不可能创建一个合理的模式,其中返回undefined将具有语义含义。有多个上下文,其中一些是动态的,例如window浏览器中的全局上下文,其中bar可能是在运行时定义的,因此它不能是编译时错误(与 Java 或 C++ 不同)。因此,当无法解析变量名时会引发运行时异常。

于 2012-09-18T21:37:34.433 回答
1

属性解析与标识符解析根本不同。简单的答案是 ECMA-262 指定尝试读取不存在的变量将引发错误,而尝试读取不存在的对象属性则不会,它只是返回特殊的未定义值。

要了解原因,您需要先询问 Brendan Eich,他首先开发了 ECMA-262 所基于的 JavaScript。然而,一个合理的猜测是,Brendan 想让 JavaScript 成为一种具有松散类型的简单语言,而不是必须执行以下操作:

if ( 'foo' in obj) {
  /* do something with obj.foo */
}

每次您第一次想要访问一个属性时,该语言都允许尝试访问未定义的属性。

另一方面,对变量应用相同的方法会产生比解决更多的问题,因此typeof可以用来查看标识符是否存在:

if (typeof foo != 'undefined') {
  /* ok to use foo */
}

否则,属性和标识符解析非常相似。不同之处在于,首先从对象开始,沿着一串内部[[Prototype]]对象(继承链),最后到null对象,而变量解析从局部变量对象开始,沿着属于外部上下文的一串相似对象(范围链)到全局对象。

于 2012-09-18T23:19:17.900 回答
0
function Foo(){
    console.log(window.bar);
}

Foo();

也会给你undefined

this.bar方法this["bar"]

于 2012-09-18T21:45:20.430 回答