执行上下文(EC)是什么?
简而言之,执行上下文就是当前JavaScript代码被解析和执行时所在环境的抽象概念, JavaScript 中运行任何的代码都是在执行上下文中运行
执行上下文的类型
- 全局执行上下文: 这是默认的、最基础的执行上下文。不在任何函数中的代码都位于全局执行上下文中。它做了两件事:1.创建一个全局对象,在浏览器中这个全局对象就是 window 对象。2.将this指针指向这个全局对象。一个程序中只能存在一个全局执行上下文。
- 函数执行上下文: 每次调用函数时,都会为该函数创建一个新的执行上下文。每个函数都拥有自己的执行上下文,但是只有在函数被调用的时候才会被创建。一个程序中可以存在任意数量的函数执行上下文。每当一个新的执行上下文被创建,它都会按照特定的顺序执行一系列步骤,具体过程将在本文后面讨论。
- Eval 函数执行上下文:运行在eval函数中的代码也获得了自己的执行上下文。
执行上下文栈(ECStack)
已知函数调用前会创建执行上下文,那么JS引擎是怎么管理这么多执行上下文的?
可以利用数组模拟一下ECStack。
ECStack = []
整个JS代码开始运行前,会创建 GlobalContext
ECstack.push(GlobalContext)
以下代码执行时
function a(){
b()
}
function b() {
c()
}
function c() {
d()
}
function d(){
console.log('d')
}
a()
当引擎发现a被调用时
ECstack.push(func<a>Context)
a的执行上下文入栈后,开始执行函数体,此时发现b被调用
ECstack.push(func<b>Context)
此时执行b的函数体,同理
ECstack.push(func<c>Context)
ECstack.push(func<d>Context)
当d的执行上下文入栈后,执行console.log('d')后发现函数执行结束
ECstack.pop()// 栈结构 最后入栈的元素最先出栈
// 同理 发现c函数也执行完毕
ECstack.pop()
ECstack.pop()
ECstack.pop()
直到全部出栈只剩下GlobalContext.
执行上下文的作用
引擎创建和管理执行上下文的目的是为了什么呢?
简单将执行上下文抽象为一个执行环境对象。
它包含三个重要属性:
- 变量对象
- 作用域链
- this