前言
本文3356字,阅读大约需要9分钟。
总括: 本文深入的讲解了Javascript中的执行上下文和执行栈。
- 原文地址:Understanding Execution Context and Execution Stack in Javascript
- 公众号:「前端进阶学习」,回复「666」,获取一揽子前端技术书籍
流水在碰到底处时才会释放活力。
正文
如果你是或者想成为一名Javascript开发者,那就必须要知道Javascript内部是如何执行的。正确的理解Javascript中的执行上下文和执行栈对于理解其它Javascript概念(比如变量提升,作用域,闭包等)至关重要。
正确的去理解Javascript执行上下文和执行栈将会是你成为一名更好的Javascript开发者。
不多废话,我们现在就开始:)
什么是执行上下文
简单的来说,执行上下文是一种对Javascript代码执行环境的一种抽象概念,也就是说只要有Javascript代码运行,那么它就一定是运行在执行上下文中。
执行上下文的类型
Javascript一共有三种执行上下文:
- **全局执行上下文。**这是一个默认的或者说基础的执行上下文,所有不在函数中的代码都会在全局执行上下文中执行。它会做两件事:创建一个全局的
window
对象(浏览器环境下),并将this
的值设置为该全局对象,另外一个程序中只能有一个全局上下文。 - **函数执行上下文。**每次调用函数时,都会为该函数创建一个执行上下文,每一个函数都有自己的一个执行上下文,但注意是该执行上下文是在函数被调用的时候才会被创建。函数执行上下文会有很多个,每当一个执行上下文被创建的时候,都会按照他们定义的顺序去执行相关代码(这会在后面会说到)。
- **Eval函数执行上下文。**在
eval
函数中执行的代码也会有自己的执行上下文,但由于eval
函数不会被经常用到,这里就不做讨论了。(译者注:eval
函数容易导致恶意攻击,并且运行代码的速度比相应的替代方法慢,因为不推荐使用)。
执行栈
执行栈,在其他编程语言中也被称为“调用栈”,这是一种后进先出(LIFO)的数据结构,被用来储存在代码运行阶段创建的所有的执行上下文。
当Javascript引擎(**译者注:**Javascript引擎是执行Javascript代码的解释器,一般被内嵌在浏览器中)开始执行你第一行Javascript脚本代码的时候,它就会创建一个全局执行上下文然后将它压到执行栈中。每当引擎碰到一个函数的时候,它就会创建一个函数执行上下文,然后将这个执行上下文压到执行栈中。(**译者注:**这种结构类似弹夹,执行栈就是弹夹,执行上下文是子弹,子弹被一个个压入弹夹,当子弹发射的时候,最后一个进弹夹的子弹会被最先射出)。
引擎会执行位于执行栈栈顶的执行上下文(一般是函数执行上下文),当该函数执行结束后,对应的执行上下文就会被弹出,然后控制流程到达执行栈的下一个执行上下文。
结合下面的代码来理解下:
let a = 'Hello World!';
function first() {
console.log('Inside first function');
second();
console.log('Again inside first function');
}
function second() {
console.log('Inside second function');
}
first();
console.log('Inside Global Execution Context');
当上述代码在浏览器中加载时,Javascript引擎首先创建一个全局执行上下文并将其压入执行栈中,然后碰到first()
函数被调用,此时再创建一个函数执行上下文压入执行栈中。
当second()
函数在first()
函数中被调用时,引擎再针对这个函数创建一个函数执行上下文将其压入执行栈中,second
函数执行完毕后,对应的函数执行上下文被推出执行栈销毁,然后控制流程到下一个执行上下文也就是first
函数。
当first
函数执行结束,first函数执行上下文也被推出,引擎控制流程到全局执行上下文,直到所有的代码执行完毕,全局执行上下文也会被推出执行栈销毁,然后程序结束。
执行上下文是如何创建的?
现在我们已经了解了Javascript引擎是如何去处理执行上下文的,那么,执行上下文是如何创建的呢?
执行上下文的创建分为两个阶段:
- 创建阶段;
- 执行阶段;
创建阶段
执行上下文是在创建阶段被创建的,创建阶段包括以下几个方面:
- 创建词法环境;
- 创建变量环境;
因此执行上下文可以抽象为下面的形式:
ExecutionContext = {
LexicalEnvironment = <ref. to LexicalEnvironment in memory>,
VariableEnvironment = <<