js预编译的执行过程

js运行三部曲:1.语法分析(通篇扫描是否有语法错误) 2.预编译  3.解释执行

预编译: 简单记忆,函数声明整体提升,变量声明提升。

声明变量的时候 var  num1=1;其实js引擎在语法分析之后的预编译过程会将var num1=1;分解成变量声明var a; 和变量赋值a =1; 并且将变量声明var a;提升到逻辑的最顶部。 所以如果在变量赋值前调用变量的值为undefined。比如 console.log(a); var a=123; 打印结果为undefined;


预编译前奏:

1.暗示全局变量 (imply global)即任何变量如果未经声明就复制,那么此变量就归全局所有。(当预编译过程中发现存在未经声明变量就赋值的时候后,直接将这个变量给到GO)

2.一切在全局声明的对象,都为window的属性。 即var a=123;等同于window.a=123;


函数的预编译:


js预编译的执行过程_第1张图片
例子


js预编译的执行过程_第2张图片
运行结果


js预编译的执行过程_第3张图片
例子2

函数预编译过错

1.创建AO对象(activation object 也叫执行期上下文 也叫活动对象)

AO{

2.找形参和变量声明,将形参和变量的名做为AO对象的属性名,值为undefined。

3.将形参和实参的值统一

4.找函数声明,将函数名作为AO对象的属性名,值赋函数体。

}

创建完ao对象之后解释一行执行一行。


全局的预编译:

1.创建GO对象(global object 也叫全局执行期上下文 也叫全局对象 【window就是GO】)

GO{

2.变量声明,将变量的名做为AO对象的属性名,值为undefined。

3.找函数声明,将函数名作为AO对象的属性名,值赋函数体。

}


js预编译的执行过程_第4张图片
例子


js预编译的执行过程_第5张图片
例子


js预编译的执行过程_第6张图片
例子


js预编译的执行过程_第7张图片

资料:https://segmentfault.com/q/1010000009718528

这其实是个历史遗留问题……

以前在ES5的时候,规范规定函数只能在顶层作用域和函数作用域之中声明,不能在块级作用域声明。所以,类似这样的语句其实都是非法的:

if(true) {functionf(){}}

但是实际上各大浏览器出于兼容性的考虑,都没有遵守这个规范。

到了现在ES6的年代,规范规定了块级作用域的存在,函数就可以在块级作用域中定义了。

但其实事情并没有这么简单,因为这样的话,函数的定义行为就和以前不兼容了,为了保证和以前的兼容性,ES6在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式。

在ES6的浏览器中,它们的行为实际上是这样的:

允许块级作用域中定义函数

函数声明实际上将会类似于使用var声明的函数表达式,所有预编译的时候块级作用域中声明的函数实际上是以变量的行为方式被提升到对象里的。

if语句等块级作用于中声明函数,实际上是隐式地声明了一个函数表达式。所以预编译的时候只能得到变量的声明提升。并不是函数声明的整体提升。

你可能感兴趣的:(js预编译的执行过程)