预编译
首先是全局预编译 三步
第1步. 创建一个GO对象 Global Object
第2步. 将var关键字声明的变量当作GO对象的属性,赋值为undefined,有重名的直接覆盖
第3步. 将function关键字声明函数 当作GO对象的属性,值为函数体,重名直接覆盖。
console.log(i);
var i = 30;
console.log(i);
function i() { }
var i = function () { }
console.log(i);
如何分析这个全局预编译
1.首先创建GO对象
2.找到变量声明,并赋值为undefined
GO{
i:undefined
}
3.找到函数声明,并赋值对应的变量
GO{
i:function i(){}
}
4.然后执行代码
{
i:function(){}
}
第一个打印的i,经过预编译现在 i 等于 function i( ){ }
第三行,i=10, 现在GO对象的i=30。
第二个打印的i,经过改变打印出 30。
第五行,i = function( ){ },现在GO对象的i=function( ){ }。
第三个打印的i,经过改变变成 function( ){ };
函数预编译
函数执行的前一刻开始
第1步. 创建一个AO对象 Activation Object 执行期上下文对象
第2步. 函数的形参,成为AO对象的属性,值为实参的值,若未传值,值为undefined
第3步. 将var关键字声明的变量,成为AO对象的属性,值为undefined,遇到已经存在的,不做任何变化
第4步. 将function声明的函数 成为AO对象的属性 值为函数体,重名直接覆盖
(这里多了个函数的形参的影响;还有就是这里的var,遇到已经遇到已经存在的,不会做任何改变)
function a(x) {
// function x(){}
console.log(x);
var x = 123;
// 123
console.log(x);
function x() { }
// 123
console.log(x);
// undefined→变为function(){}
var b = function () { }
console.log(b)
}
a(1)
首先分步骤来分析
1.创建AO对象
2.给函数的变量传入形参
AO{
x:1;
b:undefined;
}
3.var a 已经遇到存在的形参值1;所以不做任何改变
AO{
}
4.找函数声明,并赋值对应的AO对象.
AO{
x: 1; —> function x(){};
b:undefined;
}
5.执行代码
第一个x在预编译的是时候已经被函数覆盖
第二个x,值为x=123, 成为x的值
第三个x同样是123,因为函数预编译已经提前,不受影响
第四个b的值,b=function(){},给了b的。所以打印出来的是function(){}。
按照步骤来,就能分析这个预编译的问题。