javascript引擎执行的过程的理解--语法分析和预编译阶段

js是一种非常灵活的语言,理解js引擎的执行过程对于我们学习js是非常有必要的。看了很多这方便文章,大多数是讲的是事件循环(event loop)或者变量提升的等,并没有全面分析其中的过程。所以觉得把这个js执行的详细过程整理一下,帮助更好的理解js。

1.1基础概念

js是单线程语言。

在浏览器中一个页面永远只有一个线程在执行js脚本代码

js是单线程怨言,但是代码解析是非常迅速的,不会发生解析阻塞。

js是异步执行的,通过实践循环(event loop)方式实现的

 

暂时我们不考虑事件循环(event loop),我们先来看这样一段代码,来确定我们是否理解js引擎的执行过程

console.log(person) console.log(personFun) var person = "saucxs"; console.log(person) function personFun() { console.log(person) var person = "songEagle"; console.log(person) } personFun() console.log(person)

可以自己直接使用浏览器看出输出结果

首先我们来分析一下上面的代码,虽然很多开发人员基本上都能答出来,但是还是要啰嗦一下。

全面分析js引擎的执行过程,分为三个阶段

1、语法分析

2、预编译阶段

3、执行阶段

说明:浏览器先按照js的顺序加载<script>标签分隔的代码块,js代码块加载完毕之后,立刻进入到上面的三个阶段,然后再按照顺序找下一个代码块,再继续执行三个阶段,无论是外部脚本文件(不异步加载)还是内部脚本代码块,都是一样的,并且都在同一个全局作用域中。

 

二、语法分析

js的代码块加载完毕之后,会首先进入到语法分析阶段,该阶段的主要作用:

分析该js脚本代码块的语法是否正确,如果出现不正确会向外抛出一个语法错误(syntaxError),停止改js代码的执行,然后继续查找并加载下一个代码块;如果语法正确,则进入到预编译阶段。

类似的语法报错的如下图所示:

 

三、预编译阶段

js代码块通过语法分析阶段之后,语法都正确的下回进入预编译阶段。

在分析预编译阶段之前,我们先来了解一下js的运行环境,运行环境主要由三种:

1、全局环境(js代码加载完毕后,进入到预编译也就是进入到全局环境)

2、函数环境(函数调用的时候,进入到该函数环境,不同的函数,函数环境不同)

3、eval环境(不建议使用,存在安全、性能问题)

 

每进入到一个不同的运行环境都会创建 一个相应的执行上下文(execution context),那么在一段js程序中一般都会创建多个执行上下文,js引擎会以栈的数据结构对这些执行进行处理,形成函数调用栈(call stack),栈底永远是全局执行上下文(global execution context),栈顶则永远时当前的执行上下文。

 

3.1函数调用栈

什么是函数调用栈?

函数调用栈就是使用栈存取的方式进行管理运行环境,特点是先进后出,后进后出

我们来分析一下简答的js代码来理解函数调用栈:

function bar() { var B_context = "bar saucxs"; function foo() { var f_context = "foo saucxs"; } foo() } bar()

上面代码块通过语法分析后,进入预编译阶段,如图所示

stack

1、首先进入到全局环境,创建全局执行上下文(global Execution Context ),推入到stack中;

2、调用bar函数,进入bar函数运行环境,创建bar函数执行上下文(bar Execution Context),推入stack栈中;

3、在bar函数内部调用foo函数,则再进入到foo函数运行环境中,创建foo函数执行上下文(foo Execution Context),如上图,由于foo函数内部没有再调用其他函数,那么则开始出栈;

5、foo函数执行完毕之后,栈顶foo函数执行上下文(foo Execution Context)首先出栈;

6、bar函数执行完毕,bar函数执行上下文(bar Execution Context)出栈;

7、全局上下文(global Execution Cntext)在浏览器或者该标签关闭的时候出栈。

说明:不同的运行环境执行都会进入到代码预编译和执行两个阶段,语法分析则在代码块加载完毕时统一检查语法。

 

3.2创建执行上下文

执行上下文可以理解成当前的执行环境,与该运行环境相对应。创建执行上下文的过程中,主要是做了下面三件事,如图所示:

EC

1、创建变量对象(variable object)

2、创建作用域链(scope chain)

3、确定this的指向

 

3.2.1创建变量对象

创建变量对象主要是经过以下过程,如图所示:

VO

1、创建arguments对象,检查当前上下文的参数,建立该对象的属性与属性值,仅在函数环境(非箭头函数)中进行的,全局环境没有此过程。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpwwwx.html