关于变量和属性在判定存在与否的一点细节

问题开始于跨浏览器事件绑定函数中关于不同浏览器分支的判定
比如判定浏览器是否支持DOM2事件模型if(window.addEventListener)…
当浏览器不支持这一属性的时候,widow.addEventListener == “undefined”,从而隐式转化为false使判断语句生效。

看到这里的时候,我想起了前几天看的有关判定一个变量是否存在时,如果不使用if(typeof a == “undefined”) 这样的形式去判定,而使用 if(a),当变量不存在时,浏览器会抛出错误。(A ReferenceError)

那判定一个变量和一个属性又有什么区别呢。
奇怪的是,我们知道,当我们定义一个变量时,这一变量实际是定义在全局变量(在浏览器中是window)中的一个属性。即:

var a;
a == window.a;

所以当我们去判定a变量是否存在时,使用if(window.a)这样的形式是会正常工作而不会抛出错误的。

这篇文章里就这个问题有详细的解释http://javascriptweblog.wordpress.com/2010/08/16/understanding-undefined-and-preventing-referenceerrors/
大致的意思是
In ECMA terms, a Reference consists of a base value and a reference name.
在ECMA标准里面(严格模式),一个Reference包括一个基准值(base value)和一个引用名(reference name)。

If the Reference is a property, the base value and the reference name sit either side of the dot.
如果一个Reference是一个属性,基准值和引用名分别位于.的左右,比如

window.foo; //base value = window, reference name = foo;
a.b; //base value = a, reference name = b;
myObj['create']; // base value = myObj, reference name = 'create';
//Safari, Chrome, IE8+ only
Object.defineProperty(window,"foo", {value: "hello"}); //base value = window, reference name = foo;

For variable References, the base value is the VariableObject of the current execution context. The VariableObject of the global context is the global object itself (window in a browser)). Each functional context has an abstract VariableObject known as the ActivationObject.
对于变量Reference来说,基准值是当前执行环境的全局变量,在浏览器中是window,在每个函数执行环境中是一个叫做ActivationObject的抽象变量对象。比如:

var foo; //base value = window, reference name = foo
function a() {
    var b; base value = <code>ActivationObject</code>, reference name = b
}

Therefore a property reference is unresolvable if the value before the dot is undefined.
因此如果.前的值未定义的话,一个property reference被认为是unresolvable的,即会抛出错误。

所以我们可以放心使用if(window.addEventListener)这样的形式去判定浏览器的兼容性,而不用担心抛出错误。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>