所有JavaScript代码都需要在某种环境中托管和运行。在大多数情况下,这种环境是一个web浏览器。
对于在web浏览器中执行的任何一段JavaScript代码,很多过程都发生在后台。在本文中,我们将看一看JavaScript代码在web浏览器中运行的幕后发生了什么。
在开始之前,你需要先熟悉一些概念,因为我们将在本文中经常用到它们:
-
解析器:
语法解析器
是一个逐行读取代码的程序。它理解代码如何符合编程语言定义的语法,以及代码应该做什么。 -
JavaScript引擎: JavaScript引擎是一个简单的计算机程序,它接收JavaScript源代码并将其编译成CPU可以理解的二进制指令(机器码)。JavaScript引擎通常是由web浏览器供应商开发的,每个主要浏览器都有一个。例如谷歌chrome的V8引擎,Firefox的SpiderMonkey和Internet Explorer的Chakra。
-
函数声明:函数被赋予一个名称:
function doSomething() { //“doSomething” 是这个函数的名字
//statements;
} -
**函数表达式:**匿名函数,即没有函数名的函数,如:
function () {statements}
。它们通常在语句中使用,比如将函数赋值给变量:let someValue = function(){
//statements
}
现在,我们已经知道了这些概念,让我们开始吧。
JavaScript代码是如何执行的
浏览器并不能理解我们在应用程序中编写的高级JavaScript代码。它需要转换成一种浏览器和计算机都能理解的格式——机器代码。
当通过HTML读取时,如果浏览器遇到要通过<script>
标签或包含类似onClick
的JS代码的属性运行的JS代码,它会将其发送给它的JS引擎。
然后,浏览器的JS引擎创建一个特殊的环境来处理这段JS代码的转换和执行。这个环境称为执行上下文。
执行上下文包含当前正在运行的代码,以及帮助其执行的所有内容。
在执行上下文运行时,解析器解析存储在内存中的特定的代码、变量和函数,生成可执行的字节码,并执行代码。
JavaScript中有两种执行上下文:
- 全局执行上下文(GEC)
- 函数执行上下文(FEC)
接下来,让我们详细地看看这两种上下文。
全局执行上下文(GEC)
当JavaScript引擎接收到一个脚本文件时,它首先创建一个默认的执行上下文,即全局执行上下文(GEC)。
GEC
是基本的/默认的执行上下文,所有不在函数内的JavaScript代码都在这里执行。
注:对于每个
JavaScript
文件,只能有一个GEC。
函数执行上下文(FEC)
无论何时调用函数,JavaScript引擎都会在GEC中创建一种不同类型的执行上下文,称为函数执行上下文(function Execution Context, FEC),以计算和执行该函数中的代码。
由于每个函数调用都有自己的FEC,所以在脚本的运行时可以有多个FEC。
执行上下文是如何被创建的
前面我们知道了什么是执行上下文,现在让我们看看执行上下文是如何被创建的。
执行上下文(GEC或FEC)的创建分为两个阶段:
-
创建阶段
-
执行阶段
创建阶段
在创建阶段,执行上下文首先与执行上下文对象(ECO)相关联。执行上下文对象存储了许多重要数据,执行上下文中的代码在运行时使用这些数据。
创建阶段又可以分为3个阶段,在这3个阶段中定义和设置执行上下文对象的属性。这些阶段是:
- 创建变量对象(VO)
- 创建作用域链
- 为变量赋值