ECMAScript 3核心概念-执行上下文

738 阅读4分钟

前言

在学习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出去,执行权交回当前栈顶的执行上下文。

执行栈会不停地pushpop,但是栈底一直都会存在一个globalContext,它是一个兜底的执行上下文,当整个程序结束它才会销毁。

eval可执行代码(eval code)

eval函数是一个独一无二的函数,它非常强大,但也有安全的隐患,一般不提倡使用,所以这里我就不看了。

总结

  1. 执行上下文分是可执行代码执行和解析的环境的一个抽象概念
  2. 执行上下文有三种,可执行代码也有三种,有时候这两个概念可以理解为是相同的
  3. JS引擎在处理执行上下文的时候,从逻辑上是一个后进先出的顺序,所以我们可以具象为用一个栈的结构去存储执行上下文,称为执行栈

理解执行上下文的概念是理解变量对象、作用域链、this、闭包的基础,后面我也会写一些文章去介绍一下。

参考

dmitrysoshnikov.com/ecmascript/… github.com/yygmind/blo… www.cnblogs.com/TomXu/archi… www.cnblogs.com/justinw/arc…