在JS中预编译就是发生在函数执行之前发生的事情。
上代码:
var x = 1, y = z = 0;
function add(n) {
return n = n+1;
}
y = add(x);
function add(n) {
return n = n + 3;
}
z = add(x);
console.log(x,y,z)
这是一段全局预编译的面试题接下来我们一步一步的分析;
第一步先在执行代码之前进行全局预编译 创建一个GO对象
GO = {
}
第二步找到声明的变量作为属性名,值赋为undefined:
GO{
x : undefined
y : undefined
z : undefined
}
第三步找到函数,将函数名作为属性名,值赋为函数体
GO{
x : undefined
y : undefined
z : undefined
add : function add(n) {
return n = n+1;
}
}
//因为有相同的函数名,函数提前的原因后面的add()会直接覆盖掉前面的add()所以AO对象中只有一个函数
然后进行逐行解释
第一行给x,y,z进行赋值后:
GO{
x : 1
y : 0
z : 0
add : function add(n) {
return n = n+1;
}
}
第二步找到 y = add(x); 将x值为实参传入add函数中将add函数的返回值赋给变量y
GO{
x : 1
y : 1+3
z : 0
add : function add(n) {
return n = 3+1;
}
}
第三步找到 z = add(x); 将x值为实参传入add函数中将add函数的返回值赋给变量y
GO{
x : 1
y : 1+3
z : 1+3
add : function add(n) {
return n = 3+1;
}
}
最后console.log(x,y,z) 输出的内容为: x = 1,y = 4 , z = 4;
而在函数运行之前也会创建一个局部对象 AO = {}
函数的预编译分为4步
1:声明一个AO对象
2:将形参和实参进行赋值统一 其中形参作为AO对象的属性名,实参作为AO对象的属性值
3:找到声明变量,将变量名作为AO对象的属性名,值赋为undefined ,如果变量名与形参冲突则AO对象不做改变
4:找到函数,将函数名作为AO对象的属性名,函数体作为AO对象的属性值,如果函数名与声明的变量或者形参相同,则将覆盖之前的属性。