深入理解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 相关文章推荐
Mozilla中显示textarea中选择的文字
Sep 07 Javascript
JS 事件绑定函数代码
Apr 28 Javascript
js 获取和设置css3 属性值的实现方法
May 06 Javascript
js或jquery实现页面打印可局部打印
Mar 27 Javascript
jQuery事件用法实例汇总
Aug 29 Javascript
Javascript中arguments和arguments.callee的区别浅析
Apr 24 Javascript
关于RequireJS的简单介绍即使用方法
Oct 20 Javascript
利用BootStrap的Carousel.js实现轮播图动画效果
Dec 21 Javascript
详解vue组件通信的三种方式
Jun 30 Javascript
浅谈es6 javascript的map数据结构
Dec 14 Javascript
原生js实现淘宝放大镜效果
Oct 28 Javascript
layui时间控件选择时间范围的实现方法
Sep 28 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
无线电广播的开始
2002/01/30 无线电
MySQL时间字段究竟使用INT还是DateTime的说明
2012/02/27 PHP
浅谈php安全性需要注意的几点事项
2014/07/17 PHP
php简单统计在线人数的方法
2016/05/10 PHP
php strftime函数获取日期时间(switch用法)
2018/05/16 PHP
IE6/7/8/9不支持exec的简写方式
2011/05/25 Javascript
js Html结构转字符串形式显示代码
2011/11/15 Javascript
Extjs中ComboBoxTree实现的下拉框树效果(自写)
2013/05/28 Javascript
js使下拉列表框可编辑不止是选择
2013/12/12 Javascript
jQuery中fadeOut()方法用法实例
2014/12/24 Javascript
javascript属性访问表达式用法分析
2015/04/25 Javascript
javascript中数组方法汇总
2015/07/07 Javascript
jQuery制作圣诞主题页面 更像是爱情影集
2016/08/10 Javascript
AngularJS过滤器详解及示例代码
2016/08/16 Javascript
简单实现AngularJS轮播图效果
2020/04/10 Javascript
jQuery插件FusionWidgets实现的Cylinder图效果示例【附demo源码】
2017/03/23 jQuery
JS中showModalDialog关闭子窗口刷新主窗口用法详解
2017/03/25 Javascript
详解用webpack把我们的业务模块分开打包的方法
2017/07/20 Javascript
node 命令方式启动修改端口的方法
2018/05/12 Javascript
JS实现数组去重,显示重复元素及个数的方法示例
2019/01/21 Javascript
layui table去掉右侧滑动条的实现方法
2019/09/05 Javascript
vue项目中使用particles实现粒子背景效果及遇到的坑(按钮没有点击响应)
2020/02/11 Javascript
一文读懂vue动态属性数据绑定(v-bind指令)
2020/07/20 Javascript
vue实现井字棋游戏
2020/09/29 Javascript
Python3下错误AttributeError: ‘dict’ object has no attribute’iteritems‘的分析与解决
2017/07/06 Python
python取数作为临时极大值(极小值)的方法
2018/10/15 Python
python在TXT文件中按照某一字符串取出该字符串所在的行方法
2018/12/10 Python
PyCharm导入python项目并配置虚拟环境的教程详解
2019/10/13 Python
python 如何设置守护进程
2020/10/29 Python
详解canvas多边形(蜘蛛图)的画法示例
2018/01/29 HTML / CSS
英格兰橄榄球商店:England Rugby Store
2016/12/17 全球购物
XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?
2016/01/12 面试题
企业授权委托书范本
2014/04/02 职场文书
员工三分钟演讲稿
2014/08/19 职场文书
群教个人对照检查材料
2014/08/20 职场文书
大二学年个人总结
2015/03/03 职场文书