作为一个前端开发者,大家在平常最熟悉不过的开发语言就是JavaScript了,每次执行的时候你了解都发生了什么事情么?今天我们来简单了解一下js执行上下文。
执行上下文(Execution Context)
在我们运行一段js代码的时候,就会生成一个可执行的上下文,根据不同的类型的区分呢,有存在以下几种类型的执行上下文:
| 上下文 | 释义 |
|---|---|
| Global code | 代码第一时间指的全局环境 |
| Function code | 函数代码块 |
| Eval code | 函数包含的代码块 |
下面举个栗子
// global context
var hi = 'hi'
function student () { // function context
var name = '张三'
var age = 12
function showName (){ // function context
return name
}
function showAge () { // function context
return age
}
alert(hi + showName() + showAge())
}
从上面这段代码,我们有一个global context 和3个不同的function context,你可以随意的创建function context但是每一个函数都会创建一个新的执行上下文(EC)。函数外部定义的变量可以被函数内部使用,但是函数内部定义的变量不能被函数外部使用。
执行栈
我们知道浏览器解析器执行js是一个单线程的过程,所以在同一个时间点内,只能有一个事情在进行。其他的活动和事件需要排队等待,生成一个队列执行栈。
在一开始执行代码的时候,便确定了一个全局执行上下文作为默认值。如果在你的全局环境中,调用了调用了其他的函数,程序将会再创建一个新的 EC,然后将此 EC推入进执行栈中execution stack
如果函数内再调用其他函数,相同的步骤将会再次发生:创建一个新的EC -> 把EC推入执行栈。一旦一个EC执行完成,变回从执行栈中推出(pop)
(function foo(i) {
if (i === 3) {
return;
}
else {
foo(++i);
}
}(0));
上面这个函数完成了对自身的3次调用,第一次调用时,生成一个EC推入执行栈,在执行的过程中,又遇到一个新的函数foo(1)此时,又会创建一个新的EC,再次推入...
说到执行栈呢,有5个关键点可以简单的了解一下
- 同步执行
- 单线程
- 无线多的 function context
- 1 个全局执行上下文 ( Global context)
- 每个函数调用都会创建一个新的 EC,即使是调用自身
执行上下文的一些细点
我们知道一旦函数被调用了,都是会创建一个新的执行上下文出来的。但是在js解释器中,调用执行上下文有2个阶段:
阶段1: 创建阶段(函数呗调用,但是还么有执行)
- 创建作用域链
scope chain - 定义arguments、变量、函数
- 确定 this 值 阶段2: 激活、执行代码阶段
- 主要是对之前定义的变量分配值,开始解释执行代码。
每当一个 function 被调用时,我们可以大致描述一下会创建这样一个
executionContextObj对象
executionContextObj = {
'scopeChain': { /* 变量 + 父执行上下文上的变量 */ },
'variableObject': { /* function arguments / parameters,内部的 variable 和 function 声明 */ },
'this': {}
}