JS预编译
- 作用域的创建阶段—预编译的阶段
- (局部)预编译时做了那些事情:
- 创建AO对象 供js引擎自己去访问
- 找形参和变量的声明,作为ao对象的属性名,值是undefined
- 实参和形参相统一
- 找函数声明,会覆盖变量的声明
// 函数
function fn(a){
console.log(a); //function a(){}
// 变量声明+变量赋值(只提升变量声明,不提升变量赋值)
var a = 123;
console.log(a); //123
// 函数声明
function a(){};
console.log(a); //123
// 函数表达式 不是函数声明所以无需编译
var b = function x(){};
//function b(){} //这种情况就是b:undefined function b(){}
console.log(b);//function(){}
// 函数
function d(){};
}
//调用函数
fn(1);
//分析过程
// AO{
// a:undefined 1 function a(){}
// b:undefined
// d:function d(){}
// }
- 全局预编译的3个步骤:
- 创建GO对象(Global Object)全局对象。
- 找变量声明,将变量名作为GO属性名,值为undefined
- 查找函数声明,作为GO属性,值赋予函数体
console.log(global)//function global() {}
global = 100;
function test(){
console.log(global); // 根据AO对象中的数据(预编译就已经创建了,所以不会在到GO里找):undefined
var global = 200; // 执行到这时,200覆盖了undefined
console.log(global); // 200
var global = 300;
}
console.log(global)//100
function global() {}
console.log(global)//100
test();
var global;
//分析过程
//先GO,再AO
// GO{
// global:undefined function global() {}
// test:function test() {}
// }
// AO{
// global:undefined
// }
补充
关于GO对象和AO对象,它们俩是一个种链式关系,就拿上面的这个例子来说吧,如果在函数体的内部没有定义global变量,这也意味着AO对象中将有这个global这个属性。那如果没有会怎么办?它会去GO对象中寻找,说白了也就是一种就近原则。
https://zhuanlan.zhihu.com/p/50236805