深入理解JavaScript系列(11) 执行上下文(Execution Contexts)


Posted in Javascript onJanuary 15, 2012

简介
从本章开始,我将陆续(翻译、转载、整理)http://dmitrysoshnikov.com/网站关于ECMAScript标标准理解的好文。

本章我们要讲解的是ECMAScript标准里的执行上下文和相关可执行代码的各种类型。

原始作者:Dmitry A. Soshnikov
原始发布: 2009-06-26
俄文原文:http://dmitrysoshnikov.com/ecmascript/ru-chapter-1-execution-contexts/

英文翻译:Dmitry A. Soshnikov.
发布时间:2010-03-11
英文翻译:http://dmitrysoshnikov.com/ecmascript/chapter-1-execution-contexts/

本文参考了博客园justinw的中文翻译,做了一些错误修正,感谢译者。
复制代码
定义
每次当控制器转到ECMAScript可执行代码的时候,即会进入到一个执行上下文。执行上下文(简称-EC)是ECMA-262标准里的一个抽象概念,用于同可执行代码(executable code)概念进行区分。

标准规范没有从技术实现的角度定义EC的准确类型和结构,这应该是具体实现ECMAScript引擎时要考虑的问题。

活动的执行上下文组在逻辑上组成一个堆栈。堆栈底部永远都是全局上下文(global context),而顶部就是当前(活动的)执行上下文。堆栈在EC类型进入和退出上下文的时候被修改(推入或弹出)。

可执行代码类型
可执行代码的类型这个概念与执行上下文的抽象概念是有关系的。在某些时刻,可执行代码与执行上下文完全有可能是等价的。

例如,我们可以定义执行上下文堆栈是一个数组:

ECStack = [];
每次进入function (即使function被递归调用或作为构造函数) 的时候或者内置的eval函数工作的时候,这个堆栈都会被压入。

全局代码
这种类型的代码是在"程序"级处理的:例如加载外部的js文件或者本地<script></script>标签内的代码。全局代码不包括任何function体内的代码。

在初始化(程序启动)阶段,ECStack是这样的:

ECStack = [ 
globalContext 
];

函数代码
当进入funtion函数代码(所有类型的funtions)的时候,ECStack被压入新元素。需要注意的是,具体的函数代码不包括内部函数(inner functions)代码。如下所示,我们使函数自己调自己的方式递归一次:
(function foo(bar) { 
if (bar) { 
return; 
} 
foo(true); 
})();

那么,ECStack以如下方式被改变:
// 第一次foo的激活调用 
ECStack = [ 
<foo> functionContext 
globalContext 
]; // foo的递归激活调用 
ECStack = [ 
<foo> functionContext ? recursively 
<foo> functionContext 
globalContext 
];

每次return的时候,都会退出当前执行上下文的,相应地ECStack就会弹出,栈指针会自动移动位置,这是一个典型的堆栈实现方式。一个抛出的异常如果没被截获的话也有可能从一个或多个执行上下文退出。相关代码执行完以后,ECStack只会包含全局上下文(global context),一直到整个应用程序结束。

Eval 代码
eval 代码有点儿意思。它有一个概念: 调用上下文(calling context),例如,eval函数调用的时候产生的上下文。eval(变量或函数声明)活动会影响调用上下文(calling context)。

eval('var x = 10'); (function foo() { 
eval('var y = 20'); 
})(); 
alert(x); // 10 
alert(y); // "y" 提示没有声明

ECStack的变化过程:
ECStack = [ 
globalContext 
]; // eval('var x = 10'); 
ECStack.push( 
evalContext, 
callingContext: globalContext 
); 
// eval exited context 
ECStack.pop(); 
// foo funciton call 
ECStack.push(<foo> functionContext); 
// eval('var y = 20'); 
ECStack.push( 
evalContext, 
callingContext: <foo> functionContext 
); 
// return from eval 
ECStack.pop(); 
// return from foo 
ECStack.pop();

也就是一个非常普通的逻辑调用堆栈。

在版本号1.7以上的SpiderMonkey(内置于Firefox,Thunderbird)的实现中,可以把调用上下文作为第二个参数传递给eval。那么,如果这个上下文存在,就有可能影响“私有”(有人喜欢这样叫它)变量。

function foo() { 
var x = 1; 
return function () { alert(x); }; 
}; var bar = foo(); 
bar(); // 1 
eval('x = 2', bar); // 传入上下文,影响了内部的var x 变量 
bar(); // 2

结论
这篇文章是后面分析其他跟执行上下文相关的主题(例如变量对象,作用域链,等等)的最起码的理论基础,这些主题将在后续章节中讲到。

其他参考

Javascript 相关文章推荐
JS维吉尼亚密码算法实现代码
Nov 09 Javascript
JavaScript代码简单实现求杨辉三角给定行的最大值
Oct 29 Javascript
js图片向右一张张滚动效果实例代码
Nov 23 Javascript
一个小例子解释如何来阻止Jquery事件冒泡
Jul 17 Javascript
JS 滚动事件window.onscroll与position:fixed写兼容IE6的回到顶部组件
Oct 10 Javascript
Vuex之理解Getters的用法实例
Apr 19 Javascript
基于node.js express mvc轻量级框架实践
Sep 14 Javascript
jQuery实现打开网页自动弹出遮罩层或点击弹出遮罩层功能示例
Oct 19 jQuery
Bootstrap模态对话框中显示动态内容的方法
Aug 10 Javascript
angular1.x ui-route传参的三种写法小结
Aug 31 Javascript
傻瓜式解读koa中间件处理模块koa-compose的使用
Oct 30 Javascript
JavaScript禁用右键单击优缺点分析
Jan 20 Javascript
深入理解JavaScript系列(10) JavaScript核心(晋级高手必读篇)
Jan 15 #Javascript
深入理解JavaScript系列(9) 根本没有“JSON对象”这回事!
Jan 15 #Javascript
深入理解JavaScript系列(8) S.O.L.I.D五大原则之里氏替换原则LSP
Jan 15 #Javascript
深入理解JavaScript系列(7) S.O.L.I.D五大原则之开闭原则OCP
Jan 15 #Javascript
深入理解JavaScript系列(6):S.O.L.I.D五大原则之单一职责SRP
Jan 15 #Javascript
深入理解JavaScript系列(6) 强大的原型和原型链
Jan 15 #Javascript
深入理解JavaScript系列(4) 立即调用的函数表达式
Jan 15 #Javascript
You might like
php根据一个给定范围和步进生成数组的方法
2015/06/19 PHP
列举PHP的Yii 2框架的开发优势
2015/07/03 PHP
php正则去除网页中所有的html,js,css,注释的实现方法
2016/11/03 PHP
laravel 解决强制跳转 https的问题
2019/10/22 PHP
php设计模式之模板模式实例分析【星际争霸游戏案例】
2020/03/24 PHP
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
JS实现点击文字对应DIV层不停闪动效果的方法
2015/03/02 Javascript
js实现简单的省市县三级联动效果实例
2016/02/18 Javascript
Ionic如何创建APP项目
2016/06/03 Javascript
AngularJS使用angular.bootstrap完成模块手动加载的方法分析
2017/01/19 Javascript
js实现分页功能
2017/05/24 Javascript
基于JavaScript实现带数据验证和复选框的表单提交
2017/08/23 Javascript
对于Javascript 执行上下文的全面了解
2017/09/05 Javascript
基于vue cli重构多页面脚手架过程详解
2018/01/23 Javascript
JS设计模式之访问者模式定义与用法分析
2018/02/05 Javascript
vue实现word,pdf文件的导出功能
2018/07/31 Javascript
Webpack 4.x搭建react开发环境的方法步骤
2018/08/15 Javascript
Vue常用指令详解分析
2018/08/19 Javascript
vue项目引入Iconfont图标库的教程图解
2018/10/24 Javascript
基于three.js实现的3D粒子动效实例代码
2019/04/09 Javascript
Python复制文件操作实例详解
2015/11/10 Python
编写Python爬虫抓取暴走漫画上gif图片的实例分享
2016/04/20 Python
python生成特定分布数的实例
2019/12/05 Python
matlab中imadjust函数的作用及应用举例
2020/02/27 Python
windows10环境下用anaconda和VScode配置的图文教程
2020/03/30 Python
使用python-Jenkins批量创建及修改jobs操作
2020/05/12 Python
Python接收手机短信的代码整理
2020/08/02 Python
Django Form常用功能及代码示例
2020/10/13 Python
python 爬虫之selenium可视化爬虫的实现
2020/12/04 Python
html5拍照功能实现代码(htm5上传文件)
2013/12/11 HTML / CSS
美国户外运动商店:Sun & Ski
2018/08/23 全球购物
单位在职证明书
2014/09/11 职场文书
英语教师个人工作总结
2015/02/09 职场文书
python自然语言处理之字典树知识总结
2021/04/25 Python
Python中文纠错的简单实现
2021/07/07 Python
Redis实现主从复制方式(Master&Slave)
2022/06/21 Redis