预编译
JavaScript是单线程+解释型语言
// 预编译:输出a
// 函数声明整体提升
test();
function test(){
console.log('a');
}
// 预编译:输出undefined
// 变量声明提升
console.log(a);
var a = "123";
- imply global
暗示全局变量:即任何变量,如果有变量未声明就赋值,此变量就为全局对象所有。
全局对象是window,可以添加属性。
例如:
a = 123; // window的属性
console.log(a);
var a = b = 123;
第三行语句的执行过程:(1)先把123赋值给b;(2)再声明a(3)再把b的值赋给a;
b是window的属性
2. 一切声明了的全局变量,全是window的属性。
var a = 123;
console.log(window.a);
window就是全局的域
函数的预编译
function fn(a){
console.log(a);
var a = 123;
console.log(a);
function a(){}
console.log(a);
var b = function(){}
console.log(b);
function d(){}
}
fn(1);
// 预编译发生在函数执行的前一刻
预编译四部曲(以上述程序为例):
- 创建AO对象
AO{
}
- 找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
AO{
// a是形参a,不是变量a
a:undefined,
b:undefined
}
- 将实参值和形参统一
AO{
// a是形参a,不是变量a
a:1,
b:undefined
}
- 在函数体里面找函数声明,值赋予函数体
AO{
// a是函数声明a,不是形参a,也不是变量声明a
a:function a(){},
b:function(){},
d:function d(){}
}
以上程序的执行过程为:
- 第二行console.log(a);输出的是预编译之后AO里的a,也就是function a(){}
- 程序执行到第四行console.log(a);时,预编译过程没有编译第三行代码中的变量声明a,此时存入AO对象
AO{
// a是变量声明a
a:123,
b:function(){},
d:function d(){}
}
因此该行输出的是123
- 第六行console.log(a);执行时,由于第五行代码已经预编译过,因此此时AO对象中的a仍然是123
- 第八行console.log(b);执行时,第七行的代码已经预编译过,因此输出AO对象中的b,即function(){}
示例2:
function test(a, b){
console.log(a); // 1
c = 0;
var c;
a = 3;
b = 2;
console.log(b); // 2
function b(){}
function d(){}
console.log(b); //2
}
test(1);
示例3:
function test(a, b){
console.log(a); // function a(){}
console.log(b); // undefined
var b = 234; //未预编译
console.log(b); // 234
a = 123;
console.log(a); // 123
function a(){} // 函数声明可以提升
var a;
var b = function(){} // 函数表达式不能提升
console.log(a); // 123
console.log(b); // function(){}
}
test(1);
全局预编译
- 生成GO对象:global object
- 找变量声明,将变量作为AO属性名,值为undefined
- 找函数声明,值赋予函数体
未经声明就赋值的对象都是window的属性
示例4:
// GO{
// test:123
// }
console.log(test); // function test(test){...}
function test(test){
console.log(test); // function test(){}
var test = 234; // 未提升
console.log(test); // 234
function test(){}
}
// AO{
// test:234
// }
test(1);
var test = 123;
示例五:
// GO{
// a:undefined,
// tets:function test(){...},
// c:234
// }
function test(){
console.log(b); // undefined
if(a){ // 预编译不管if等语句,直接看块内语句是不是需要预编译
var b = 100;
}
console.log(b); // undefined
c = 234;
console.log(c); // 234
}
var a;
// AO{
// b:10,
// }
test();
a = 10;
console.log(c); // 234
知识和示例来源:渡一