预编译:先扫描代码,语法分析
变量 函数提升
函数声明整体提升:函数不管写到哪里,都会被提到逻辑的最前面。所以不管在哪
里调用,本质上都是在后面调用
变量 声明提升,赋值不提升:把 var a 提升到最前面
test();function test(){console.log(‘a’);}console.log(a); //undefined 不会报错var a = 123;
全局变量 window global
.imply global 暗示全局变量:即任何变量,如果变量未经声明就赋值,此变量就为 全局对象(就是 window)所有
a = 10; ===> windows.a = 10;
function test() {b = 123}test()console.log(b)//123b = 123console.log(b)//123var a = b = 234;function test(){var a = b = 123;}test()
写 test()代表执行 test,赋值是自右向左的,上面先把 123 赋给 b 的时候,b 未经声明,
然后再声明 a,再 b 的值赋给 a,导致 b 未经声明,所以 b 归 window 所有
访问 window.a 是 undefined,访问 window.b 是 123
一切声明的全局变量,全是 window 的属性,window 就是全局的域
定义全局变量,就是把a放入window对象
var a = 123; ===> window.a = 123;
预编译过程
函数预编译
预编译发生在函数执行的前一刻
function fn(a) {console.log(a) //function() {}var a = 123console.log(a) //123function a() {}console.log(a) //123var b = function() {}console.log(b) //function () {}function d() {}}fn(1)
- 创建 AO 对象 Activation Object(执行期上下文,作用是理解的作用域,函数产生 的执行空间库)
找形参和变量声明,将变量和形参名作为 AO 属性名,值为 undefined
AO{a : undefined,b : undefined}
将实参值和形参统一(把实参值传到形参里)
AO{a : 1,b : undefined}
在函数体里面找函数声明,提升函数声明并将函数体赋予函数名,function a () {}和 function d () {}都是函数声明,但是 var b = function (){}不是声明而是函数表达式所以不提升,a函数提升覆盖了形参的值
AO{a : function a() {},b : undefined,d : function d() {}}
执行第一行 console.log(a);时,用的是
AO{a : function a() {},b : undefined,d : function d() {}}
执行 var a =123;改变的是
AO{a : 123,b : undefined,d : function d() {}}
在 b = function (){}时
AO{a : 123,b : function () {},d : function d() {}}
function test() {var a = 123function a() {}console.log(a) //123}test()AO{a : undefined}AO{a : function a() {}}//-----------预编译结束var a = 123AO{a : 123}function a() {} //什么都不做,因为已经做了
全局预编译
- 生成了一个 GO 的对象 Global Object(window 就是 GO)
- 找形参和变量声明,将变量和形参名作为 GO 属性名,值为 undefined
- 在函数体里面找函数声明,值赋予函数体,没有就新增属性
console.log(a) //function a() {}var a = 123console.log(a) //123function a() {}
预编译例子
先进行GO,再进行AO




