前言
在学习JavaScript这些核心部分的时候,看了汤姆大叔的博客, 发现是从外国的一个开发者Dmitry Soshnikov写的关于ECMA-262-3标准解析博客系列里翻译过来的,原文的翻译国内也有人在做www.cnblogs.com/justinw/arc…
可能是我有点菜,被绕晕了,那干脆不如我自己去翻译别人的文章,用我的理解,从一个初学者的角度去翻译,看下自己能不能理解,可能会帮助到一些人也不一定?
所以本文是从自己的理解出发的,难免会有错误,非常期待能得到批评指正,我们一起讨论一起进步。
请注意:本系列文章基于ES3标准展开,有些内容在ES5已经被修改了
执行上下文(execution contexts)
执行上下文(execution contexts)是当前JavaScript代码被解析和执行时所在环境的抽象概念。
标准规范没有从技术的角度去定义执行上下文的准确类型和结构,具体实现是由厂商实现JS引擎时决定。
执行上下文的类型
- 全局执行上下文
- 函数执行上下文
- eval执行上下文
执行栈
JS引擎在处理执行上下文的时候,从逻辑上是一个后进先出的顺序,所以我们可以具象为用一个栈的结构去存储执行上下文,也就是我们俗称的执行栈,执行栈的底部总是会有一个全局执行上下文,顶部是当前执行上下文,
我们甚至可以将一个执行栈定义为一个数组,以方便我们的理解。
ECStack = []
每次当执行一个函数的时候(包括递归调用,作为构造函数调用或者是作为eval函数的内部函数),执行栈会将相应的执行上下文压入执行栈中。
可执行代码的类型
要理解执行上下文,首先要理解可执行代码(executable code)的概念,在某些时刻,可执行代码与执行上下文完全有可能是等价的。
在JavaScript中,可执行代码可以分为以下三种:
全局可执行代码(Global code)
全局可执行代码是
<script></script>
标签内或者是从外部加载的js文件中不存在于任何在函数体内的代码
这么理解就行了,除了定义在函数内的代码,其他代码都是全局可执行代码。
全局可执行代码,还记得上面定义的执行栈吗,在JS程序开始的时候,执行栈会被初始化,往里面push
一个全局执行上下文
ECStack = [
globalContext
];
函数可执行代码(function code)
每当执行一个函数(所有类型的函数)的时候,执行栈会push
一个新的函数执行上下文,但函数执行上下文不包括当前函数的内部函数。
要理解这句话,还是得看一个例子
(function foo(flag) {
if (flag) {
return;
}
foo(true);
})(false);
这是一个立即执行函数,这个函数会递归调用自身函数一次,也就是说在一个函数内部调用了一个函数,执行栈会发生这样的变化:
当调用foo的时候,执行栈会push
一个新的函数执行上下文<foo> functionContext
ECStack = [
<foo> functionContext
globalContext
];
当调用foo中递归调用foo的时候,执行栈会push
一个新的函数执行上下文<foo> functionContext – recursively
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];
也就是说,foo第一次被调用时创建的执行上下文不包括递归调用的foo,递归调用的foo自己又创建了一个执行上下文。这么做的目的是为了明确执行权的交接,
因为每一个执行上下文中的函数return之后,执行栈就会将这个执行上下文pop
出去,执行权交回当前栈顶的执行上下文。
执行栈会不停地push
和pop
,但是栈底一直都会存在一个globalContext
,它是一个兜底的执行上下文,当整个程序结束它才会销毁。
eval可执行代码(eval code)
eval函数是一个独一无二的函数,它非常强大,但也有安全的隐患,一般不提倡使用,所以这里我就不看了。
总结
- 执行上下文分是可执行代码执行和解析的环境的一个抽象概念
- 执行上下文有三种,可执行代码也有三种,有时候这两个概念可以理解为是相同的
- JS引擎在处理执行上下文的时候,从逻辑上是一个后进先出的顺序,所以我们可以具象为用一个栈的结构去存储执行上下文,称为执行栈
理解执行上下文的概念是理解变量对象、作用域链、this、闭包的基础,后面我也会写一些文章去介绍一下。
参考
dmitrysoshnikov.com/ecmascript/… github.com/yygmind/blo… www.cnblogs.com/TomXu/archi… www.cnblogs.com/justinw/arc…