什么是执行上下文:
当前javascript代码被解析和执行时所在的环境,javascript中运行任何的代码都是在执行上下文中运行。
执行上下文类型:
全局上下文:默认最基础执行上下文。不在任何函数中的代码都位于全局执行上下文中,
全局上下文做了两件事:
创建了一个全局对象,在浏览器中这个全局对象就是window对象;
将this指向这个全局对象,一个程序中只有一个全局执行上下文。
函数执行上下文:每次调用函数时,都会为该函数创建一个新的函数执行上下文。每个函数都拥有自己的函数执行上下文,只有在函数被调用的时候才会创建,
一个程序中可以有任意数量的函数执行上下文。
每当一个新的执行上下文被创建,都会按特定的顺序执行一系列步骤。
如上图:一个被紫色边框圈起来的全局上下文和三个分别被绿色,蓝色和橘色框起来的不同函数上下文。只有全局上下文(的变量)能被其他任何上下文访问。
执行上下文包含部分
变量对象、作用域链、this指向
executionContextObj = {
scopeChain: { 作用域链/*(variableObject)+ 所有父执行上下文的变量对象*/ },
variableObject: { /*变量对象,函数 arguments/参数,内部变量和函数声明 */ },
this: {}
}
代码执行过程:
- 创建全局上下文(global EC)
- 全局上下文(caller)逐行自上而下执行。遇到函数时,函数执行上下文(callee)被push到执行栈顶层
- 函数执行上下文被激活,成为active EC,开始执行函数中的代码,全局上下文(caller)被挂起
- 函数执行完之后,函数执行上下文(callee)被pop移除出执行栈,控制权还给全局上下文(caller),继续执行
例如下图:
(function foo (i) {
if (i === 3) {
return;
} else {
foo(++i);
}
}(0));
这个代码调用自己三次,每次给i值加一。每次foo函数被调用,将创建一个新的执行上下文,一旦上下文执行完毕,它将被从栈顶弹出,并将控制权返还给下面的上下文,直到只剩下全局上下文为止。