【译】深入理解JavaScript系列:1. 执行环境
定义
执行环境是ECMA-262使用的一个抽象概念,用于表示和区分可执行代码;
ECMAScript中每当进入可执行代码时,就进入了一个执行环境;
- 一系列活动的执行环境构成了执行环境堆栈,该堆栈的底部总是全局执行环境,其顶部是当前执行环境;
- 当进入或退出执行环境时将推入或者弹出堆栈;
可执行代码的类型
鉴于执行环境是一个抽象概念,而不是技术实现,在某些情况下可执行代码的类型与执行环境是等价的;
如果将执行环境堆栈定义为数组,每当调用函数或者执行eval()时其执行环境就被推入堆栈,即使函数是递归调用或构造函数;
全局代码
全局代码是指不包含在任何函数体内的代码,全局代码是在程序级处理的,比如加载外部的.js文件或者内嵌的<script>中的代码;
在初始化阶段(程序启动阶段),执行环境堆栈中只包含全局执行环境;
ECStack=[
gloablContext;
];
函数代码
当控制流进入函数代码时,对应的函数执行环境会被推入执行环境堆栈;
当前函数代码不包含内层函数的代码;
(function foo(flag){
if(flag){
console.log(true);
}
foo(true);
})(false);
第一次调用foo()之后的执行环境堆栈:
ECStack=[
<foo>functionContext,
globalContext
];
递归调用foo()之后的执行环境堆栈:
ECStack=[
<foo>functinContext - recursively,
<foo>functionContext,
globalContext
]
函数返回之后控制流从当前执行环境中退出,相应的执行环境从执行环境堆栈中弹出,以此类推,执行环境按照由上到下的顺序依次弹出,最终执行环境堆栈中只有全局执行环境,直至程序运行结束;
抛出异常但未捕获时会导致从一个或多个执行环境退出;
(function foo(){
(function bar(){
throw "从bar和foo退出";
})()
})()
eval代码
eval()中的代码,比如变量或函数定义,将影响调用环境;
- 调用环境(calling context)是指eval()调用时所处的执行环境;
- eval()会创建执行环境,但不创建新的变量对象;
//eval
eval("var x=10");//改变全局执行环境
(function foo(){
eval("var y=20");//改变foo的变量对象
})();
console.log(x,y);//10,ReferenceError
在ES5的严格模式中,eval()不再影响调用环境,而是在局部sandbox中执行代码;

浙公网安备 33010602011771号