「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」
JavaScript的发展很快,从JavaScript最初版本到现在ES6+已经经历过很多版本的迭代。那么JavaScript ES3中的执行上下文到底是怎样的呢?
执行上下文(execution context)
说到ES3中的执行上下文,不得不先了解一下执行上下文(execution context)的概念。简单来说在 JavaScript 代码运行时所处的环境,其实就是执行上下文(execution context)。 在JavaScript中执行上下文分为三类:
- 全局执行上下文
- 函数执行上下文
- eval 函数执行上下文
执行上下文栈(Execution context stack)
我们可以通过以下代码来了解一下执行上下文(execution context)
function fn1(){
console.log(1)
fun2()
}
function fun2(){
console.log(2)
function fun3(){
console.log(3)
}
fun3()
}
fun1()
此时这种多个函数嵌套的情况在JavaScript中是使用执行上下文栈(Execution context stack)简写就是ECS。既然叫栈那么他就具有先进后出的特性了。
首先我们可以定义ECS变量来代表执行上下文栈(Execution context stack)
let ECS = []
ECS.push('globalContext')
执行一个函数时首先先将创建一个函数上下文并把入栈,执行完毕后就会出栈。
ECS.push('functionContext1')
ECS.push('functionContext2')
ECS.push('functionContext3')
ECS.pop()
ECS.pop()
ECS.pop()
了解完大致的执行过程,我们再来说说JavaScript中早期执行上下文(execution context)也就是ES3时期的。
JavaScript中早期执行上下文(execution context)
在ES3时期JavaScript上下文(execution context)主要包含3个部分
- 变量对象(variable object)通常用VO来表示
- 作用域(scope)
- this(this value)
变量对象(variable object)
变量对象会根据当前执行上下文不同会区分为函数全局变量对象,函数变量对象又称为活动对象(activation object)简称(AO)。
全局上下文中的全局对象
在浏览器环境中,全局对象是windowd。
函数上下文中的活动对象
通常我们把函数的活动对象(AO)与函数的变量对象(VO)看作成一个东西。但严格来讲AO = VO + parameters + arguments的。
作用域(scope)
我们都知道JavaScript中使用的是词法作用域(lexical scoping),在函数定义的时候就决定了。
词法作用域可以根据变量定义的位置来确认该变量可以在哪里使用。值得一提的是当发生函数嵌套时,内部函数可以调用外部函数作用域的变量。
let n = 0
function fun1(){
let n = 1
function fun2(){
console.log(n)
}
fun2()
}
fun1()
此时我们可以发现内部函数fun2可以使用外部函数fun1作用域定义的变量。
我们将代码稍作修改:
let n = 0
function fun1(){
let n = 1
return function fun2(){
console.log(n)
}
}
const f = fun1()
f()
此时俩种写在结果上面是一模一样的,但值上下文执行栈中则略有不同。
- 第一种写法
ECS.push('fun1Context')
ECS.push('fun2Context')
ECS.pop() // fun2
ECS.pop() // fun1
- 第二种写法
ECS.push('fun1Context')
ECS.push('fun2Context')
ECS.pop() // fun2
ECS.pop() // fun1
this的确定
this会根据执行上下文的变化,可能会发生变化。具体的变可以我之前写的一篇了解this的四种形式,看完这篇文章就足够了!!!。