深入理解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 相关文章推荐
JavaScript中null与undefined分析
Jul 25 Javascript
javascript制作loading动画效果 loading效果
Jan 14 Javascript
JS实现让网页背景图片斜向移动的方法
Feb 25 Javascript
JavaScript框架是什么?怎样才能叫做框架?
Jul 01 Javascript
JavaScript获取当前cpu使用率的方法
Dec 15 Javascript
基于Bootstrap使用jQuery实现输入框组input-group的添加与删除
May 03 Javascript
微信小程序 wx.uploadFile在安卓手机上面the same task is working问题解决
Dec 14 Javascript
在vue中使用公共过滤器filter的方法
Jun 26 Javascript
JavaScript解决浮点数计算不准确问题的方法分析
Jul 09 Javascript
微信小程序滑动选择器的实现代码
Aug 10 Javascript
微信小程序JS加载esmap地图的实例详解
Sep 04 Javascript
js回调函数仿360开机
Dec 26 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和javascript之间变量的传递实现代码
2012/12/19 PHP
解析php中var_dump,var_export,print_r三个函数的区别
2013/06/21 PHP
php实现scws中文分词搜索的方法
2015/12/25 PHP
javascript 浏览器检测代码精简版
2010/03/04 Javascript
JS实现self的resend
2010/07/22 Javascript
jQuery 表单验证扩展(四)
2010/10/20 Javascript
SeaJS 与 RequireJS 的差异对比
2014/12/08 Javascript
javascript中window.open在原来的窗口中打开新的窗口(不同名)
2015/11/15 Javascript
JS基础随笔(菜鸟必看篇)
2016/07/13 Javascript
BootStrap实现手机端轮播图左右滑动事件
2016/10/13 Javascript
网页瀑布流布局jQuery实现代码
2016/10/21 Javascript
在javaScript中检测数据类型的几种方式小结
2017/03/04 Javascript
vue中mint-ui环境搭建详细介绍
2017/04/06 Javascript
vue用addRoutes实现动态路由的示例
2017/09/15 Javascript
jquery一键控制checkbox全选、反选或全不选
2017/10/16 jQuery
微信小程序实现动态设置页面标题的方法【附源码下载】
2017/11/29 Javascript
在vue项目中使用Nprogress.js进度条的方法
2018/01/31 Javascript
vue 修改 data 数据问题并实时显示的方法
2018/08/27 Javascript
微信小程序按钮去除边框线分享页面功能
2018/08/27 Javascript
微信小程序中转义字符的处理方法
2019/03/28 Javascript
node.js使用yargs处理命令行参数操作示例
2020/02/11 Javascript
vue添加锚点,实现滚动页面时锚点添加相应的class操作
2020/08/10 Javascript
[50:11]2018DOTA2亚洲邀请赛 4.7总决赛 LGD vs Mineski 第三场
2018/04/09 DOTA
[57:36]DOTA2-DPC中国联赛 正赛 SAG vs CDEC BO3 第三场 2月1日
2021/03/11 DOTA
Python中文编码知识点
2019/02/18 Python
python实现身份证实名认证的方法实例
2019/11/08 Python
使用Python来做一个屏幕录制工具的操作代码
2020/01/18 Python
python 如何区分return和yield
2020/09/22 Python
pycharm2020.1.2永久破解激活教程,实测有效
2020/10/29 Python
Electrolux伊莱克斯巴西商店:家用电器、小家电和配件
2018/05/23 全球购物
说谎欺骗人检讨书300字
2014/11/18 职场文书
领导干部学习十八届五中全会精神心得体会
2016/01/05 职场文书
《确定位置》教学反思
2016/02/18 职场文书
民政局2016年“六一”儿童节慰问活动总结
2016/04/06 职场文书
年中了,该如何写好个人述职报告?
2019/07/02 职场文书
python中pd.cut()与pd.qcut()的对比及示例
2022/06/16 Python