Javascript是弱类型语言,相对于一些强类型语言,比如Java、C\C++..., 它本身也有类似于编译的预编译行为,它是解释性语言,它的预编译就是发生在函数执行前一刻。这里的函数不单单是function,<script><script/>代码块也算是函数。今天在这里结合大神们博文,就我自己,作以下总结。
先来看下如下代码:
function f1(a){
alert(a);
var a = 111;
alert(a);
function a(){}
alert(a);
var b = function(){}
alert(b);
function d(){}
}
f1(1);
这里弹出的结果依次function a(){}、111、111、function(){},为什么是这样的结果呢?
其实执行函数前的预编译有以下四部曲:
1.创建AO对象(activation object);
2.找形参和变量声明,将变量和形参作为AO对象属性名,值为undefined;
3.将实参值与形参统一;
4.在函数体中找函数声明,值赋为函数体(注:赋值函数式不是函数声明);
上面提到<script><script/>也可看做一个函数,那么它执行前同样进行预编译,与执行函数前预编译四部曲步骤差不多,但它没有形参和实参,就少了一些步骤,但也有不同之处,就是它此时创建不是AO对象了,具体如下:
1.创建GO对象(global object)即window;
2.查找全局变量,将变量名作为window的属性,赋值为undefined(注:未声明就赋值的变量,即隐式变量,也是全局变量);
3.在<script><script/>内查找函数声明,函数名作为全局对象的属性,值为函数引用;
当变量名与函数名相同时,AO或GO内只建一个属性名;
预编译完在之后,就要执行函数了:
function f1(a){
alert(a);//AO{
//a:undefined->1->function a(){},
//b:undefined,
//d:function d(){}
//}
var a = 111;//AO中a:111
alert(a);//
function a(){}
alert(a);//a:111
var b = function(){}//AO中b:function(){}
alert(b);
function d(){}
}
f1(1);
需要注意的是在预编译中,是先创建GO对象,再创AO对象,当执行代码时,AO、GO都有同一属性名时,要看执行代码的作用域,是全局就使用GO,是局部就使用AO,若AO内没有,而又是局部域,就可向GO对应的值。