先来看一段代码:
以下是代码片段:
alert("a" in window); /*true - 1*/
if( false ){
var a = 1;
}
alert("b" in window); /*false - 2*/
if( false ){
b = 1;
}
alert("b" in window); /*false - 3*/
alert("c" in window); /*false - 4*/
if( true ){
c = 1;
}
alert("c" in window); /*true - 5*/
以上代码片段是在全局作用域下定义的,对于第一个例子,Javascript在预解析的时候已经将变量a的声明添加到了活动对象中(具体可参考Javascript的“预解析),于是在运行时 “a” in window 为true。
然后第二个例子的结果是false,也就是说变量”b”在预解析的过程中并没有被放置在当前环境的活动对象中,原因在于没有使用var来定义变量”b”。对于使用了var定义的变量,预解析时可以明确的知道这是当前作用域的“本地”变量,因此可以准确无误的将变量添加到活动对象中,而那些没有使用var定义的变量则需要在运行时去处理。示例中的2 - 5句正好验证了没有使用var定义的变量需要在运行时进行处理。
在Answering Baranovskiy’s JavaScript quiz一文中给出的前3个问题均与预解析相关,如下:
以下是代码片段:
if (!("a" in window)) {
var a = 1;
}
alert(a);/*undefined*/
预解析时已经将变量a添加到window上,因此!(”a” in window)为false,导致运行时a没有被赋值,所以a的值为undefined。
以下是代码片段:
var a = 1,
b = function a(x) {
x && a(--x);
};
alert(a);/*1*/
这个在所有浏览器下都输出1,预解析时,第一行定义的变量a被添加到了window对象中,此时它的值为undefined,解析到第二行时,变量b也被添加到window对象中,其值也为undefined。同时,在IE下,后面的函数表达式也会被当做一个函数定义来处理,即相当于
以下是代码片段:
var a = 1;
var b = function (x){
x && a(―x);
};
function a(x) { /*在IE下会被当做函数定义处理*/
x && a(--x);
}
alert(a);/*1*/
当解析过程完成后,window对象中的变量a的引用是一个函数定义(仅限于IE),而到了运行时给变量赋值的时候,执行了以下3个动作:
1. 给变量a赋值为1(覆盖了原先a上面的函数定义)
2. 给变量b赋值为函数表达式
3. alert(a)
因此a的值为1。
以下是代码片段:
function a(x) {
return x * 2;
}
var a;
alert(a);/*函数代码*/
预解析时,完成了函数a的定义,即在window对象上添加变量a,并赋值为函数定义。之后遇到”var a;”,由于当前作用域已经有变量a,因此不需要做什么工作。在运行时,由于并没有给变量a赋值,因此原来的函数定义并没有覆盖,因此最终变量a是一个函数。如果将”var a;”改为”var a=1;”,则最终a的值为1。