一、案例引入
var global = 100
function fn() {
console.log(global)
}
fn()
在面对HR,面试官问你代码执行结果时,看到这个代码,你可能脱口而出 '100'!紧接着问到原因时,也许你同样能快速答出内部代码找不到此变量,往外部代码找。当然是对的,但在面试官眼中可能并不太满意,换句话说,不够底层!
二、详谈预编译
何为预编译? 代码在执行前进行编译操作,用于确定代码之间的各种关联!
Javascript的预编译,仅在代码执行前的短时间内完成。而预编译分为两种。为全局预编译和函数体内的预编译。而整个代码的执行步骤为: 全局代码预编译->全局代码执行->函数体内预编译->函数体内代码执行
接下来我们将根据一份看似复杂的代码来人脑执行(可以偷偷用电脑跑)
三、代码引入及照着步骤跑!
function test(a, b) {
console.log(a);//1
c = 0
var c;
a = 3
b = 2
console.log(b);//2
function b() {}
console.log(b);//2
}
test(1)
}
全局预编译三小点
1 创建GO对象
GO {
//为空
}
2 找变量声明,将变量名作为GO属性名,值为undefined
GO {
//全局无变量声明,依旧空
}
3 在全局找函数声明,将函数名作为GO的属性名,值为该函数体
GO {
test: function(){}
}
全局代码执行
执行test(1) (此时注意,函数只有调用才被执行,故直接到test(1))
现在可犯了难,test(1)是什么呢?此时我们想起刚刚的步骤,回到函数的预编译!!!
函数体的预编译四小点
1创建一个AO对象
AO {
为空
}
2找形参和变量声明,将形参和变量名作为AO属性名,值为undefined
AO {
a: undefined
b: undefined
c: undefined
}
3形参和实参统一
AO {
a: undefined->1
b: undefined
c: undefined->0
}
4在函数体内找函数声明,将函数名作为AO属性名,值为函数体
AO {
a: undefined->1
b: undefined->function b(){}
c: undefined->0
}
函数体代码执行
AO {
a: undefined->1->3
b: undefined->function b(){}->2
c: undefined->0
}
四、总结
完整地按照此步骤进行:全局代码预编译->全局代码执行->函数体内预编译->函数体内代码执行,相信面试官对你会刮目相看噢 另外第一次创作码字不易,大家点点关注和点赞!!!谢谢啦
一些概念和可能的疑难解答
-
AO对象:Activation object活动对象
-
GO对象:Global object全局对象
-
c = 0 不是声明变量语句,只是赋值
-
函数只有被调用才会执行,否则往下走就是,所以此代码全局执行时直接到test(1)
-
此代码的执行结果为 1 2 2;至于为什么a不是3,那是console.log(a)在a变为3的时候已经执行啦
-
但其实a b c的值正如最后一段AO所示变成了3 2 0;不信的话执行下面的代码
function test(a, b) {
console.log(a);//1
c = 0
var c;
a = 3
b = 2
console.log(b);//2
function b() {}
console.log(b);//2
console.log(a)
console.log(b)
console.log(c)
}
test(1)