本章我们一起讨论一下ECMAScript的执行上下文及相关可执行代码的各种类型。so...什么是执行上下文?我们来看看定义:

每次当控制器转到ECMAScript可执行代码的时候, 即会进入到一个执行上下文。 执行上下文(以下我们且称EC)是ECMA-262标准里的一个抽象概念,用于可执行代码概念进行区分。活动的执行上下文组在逻辑上组成一个堆栈。 堆栈底部永远都是全局上下文(global context), 而顶部就是当前EC。堆栈在EC类型进入和退出上下文的时候被修改(pop or push)。

可执行代码类型

可执行代码的类型这个概念与执行上下文的抽象概念是有关系的。 在某些时刻, 可执行代码与执行上下文
完全有可能是等价的。下面我们且定义EC堆栈是一个数组:

var ECStack = [];

每次执行function时(递归调用或作为构造函数调用)或内置的eval函数工作时,这个堆栈就会被压入。

全局代码

全局代码是在“程序”级处理的,比如外部引入的js文件、本地<script></script>标签中的代码。而任何function体内的代码都不是全局代码。

在初始化阶段,ECStack是这样的:

ECStack = [
globalContext
]

函数代码

当进入函数代码的时候,ECStack被压入新元素。但不包括该函数的内部函数代码。比如,我们定义一个函数,使函数递归一次:

(function func(bar){
if(bar) {
return ;
}
arguments.callee.call(null ,true);
})();

第一次执行上面代码时,ECStack是这样的:

ECStack = [
<foo> functionContext,
globalContext
]

第二次(递归调用)执行的时候,ECStack变成这样了:

ECStack = [
<foo> functionContext,
<foo> functionContext,
globalContext
]

当程序 return 的时候,就会退出当前EC,对应的ECStack会被弹出。栈指针会自己调整位置,这是典型的堆栈。一个抛出的异常如果没被截获的话也有可能从一个或多个执行上下文退出。 相

关代码执行完以后, ECStack只会包含全局上下文(global context), 一直到整个应用程序结束。

eval代码

我们这里不讨论eval性能及其他问题。这里我们只关注上下文相关,它有一个概念:calling context(调用上下文),例如:eval函数调用所产生的上下文会影响调用上下文:

eval('var x = 1');

(function(){
eval('var y = 2');
})(); console.log(x) //
console.log(y) // y is not defined

整个执行过程,ECStack变化如下:

ECStack = [
globalContext
]
//eval('var x = 1')
ECStack.push(evalContext);
ECStack = [
evalContext ,
callingContext : globalContext
];
// eval exited context
ECStack.pop();
//anonymous function
ECStack.push(<anonymous> functionContext);
//eval('var y = 2')
ECStack.push(evalContext);
//eval exited context
ECStack.pop();
// anonymous function exited context
ECStack.pop();

参考:

本文参考了大叔的“执行上下文”章节,在此基础上做了一些调整。

最新文章

  1. 《图形学》实验七:中点Bresenham算法画椭圆
  2. 错误:E:Unable to locate package ...
  3. 1117Mysql prepare预处理语句
  4. Mac Pro 修改环境变量
  5. Angular中使用Rainbow
  6. NYOJ-组合数
  7. s3c2440 test 里面的一些用法
  8. BZOJ 3106 棋盘游戏
  9. 转:MySQL导入.sql文件及常用命令
  10. SQL函数:用于将小写的数值翻译成大写的字符串
  11. 10.26最后的模拟DAY2 改造二叉树[中序遍历+严格递增的最长不下降子序列]
  12. 每天一个Linux命令(14)--head命令
  13. 【JDK1.8】JDK1.8集合源码阅读——TreeMap(二)
  14. fitnesse - 安装部署
  15. GDB 调试多线程多进程
  16. python抽象类+抽象方法实现接口(interface)
  17. 11.Django|中间件
  18. 安装routeos
  19. 安装windows 2003iso 步骤
  20. win32下编译glog

热门文章

  1. IntraWeb.v14.0.32安装及破解指南
  2. python之requests-multipart/from-data
  3. [BZOJ 1502] [NOI2005] 月下柠檬树 【Simpson积分】
  4. ireport常见问题
  5. 【HDU3065】 病毒侵袭持续中(AC自动机)
  6. 【POJ2773】Happy 2006 欧几里德
  7. Delphi消息的广播方式(先RegisterWindowMessage,后SendMessage HWND_BROADCAST,最后改写接收窗口的WndProc)
  8. Linux启动或禁止SSH用户及IP的登录
  9. lc面试准备:Reverse Linked List II
  10. 【HDOJ】1881 毕业bg