三十八.预编译

109 阅读2分钟

js执行步骤

js执行分为三个步骤:

1.语法分析:分析代码的符号和语法是否正确;

2.预编译:隐式操作(全局预编译、函数预编译);

3.执行语句,预编译过的就不在运行。

预编译

函数预编译

函数预编译:在函数调用之后,运行代码之前。预编译时函数每次调用都会生成一个AO对象。

函数预编译过程(形实函运):

1)创建AO对象:函数调用以后在运行代码之前会生成一个执行期上下文对象AO,函数每调用一次都会生成一个AO对象。

2)给AO对象添加成员:找函数内部的局部变量和形参变量(局部变量和形参变量不分先后),局部变量和形参变量的变量名作为AO对象的成员名,赋值为undefined。

3)把传入的实参赋值给AO对象的属性(实参先取值然后将传入的实参值赋值给AO对象的成员),AO对象的成员值不再是undefined。

4)在函数体里面找局部函数声明,把函数体赋值给AO对象的成员(把局部函数的名字让AO对象也有一个一样的成员名,把函数体赋值给这个成员)

当函数调用运行完以后,AO对象会释放掉。

image.png

image.png

全局预编译

全局预编译:全局作用域运行代码时的预编译

全局预编译过程:

1)生成一个对象GO

2)找所有全局变量,把变量名设置为GO对象的成员名,值为undefined

3)找所有声明的函数,把函数名作为GO对象的成员名,值为函数体

image.png

image.png

全局预编译还有一步:不同的环境中运行js代码不一样。浏览器环境中的js脚本会把GO对象的成员全部浅拷贝(GO引用给window)给环境对象window。后端node.js环境中没有这一步。

关于成员访问

console.log(a)访问的是GO对象的成员。(当变量a取值时在作用域链上取到GO对象都没有时就会报错)作用域链没有的变量会报错。

console.log(window.a)不报错没有这个成员会返回undefined。原型链上没有直到null没有返回undefined,原型链没有的返回undefined。