javascript系列之执行上下文
写在前面:一 直想系统的总结一下学过的javascript知识,喜欢这门语言也热爱这门语言。未来想从事前端方面的工作,提前把自己的知识梳理一下。前面写了些 DOM的知识,略觉水平有限。没几个月就要开赴找工作的前线,奈何自己还是个菜鸟,具体写的时候还没有一个完整的思路。多番考虑之后,决定还是翻译外国的 经典系列文章,总结提升的同时,英语水平也可以上一个台阶,双管齐下,相信对以后肯定有好处。当然这个系列的文章已经有好多人翻译过了,水平都挺高(我翻 译过之后参考了一些语句,在此感谢前辈)。要是你觉得我的很烂,还望轻拍砖。实在看不下去的,请绕行,重了会伤害我幼小的心灵的哦。
在此贴上本系列的英文地址:http://dmitrysoshnikov.com/tag/ecma-262-3/
引言 |
本文将会谈到ECMAScript的执行上下文(译者注:或者执行环境)和与此相关的各类型的可执行代码
每当控制器跳转到ECMAScript的执行代码中时,控制器也就进入了一个执行上下文。
执行上下文(EC):ECMA-262用来定义一段可执行代码的典型性和差异性的抽象概念。
标准文档没有从技术实现的角度准确定义EC的结构和类型。这应该是ECMAScript引擎在具体实现时考虑的问题。
逻辑上,一个动态执行上下文的集合形成了一个堆栈,栈的底部一般是全局执行上下文,顶部--当前(活动)执行上下文。通过压入(push)和推出(pop)各种执行上下文来修改这个栈.
可执行代码 |
可执行代码是一个与执行上下文这个抽象概念相联系的概念,在谈到可执行代码的同时,可能也就意味着一个执行上下文。
例如,我们定义一个执行上下文堆栈为一个数组 ECStack=[] 每当进入一个函数(即使是递归调用的函数或者是构造函数),这个堆栈就压入一个新的执行上下文,嵌入的eval函数也是一样的。
全局代码 |
这种代码在“程序层面”中执行:例如外部加载的js文件或者是本地内联代码(在<script></script>
标签里)。全局代码不包含存在于函数体内的任何代码。初始化时(程序开始),ECStack
如下:
1 ECStack=[globalContext];
函数代码段 |
当进入函数体(所有的函数),ECStack
堆栈中压入了新的元素。必须要注意的是具体函数代码不包含它的内部函数代码段。例如,我们调用一个递归调用自身的函数:
1 (function foo(flag){ 2 if(flag){ 3 return; 4 } 5 foo(true); 6 })(false)
然后,ECStack堆栈修正如下:
1 //首先执行外部foo函数时 2 ECStack=[ 3 <foo>functionContext 4 globalContext] 5 //递归执行内部foo函数时 6 ECStack=[ 7 <foo>functionContext-递归foo 8 <foo>functionContext 9 globalContext]
当存在于当前执行上下文的函数返回时,ECStack弹出相应的执行上下文,这样连续的自上而下的执行,栈指针也不断移动,这是一个典型的堆栈实现方式。当相关段代码执行完以后,ECStack只包括全局上下文(global context),直到整个应用程序结束。一个被抛出但是没有被截获的异常,同样存在一个或多个执行上下文。
eval代码 |
(译者注:大量资深学者提出尽量不使用eval,而且此部分价值不大。减少阅读量,故不翻译)
这一小部分理论在未来进一步分析与执行上下文相关的一些细节问题,比如变量对象,作用域链时是很需要的。这些理论将在相关章节中提到。