在了解js执行引擎之前的我们先了解一些基础知识。
Q1: JS的特点?
- 是一种
解析型
、单线程
的弱脚本语言。- js 的执行顺序是自上向下进行的。
- 有自动垃圾回收(标识清除和引用清除)
- 动态类型的语言: 运行的时候才确定对象的类型。
- 面向对象的概念。
v8引擎: 从头到尾负责js程序的编译及执行过程
V8 引擎有两个主要的部件:
Memory heap(内存堆) —— 内存分配地址的地方
Call Stack (调用栈) —— 代码执行的地方
编译器: 负责语法分析和代码生成
作用域: 负责收集并维护所有声明的变量和函数组成的一系列查询,并实施一条非常严格的规则,确定当前执行的代码对这些变量和函数的访问权限。
js 引擎执行的过程分为三个部分:
- 语法分析
- 预编译
- 执行解析
接下来,我们将从这三个过程对js引擎执行过程进行详细的分析。
注: 浏览器首先按照顺序加载由<script>
标签分割的js代码块,加载js代码块完毕之后,立即进入三个阶段,然后在按照顺序查找下一个代码块,在继续执行以上三个阶段。(无论外部脚本语言,还是内部脚本代码块)
语法分析阶段
js 脚本语言加载完毕之后,会首先进行语法分析阶段。作用是:
分析该js代码块的语法是否存在基本的语法错误,若存在则抛出语法错误(SyntaxError), 停止该js代码块的执行,然后继续查找并加载下一个代码块;如果语法正确,则会进入预编译阶段。
注意: javaScript报错后,在相同的script标签中的js代码,会受到影响;
在新的script标签中的js代码,不会受到影响!javaScript报错后,在相同的script标签中的js代码,会受到影响;
在新的script标签中的js代码,不会受到影响!
预编译阶段
js 代码块通过语法分析阶段后,语法正确则进入预编译阶段,在分析预编译阶段之前,我们了解一下js的运行环境, 运行环境主要有三种:
- 全局环境 (JS代码加载完毕后,进入代码预编译阶段即进入全局环境)
- 函数环境(函数调用执行时, 进入该函数环境,不同的函数则函数环境同)
- eval (不建议使用,会有安全,性能等问题)
每进入一个不同的运行环境都会创建一个执行期上下文(Execution Context), 那么在一段js代码中会创建多个执行期上下文,js引擎会以栈的方式对这些执行期上下文进行处理,形成函数调用栈(call stack), 栈底永远是全局执行上下文(Global Execution Context),
栈顶则永远是当前执行上下文(Active Execution Context)。
函数调用栈就是使用栈的存取方式进行管理运行环境,特点是LIFO, FILO.
模仿调用栈的运行方式
function bar() {
var B_context = "Bar EC";
function foo() {
var f_context = "foo EC";
}
foo()
}
bar()
-
- 首先进行全局环境,创建全局执行上下文(GO), push到stack栈中,
-
- 调用bar()函数,进入bar() 函数运行环境, 创建bar函数执行上下文(AO), push() 到stack栈中
-
- 在bar()函数中调用foo()函数, 则再进入foo() 函数运行环境,创建foo() 函数执行期上下文(AO), push到stack栈中。
-
- 此时,栈底为全局执行上下文(GO),栈顶是foo() 函数执行上下文(AO),由于foo()函数没有再调用其他函数,那么则开始出栈。
-
- foo() 函数执行完毕之后,栈顶foo函数执行上下文(AO) 首先pop()出栈并销毁。
-
- foo() 函数执行完毕之后,bar() 函数执行上下文(AO) pop()出栈并销毁。
-
- 全局执行上下文 则在浏览器或者标签页关闭时候pop()出栈并销毁。
注意:不同的运行环境执行都会进入代码预编译和执行两个阶段,语法分析则在代码加完毕时统一检验语法
- 全局执行上下文 则在浏览器或者标签页关闭时候pop()出栈并销毁。
创建执行上下文
执行上下文可以理解为当前的执行环境,与该运行环境相对应。创建执行上下文主要分为三个部分:
- 创建变量对象 variable object
- 建立作用域链 Scope chain
- 确定 this 指向
创建变量对象
变量对象创建过程分为:
-
- 创建arguments对象,检查当前作用域(上下文)中的参数
-
- 检查当前上下文的函数声明
-
- 检查当前上下文的变量声明
- 检查当前上下文的变量声明
建立作用域链
**作用域链由当前执行环境的变量对象(未进入执行阶段前)**与上层环境的一系列活动对象组成,它保证了当前执行环境对符合访问权限的变量和函数的有序访问。
确定this指向
在全局环境下,全局执行上下文中的变量对象的this属性指向为window; 函数环境下的this指向却较为灵活。