如对JavaScript的运用总是有些偏差,则应深入了解其中原理。
JavaScript 是单线程,解释性语言。说白了就是从上到下,逐行解释一句,执行一句。
运行步骤:语法分析、预编译、解释执行
预编译常说的两句:
//变量 声明提升
//函数声明整体提升
预编译前奏
一切声明的全局变量,全是window
的属性。(window
就是全局的域)
imply global
暗示全局变量,如果变量未经声明就赋值,此变量就为全局对象所有,就是全局变量。(全局对象即window
)
var a = 1;
function test(){ b = 2; }
test();
console.log(window.a); // 1
console.log(window.b); // 2
预编译
函数体的预编译发生在函数执行的前一刻
四步:
- 创建
AO(Activation Object)
对象 (执行期上下文) - 找形参和变量声明,将形参名和变量声明的名作为AO对象的属性名,值为
undefined
- 将实参值和形参统一
- 在函数体里面找函数声明,将函数声明的函数名作为AO对象的属性名,值为
函数体
例:
function test(a,b){
console.log(a);
console.log(b);
b = 2;
console.log(b);
function b(){}
var a = function(){}
console.log(a);
}
test(1);
预编译过程
预编译第一步:
AO{ }
预编译第二步:
AO{
a : undefined,
b : undefined,
}
预编译第三步:
AO{
a : 1,
b : undefined,
}
预编译第四步:
AO{
a : 1,
b : function b(){},
}
执行的结果:
函数执行到最后AO对象应为:
AO{
a : function (){},
b : 2,
}
全局预编译
预编译不只发生在函数体,还发生在全局,全局预编译步骤:
- 生成一个GO(Global Object)对象,即
window
- 找变量声明,将变量名作为GO属性名,值为
undefined
- 找函数声明,将函数名作为GO属性名,值为
函数体
全局的预编译发生在全局执行之前,所以JavaScript的预编译过程是先生成GO对象,再生成AO
例:
// GO{
// a : undefined,
// test : function test(){...},
// c : 200
// }
function test(){
console.log(b); //undefined
if (a) {
var b = 100;
}
console.log(b); //undefined
c = 300;
console.log(c); //300
}
var a;
test();
// AO{
// b : undefined
// }
执行的结果: