JS:预编译
我们知道在表示符提升问题上是声明的变量先提升,函数整体后提升;
我们把变量分为局部变量和全局变量,其区别是作用域不同,局部变量在函数内部的作用域内,但有时我们也会遇到函数内部的变量是全局变量,因为他未在内部被声明;
在JS中,系统首先会检测我们的语法错误,再进行预编译,最后逐条执行;
我们所学的表示提升就是在预编译这个环节进行的;
函数预编译的流程:
1、在函数被调用之后,代码执行之前
2、函数每次调用都会生成一个对象:执行期上下文对象
3、给AO对象添加成员:函数内部的局部变量和形参变量名,作为AO对象的属性名
4、把传入的实参赋值给AO对象的属性
5、局部函数声明、赋值,把局部函数的名字让AO对象也有一个一样的成员名,把函数体赋值给这个属性
6、运行代码,预编译过的不再运行
全局预编译的流程:
1、生成一个对象Global Object (GO)
2、把所有的全局变量 设置为GO的属性名
3、把所有函数名 作为GO的成员名,把函数体赋值给这个成员
4、执行代码
对比以下三个代码:
console.log(a);
a= 1;
打印结果:报错 a未定义
console.log(a) ; var a = 1 ; //提升了变量,值没有提升;
打印结果:undefined
console.log(window.a);
a = 1; //相当于把window.a 赋值为1;
打印结果:undefined
在全局中,a = 1;var a = 1;区别在于没有var 就没有提升变量;
在js环境中运行代码:
GO对象的成员全部浅拷贝给环境对象window
*node.js 环境中没有这一步
拓展知识:
关于访问成员 console.log(a) 访问的是GO对象的成员(作用域链中没有就报错)
console.log(window.a) 不报错 原型链没有返回undefined