1.JS运行分为三步
- 语法分析
- 预编译
- 解释执行
2.预编译时要做的事
创建对象,声明函数和变量,但是没有初始化行为(赋值)
<script>
var a = 1;
function test(a) {
console.log(a);
var b = 123;
function funA() {}
var funB = function() {}
}
var funC = function (){}
test(2);
</script>
对于以上例子,预编译时执行顺序如下:
1.创建外层的全局对象(如window对象)
obj = {}
2.查找变量与函数的声明
obj={
a: undefined,
test: undefined,
funC: undefined
}
解释执行时:变量和函数体赋值
obj = {
a: 1,
test: function(a) {
console.log(a);
var b = 123;
function funA() {}
var funB = function() {}
},
funC: function (){}
}
执行函数test之前的预编译顺序:
1.创建AO活动对象(Active Object)
2.函数与变量声明
AO = {
a:undefined, //形参
b:undefined,
funA: undefined,
funB: undefined
}
3.实参赋值给形参
AO = {
a:2, //实参
b:undefined,
funA: undefined,
funB: undefined
}
解释执行时:赋值
AO = {
a:2,
b:123,
funA: function (){},
funB: function (){}
3.注意事项
- 预编译不初始化变量,只有在解释执行阶段才会进行初始化
- 匿名函数不参与预编译
- 函数声明整体提升(无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)
- var声明的变量被提升,let和const声明的变量不会被提升
- 一切声明的全局变量,全是window的属性