by Dmitry Soshnikov
In this note we will mention execution contexts of ECMAScript and types of executable code related with them.
Every time when control is transferred to ECMAScript executable code, control is entered an execution context.
Execution context (abbreviated form — EC) is the abstract concept used by ECMA-262 specification for typification and differentiation of an executable code.
The standard does not define accurate structure and kind of EC from the technical implementation viewpoint; it is a question of the ECMAScript-engines implementing the standard.
Logically, set of active execution contexts forms a stack. The bottom of this stack is always a global context, the top — a current (active) execution context. The stack is modified (pushed/popped) during the entering and exiting various kinds of EC.
With abstract concept of an execution context, the concept of type of an executable code is related. Speaking about code type, it is possible in the certain moments to mean an execution context.
For examples, we define the stack of execution contexts as an array:
The stack is pushed every time on entering a function (even if the function is called recursively or as theconstructor), and also at built-in eval
function work.
This type of code is processed at level Program
: i.e. the loaded external .js
-file or the local inline-code (inside the <script></script>
tags). The global code does not include any parts of a code which are in bodies of functions.
At initialization (program start), ECStack
looks like:
ECStack = [
globalContext
];
|
On entering the function code (all kinds of functions), ECStack
is pushed with new elements. It is necessary to notice that the code of concrete function does not include codes of the inner functions.
For example, let’s take the function which calls itself recursively once:
( function foo(flag) {
if (flag) {
return ;
}
foo( true );
})( false );
|
Then, ECStack is modified as follows:
ECStack = [
<foo> functionContext
globalContext
];
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];
|
Every return from a function exits the current execution context and ECStack
popped accordingly — consecutively and upside-down — quite natural implementation of a stack. After the work of this code is finished, ECStack
again contains only globalContext
— until the program end.
A thrown but not caught exception may also exit one or more execution contexts:
( function foo() {
( function bar() {
throw 'Exit from bar and foo contexts' ;
})();
})();
|
Things are more interesting with eval
code. In this case, there is a concept of a calling context, i.e. a context from which eval
function is called.
The actions made by eval
, such as variable or function definition, influence exactly the calling context:
eval ( 'var x = 10' );
( function foo() {
eval ( 'var y = 20' );
})();
alert(x);
alert(y);
|
Note, in the strict-mode of ES5, eval
already does not influence the calling context, but instead evaluates the code in the local sandbox.
For the example above we have the following ECStack
modifications:
ECStack = [
globalContext
];
ECStack.push({
context: evalContext,
callingContext: globalContext
});
ECStack.pop();
ECStack.push(<foo> functionContext);
ECStack.push({
context: evalContext,
callingContext: <foo> functionContext
});
ECStack.pop();
ECStack.pop();
|
I.e. quite casual and logical call-stack.
In old SpiderMonkey implementations (Firefox), up to version 1.7, it was possible to pass a calling context as a
second argument for
eval
function. Thus, if the context still exists, it is possible to influence
private variables:
function foo() {
var x = 1;
return function () { alert(x); };
};
var bar = foo();
bar();
eval ( 'x = 2' , bar);
bar();
|
However, due to security reasons in modern engines it was fixed and is not significant anymore.
This theoretical minimum is required for the further analysis of details related with execution contexts, such as variable object or scope chain, which descriptions can be found in the appropriate chapters.
Corresponding section of ECMA-262-3 specification — 10. Execution Contexts.
中文版 转载自 http://www.cnblogs.com/justinw/archive/2010/04/16/1713086.html
这篇文章我们主要探讨ECMAScript执行上下文和相关的ECMAScript可执行代码。
每次当控制器转到ECMAScript可执行代码的时候,即会进入到一个执行上下文。
执行上下文(简称-EC)是一个抽象概念,ECMA-262标准用这个概念同可执行代码(executable code)概念进行区分。
标准规范没有从技术实现的角度准确定义EC的类型和结构;这应该是具体实现ECMAScript引擎时要考虑的问题。
活动的执行上下文在逻辑上组成一个堆栈。堆栈底部永远都是全局上下文(global context),堆栈顶部是当前(活动的)执行上下文。堆栈在EC类型的变量(various kingds of EC)被推入或弹出的同时被修改。
可执行代码的概念与抽象的执行上下文的概念是相对的。在某些时刻,可执行代码与执行上下文是等价的。
例如,我们可以定义一个数组来模拟执行上下文堆栈:
每次进入函数 (即使函数被递归调用或作为构造函数) 的时候或者内置的eval函数工作的时候,这个堆栈都会被推入。
这种类型的代码是在"程序"级处理的:例如加载外部的js文件或者本地的在<script></script>标签内的代码。全局代码不包括任何函数体内的代码。
在初始化(程序启动)阶段,ECStack是这样的:
1
2
3
|
ECStack = [
globalContext
];
|
当进入函数代码(所有类型的函数),ECStack被推入新元素。要注意的是,具体的函数代码不包括内部函数(inner functions)代码。如下所示,我们使函数自己调自己的方式递归一次:
1
2
3
4
5
6
|
( function foo(bar) {
if (bar) {
return ;
}
foo( true );
})();
|
那么,ECStack以如下方式被改变:
1
2
3
4
5
6
7
8
9
10
11
12
|
ECStack = [
<foo> functionContext
globalContext
];
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];
|
每次返回存在的当前执行上下文和ECStack弹出相应的执行上下文的时候,栈指针会自动移动位置,这是一个典型的堆栈实现方式。一个被抛出但是没有被截获的异常,同样存在一个或多个执行上下文。当相关段代码执行完以后,直到整个应用程序结束,ECStack都只包括全局上下文(global context)。
eval 代码有点儿意思。它有一个概念: 调用上下文(calling context), 这是一个当eval函数被调用的时候产生的上下文。eval(变量或函数声明)活动会影响调用上下文(calling context)。
1
2
3
4
5
6
7
8
|
eval( 'var x = 10' );
( function foo() {
eval( 'var y = 20' );
})();
alert(x);
alert(y);
|
ECStack的变化过程:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
ECStack = [
globalContext
];
ECStack.push(
evalContext,
callingContext: globalContext
);
ECStack.pop();
ECStack.push(<foo> functionContext);
ECStack.push(
evalContext,
callingContext: <foo> functionContext
);
ECStack.pop();
ECStack.pop();
|
看到了吧,这是一个非常普通的逻辑调用堆栈
在版本号1.7以上的SpiderMonkey(内置于Firefox,Thunderbird)的实现中,可以把调用上下文作为第二个参数传递给eval。那么,如果这个上下文存在,就有可能影响“私有”(类似以private关键字命名的变量一样)变量。
1
2
3
4
5
6
7
8
9
10
11
12
|
function foo() {
var x = 1;
return function () { alert(x); };
};
var bar = foo();
bar();
eval( 'x = 2' , bar);
bar();
|
这篇文章的内容是未来分析其他跟执行上下文相关的主题(例如变量对象,作用域链,等等)的最起码的理论基础,这些主题将在后续章节中讲到。
这篇文章的内容在ECMA-262-3 标准规范中对应的章节— 10. Execution Contexts.
分享到:
相关推荐
ECMA-262-语言标准中文版.pdfECMA-262-语言标准中文版.pdfECMA-262-语言标准中文版.pdfECMA-262-语言标准中文版.pdf
ECMA-262-3 in detail
ECMA2017,发版时间2020年6月的英文版,有需要的同学可以下载。没有c币的可以留言邮箱,看到就回复。
ECMA-262官方规范,javascript开发的标准参考
ECMA-262, 2nd edition, August 1998.pdf ECMA-262, 3rd edition, December 1999.pdf ECMA-262. 5rd edition, December 2009.pdf 三个标准的合集,
ECMA-262-5.1中文版,javascript的核心内容。
ECMA-335 ECMA-335
Ecma-262
ECMA-262笔记。。ECMA-262笔记。。ECMA-262笔记。。
ECMA-262-5.1中文版,用于javascript编程
Ecma-262(ECMAScript5.1中文版+英文版),中文版为html格式,英文版为chm格式
Ecma标准Ecma-262.pdf
这里下载的是ECMA-262标准 的第三版 的中文 翻译。格式为PDF。 如果需要,随手拿去。 声名:这不是我翻译的。我只是把 Lich_Ray 翻译好的HTML版 整理成 更加易于学习的 PDF版。 正文内容来自: Lich_Ray 的...
ECMA-262标准官方文档
ECMA-262中文版及英文原版。ECMAScript是标准化的脚本语言,JavaScript和JScript都遵循这个规范,并且有所扩充。
ECMAScript Language Specification
在ECMA机构的促成下,由多家浏览器商共同完成。JavaScript脚本语言标准,JS核心内容
ES2015规范
这似乎针对ecma-262英文版的一个翻译版本。适合从事javascript开发工作者查阅