概要

本文将向大家介绍ECMAScript的执行上下文以及相关的可执行代码类型。

定义

每当控制器到达ECMAScript可执行代码的时候,控制器就进入了一个执行上下文。
执行上下文(简称:EC)是个抽象的概念,ECMA-262标准中用它来区分不同类型的可执行代码。

标准中并没有从技术实现的角度来定义执行上下文的具体结构和类型;这是实现标准的ECMAScript引擎所要考虑的问题。

一系列活动的执行上下文从逻辑上形成一个栈。栈底总是全局上下文,栈顶是当前(活动的)执行上下文。当在不同的执行上下文间切换(退出的而进入新的执行上下文)的时候,栈会被修改(通过压栈或者退栈的形式)。

可执行代码类型

可执行代码类型和执行上下文相关。有的时候,当提到代码类型的时候,其实就是在说执行上下文。

举个例子,我们将执行上下文的栈以数组的形式来表示:

ECStask = [ ];

每次控制器进入一个函数(哪怕该函数被递归调用或者作为构造器),都会发生压栈的操作。内置eval函数工作的时候也不例外。

全局代码

这类代码是在“程序”级别上被处理的:比如,加载一个外部的js文件或者内联的js代码(被包含在<script></script>标签内)。全局代码不包含任何函数体内的代码。

在初始化的时候(程序开始),ECStack如下所示:

ECStack = [
globalContext
];

函数代码

一旦控制器进入函数代码(各类函数),就会有新的元素会被压栈到ECStack。要注意的是:实体函数代码并不包括内部函数的代码。如下所示,我们调用一个函数,该函数递归调用自己一次:

(function foo(bar){
if (bar){ return; } foo(true);
})();

之后,ECStack就被修改成如下所示:

//首先激活foo函数
ECStack = [
functionContext
globalContext
];
//递归激活foo函数
ECStack = [
functionContext - recursively
functionContext
globalContext
];

每次函数返回,退出当前活动的执行上下文时,ECStack就会被执行对应的退栈操作——先进后出——和传统的栈实现一致。同样的,当抛出未捕获的异常时,也会退出一个或者多个执行上下文,ECStack也会做相应的退栈操作。待这些代码完成之后,ECStack中就只剩下一个执行上下文(globalContext)——直到整个程序结束。

Eval代码

说到eval代码就比较有意思了。这里要提到一个叫做调用上下文的概念,比如:调用eval函数时候的上下文,就是一个调用上下文,eval函数中执行的动作(例如:变量声明或者函数声明)会影响整个调用上下文:

eval(‘var x = 10’);
(function foo(){
eval(‘ var y = 20’);
})();
alert(x); // 10
alert(y); // ”y” is not defined

ECStack会被修改为:

ECStack = [
globalContext
];
//eval(‘var x = 10’);
ECStack.push(
evalContext,
callingContext: globalContext
); // eval exited context
ECStack.pop(); //foo function call
ECStack.push( functionContext); //eval(‘ var y = 20’);
ECStack.push(
evalContext,
callingContext: functionContext
); //return from eval
ECStack.pop(); //return from foo
ECStack.pop();

在1.7以上版本SpiderMonkey的实现中(Firefox,Thunderbird浏览器内置的JS引擎),允许在调用eval函数的时候,将调用上下文作为第二个参数传递给eval函数。因此,如果传入的调用上下文存在的话,就有可能会影响该上下文中原有的私有变量(在该上下文中声明的变量):

function foo(){
var x = 1;
return function() { alert(x); }
}; var bar = foo(); bar(); // 1
eval(‘x = 2’, bar); //传递上下文,影响了内部变量“var x”
bar(); // 2

总结

这些基本理论对于后面执行上下文相关的细节(诸如变量对象、作用域链等等)分析是非常必要的。

扩展阅读

ECMA-363-3标准文档的对应的章节—— 10. 执行上下文

JavaScript内部原理系列-执行上下文(Execution Context)的更多相关文章

  1. 理解Javascript之执行上下文(Execution Context)

    1>什么是执行上下文 Javascript中代码的运行环境分为以下三种: 全局级别的代码 - 这个是默认的代码运行环境,一旦代码被载入,引擎最先进入的就是这个环境. 函数级别的代码 - 当执行一 ...

  2. 深入理解javascript执行上下文(Execution Context)

    本文转自:http://blogread.cn/it/article/6178 在这篇文章中,将比较深入地阐述下执行上下文 - Javascript中最基础也是最重要的一个概念.相信读完这篇文章后,你 ...

  3. 深入理解Javascript之执行上下文(Execution Context)

    在这篇文章中,将比较深入地阐述下执行上下文 - Javascript中最基础也是最重要的一个概念.相信读完这篇文章后,你就会明白javascript引擎内部在执行代码以前到底做了些什么,为什么某些函数 ...

  4. JavaScript内部原理系列-变量对象(Variable object)

    概要 我们总是会在程序中定义一些函数和变量,之后会使用这些函数和变量来构建我们的系统.然而,对于解释器来说,它又是如何以及从哪里找到这些数据的(函数,变量)?当引用一个对象的时候,在解释器内部又发生了 ...

  5. JavaScript内部原理实践——真的懂JavaScript吗?(转)

    通过翻译了Dmitry A.Soshnikov的关于ECMAScript-262-3 JavaScript内部原理的文章, 从理论角度对JavaScript中部分特性的内部工作机制有了一定的了解. 但 ...

  6. Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

    执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...

  7. JVM 内部原理系列

    JVM 内部原理(一)— 概述 JVM 内部原理(二)— 基本概念之字节码 JVM 内部原理(三)— 基本概念之类文件格式 JVM 内部原理(四)— 基本概念之 JVM 结构 JVM 内部原理(五)— ...

  8. Javascript 执行上下文 context&scope

    执行上下文(Execution context) 执行上下文可以认为是 代码的执行环境. 1 当代码被载入的时候,js解释器 创建一个 全局的执行上下文. 2 当执行函数时,会创建一个 函数的执行上下 ...

  9. [JavaScript深入系列]JavaScript深入之执行上下文栈(转载)

    顺序执行? 如果要问到 JavaScript 代码执行顺序的话,想必写过 JavaScript 的开发者都会有个直观的印象,那就是顺序执行,毕竟: var foo = function () { co ...

随机推荐

  1. PHP用"字符串和变量"组成变量

    理论很简单,将字符串和变量组合在一起形成对另一个变量的操作.同样也可以是数组 例:   $FFabcd = '组合变量'; $a = 'abcd'; $ay = array('FF','abcd'); ...

  2. TensorFlow学习笔记(三)MNIST数字识别问题

    一.MNSIT数据处理 MNSIT是一个非常有名的手写体数字识别数据集.包含60000张训练图片,10000张测试图片.每张图片是28X28的数字. TonserFlow提供了一个类来处理 MNSIT ...

  3. matplotlib中的legend()—显示图例

    源自  matplotlib中的legend()——用于显示图例 -- 博客园 http://www.cnblogs.com/yinheyi/p/6792120.html legend()的一个用法: ...

  4. TWebBrowser静音

    procedure TForm1.FormCreate(Sender: TObject); var   hDSound: Cardinal;   pDirectSoundCreate: Pointer ...

  5. Delphi APP 開發入門(九)拍照與分享

    Delphi APP 開發入門(九)拍照與分享 分享: Share on facebookShare on twitterShare on google_plusone_share   閲讀次數:30 ...

  6. PHP双向队列,双端队列代码

    <?php /**  * User: jifei  * Date: 2013-07-30  * Time: 23:12 */ /**  * PHP实现双向队列,双端队列  * 双端队列(dequ ...

  7. Glide Picasso和Fresco的对比

    比较Picasso.Glide 和 Fresco 三种图片加载库 比较 Picasso 与 Glide 总体来说二者极为相似,有着近乎相同的 API 的使用风格,但 Glide 在缓存策略和加载 gi ...

  8. suse linux 常用命令

    功能:rm 命令,删除一个目录中的一个或多个文件或目录(文件夹). 它也可以将某个目录及其下的所有文件及子目录均删除. 对于链接文件,只是删除了链接,原有文件均保持不变. 文件一旦被删除,它不能被恢复 ...

  9. python3_json模块使用与字符编码问题

    序列化:将对象的状态信息转换为可以存储或可以通过网络传输的过程,传输的格式可以是json,xml. 反序列化:就是从存储区域(json,xml)读取反序列化对象的状态,重新创建该对象 Json:一种轻 ...

  10. Ubuntu 16.04 安装Navicat Premium

    一.介绍 Navicat premium是一款数据库管理工具,是一个可多重连线资料库的管理工具,它可以让你以单一程式同时连线到 MySQL.SQLite.Oracle 及 PostgreSQL 资料库 ...