写在前面
首先,这系列文章是来自俄国某大神的博客。dmitrysoshnikov.com/
其次,其实在网上已经有了此系列的翻译文章。本人原本只想做个搬运工,So,不要说我抄袭什么的感谢了!
介绍
这篇文章我们将介绍ECMAScript的执行上下文和与执行上下文相关的可执行代码类型。
定义
每当控制器进入一段ECMAScript的可执行代码时,控制器就进入了一个执行上下文。标准中并没有准确定义执行上下文(缩写为EC(Execution context))的结构和类型,这对ECMAScript执行引擎来说是一个问题。
活动的执行上下文被描述成一个栈,栈底总是全局上下文,栈顶总是当前(被激活)的执行上下文。栈的修改(即: 进栈/出栈)发生在进入一个新的执行上下文与退出一个正在执行的执行上下文(有点拗口)。
可执行代码的类型
我们抽象出来的关于可执行上下文的概念,其类型与可执行代码有关。我们的执行上下文其实就是在说可执行代码的类型。
举个例子,我们把执行上下文的栈抽象成一个数组:
ECStack = [];
复制代码
这个数组被push是在进入一个新的执行上下文时发生(即使是函数的递归或者作为一个构造函数)。
全局代码
这类代码是在“程序”级别上被处理的:比如,加载一个外部的js文件或者内联的js代码(被包含在标签内)。全局代码不包含任何函数体内的代码。
在程序初始化的时候。ECStack变成这样:
ECStack = [
globalContext
];
复制代码
函数代码
在每次执行到函数代码时(各种各样的函数),ECStack就会push进去其函数执行上下文。有必要注意的是:函数内部的代码跟这个上下文没有任何关系。
举个例子,让我们看一个函数,其调用自己。
(function foo(flag) {
if (flag) {
return;
}
foo(true);
})(false);
复制代码
然后我们可以看到ECStack被修改成这样:
//外部foo函数被激活时
ECStack = [
<foo> functionContext
globalContext
];
//内部foo函数被激活时
ECStack = [
<foo> functionContext – recursively
<foo> functionContext
globalContext
];
复制代码
函数每次return时或者执行完时,其执行上下文就会退出,ECStack会相应的弹出这个执行上下文,然后很多次的进栈、出栈,最后直到所有可执行代码被执行完以后,只剩globalContext。
(eval的部分也很有意思,只不过认为不常用,所以不写出来)
结论
这篇文章对系列文章中的“变量对象”、“作用域链”都很重要,希望可以深入理解掌握。