【译】深入理解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中执行代码;

posted @ 2016-09-22 11:46  青鹤  阅读(127)  评论(0)    收藏  举报