为什么当我尝试访问不存在的变量时,javascript抛出异常但是当我尝试访问对象中不存在的属性时,javascript会返回undefined
值?
例如,此案例返回undefined
值:
function Foo(){
console.log(this.bar);
}
Foo();
但是,在另一个例子中,javascript抛出异常:
function Foo(){
console.log(bar);
}
Foo();
ReferenceError:未定义bar
答案 0 :(得分:3)
由于JavaScript中的每个对象都是字典,也称为其他语言的映射,this.bar
等同于this['bar']
,即通过键访问值。在大多数语言中,例如在Java中,返回null
,NULL
或undefined
允许您有条件地创建此插槽(如果它尚不存在),而不处理异常或任何其他副作用。
但是,如果只编写console.log(bar)
而未指定bar
的上下文,则无法创建合理的模式,其中返回undefined
将具有语义含义。有多个上下文,其中一些是动态的,如浏览器中的全局上下文window
,其中bar
可能在运行时定义,因此它不能是编译时错误(与Java或C ++)。因此,当无法解析变量名时,抛出运行时异常。
答案 1 :(得分:1)
属性解析与标识符解析根本不同。简单的答案是,ECMA-262指定尝试读取不存在的变量将引发错误,而尝试读取不存在的对象属性则不会,它只返回特殊的undefined值。
为了解决这个问题,你需要先咨询开发JavaScript的Brendan Eich,ECMA-262就是基于它的。然而,一个合理的猜测是Brendan希望将JavaScript变成一种松散打字的简单语言,而不是像以下那样做:
if ( 'foo' in obj) {
/* do something with obj.foo */
}
每当您第一次想要访问某个属性时,该语言就可以容忍访问未定义属性的尝试。
另一方面,对变量应用相同的方法会产生比解决更多的问题,因此可以使用typeof
来查看是否存在标识符:
if (typeof foo != 'undefined') {
/* ok to use foo */
}
否则,属性和标识符解析非常相似。不同之处在于,第一个从对象开始,沿着一串内部[[Prototype]]
对象(继承链),最后到达null
对象,而变量分辨率从局部变量对象沿着一个字符串进行属于外部上下文(作用域链)的类似对象的全局对象。
答案 2 :(得分:0)
function Foo(){
console.log(window.bar);
}
Foo();
也会给你undefined
。
this.bar
表示this["bar"]