js运行三个阶段
- 语法分析
- 预编译
- 解释执行
语法分析就是JS引擎去检查你的代码是否有语法错误,解释执行就是执行你的代码。最重要最需要理解的就是第二个环节预编译,简单理解就是在内存中开辟一些空间,存放一些变量与函数 。
预编译可分为全局预编译和局部预编译。
- 在js脚本加载之后,会先通篇检查是否存在低级错误;
- 在语法检测完之后,便进行全局预编译;
- 在全局预编译之后,就解释一行,执行一行;
- 当执行到函数调用那一行前一刻,会先进行函数预编译,再往下执行。
全局预编译的3个步骤
- 创建GO对象(Global Object)全局对象,即window对象。
- 找变量声明,将变量名作为GO属性名,值为undefined
-
局部预编译的4个步骤
创建AO对象(Activation Object)执行期上下文。
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
- 将实参值和形参统一。
- 在函数体里面找函数声明,值赋予函数体。
GO对象是全局预编译,所以它优先于AO对象所创建和执行
案例分析
<script>
var a = 10;
console.log(a);
function foo(a) {
console.log(a);
var a = 100;
console.log(a);
function a() {}
console.log(a);
var b = function(){};
console.log(b);
function d() {}
}
var c = function (){
console.log("匿名函数C");
};
console.log(c);
foo(20);
</script>
全局预编译
GO/window = {
a: undefined,
c: undefined,
foo: function(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
}
}
解释执行代码
直到执行调用函数foo(20)语句
GO/window = {
a: 10,
c: function (){
console.log("I at C function");
}
test: function(a) {
console.log(a);
var a = 123;
console.log(a);
function a() {}
console.log(a);
var b = function() {}
console.log(b);
function d() {}
}
}
局部预编译
调用函数foo(20)前发生
// 局部预编译前两步:
AO = {
a:undefined,
b:undefined,
}
// 局部预编译第三步:
AO = {
a:20,
b:undefined,
}
// 局部预编译第四步:
AO = {
a:function a() {},
b:undefined
d:function d() {}
}
预编译总结:
- 函数声明整体提升-(具体点说,无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)
- 变量 声明提升-(具体点说,无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是undefined)