在调用一个JavaScript方法之前,都会对方法进行一次词法分析的过程,主要分析如下内容:
第一步: 先分析参数
第二布: 再分析变量声明
第三步: 最后分析函数声明
现提供一个具体例子代码,并解析分析步骤:
function t(age){
var e = 2;
var age = 10;
function age() {
}
}
t(2);
具体步骤:
1、 函数在运行前的瞬间,会生成一个活动对象(Active Object),简称AO。
2、分析函数的参数,并将其作为AO的属性,默认值全部为underfined,如:
AO{age=underfined}。
3、分析函数接受到的参数,并将参数内容设置到对象的AO属性上,如:
AO{age=2}
4、分析函数内部的变量声明,如var age,如果AO上还没有age属性,则添加AO属性,值是undefined;如果AO上已经有age属性则不做任何影响。如:
AO{age=2, e=undefined}
5、分析函数声明,并将函数赋给成AO的属性。
AO{age= function(){}, e=undefined}
注意:由于age属性已经存在,则被覆盖掉了。
根据以上步骤再来分析一个比较复杂的函数:
function a(b){
alert(b);
function b() {
alert(b);
}
b();
}
a(1);
1、分析函数的参数,结果为:AO{b=undefined}
2、分析函数的接受到的参数,结果为:AO{b=1}
3、分析函数内部的变量声明,这里没有声明内部变量。
4、分析函数声明,结果为:AO{b=function(){alert(b)}}
词法分析完成之后将根据这个AO对象来运行,此时2个alert(b)都将会打印b函数。
根据这个词法的分析过程,可以清楚的明白JavaScript的运行原理,对这种奇葩的结果就自然而然的明白了。
注意点:
1、在词法分析过程中,分析函数声明的时候如果遇到如下情况需要注意。
function a(b){
alert(b);
b = function() {
alert(b);
}
b();
}
a(1);
这里的b= function(){} 并不是函数声明,而是函数表达式的赋值,在词法分析阶段不会使b=function(){},而是在运行阶段赋值。
因此这里的结果跟上面就不一样了,大家可以自行查看。