javascript之作用域链

作用域链

作用域链是对象的集合,在代码的上下文里,他们提供给标识符进行查找的。

这个规则也很简单,类似于原型链:如果一个变量在它自己的作用域(自己的变量/激活对象)未找到的话,它会继续找它的

父变量对象,依次类推。

对于上下文,标识符有: 变量的名称,函数声明,形参,等等。当一个函数查找它代码的标识符,这个标识符不是本地的变量(

或本地函数,或一个形参),这个变量就就称为自由变量。那么查找这些自由变量就会使用到作用域链。

通常情况下,作用域链是所有的父变量对象的集合,加上(在这个作用域链最前面的)这个函数自身的变量/激活对象。然而,这个

链域可能包含了其他的对象,比如,对象动态的添加到这个作用域链这个上下文执行期间,通过 with--对象,或捕获异常对象。

当去查找某个标识符时,作用域链会从当前的激活对象开始查找,并(如果在自身的激活对象里没找到的话)继续向上查找,重复

下去,同原型链一样。

var x = 10;

(function foo(){
    var y = 20;

    (function bar(){
        var z = 30;
        /*
            x,y 是自由变量,
            在bar的作用域链中,
            他们会被查到在接下
            来的对象(继bar的激
            活对象)
        */
        consloe.log( x + y + z );
    })();
})()

我们将会使用内部属性__parent__来连接作用域对象,这个内部属性会引用到这个作用域链的下个对象。另外一种现实可能是通过数组。

通过__parent__概念,我有下面的图片关于来展现上面的代码(此外,变量对象是存放在函数的[[Scope]]属性上的。

在代码执行时,作用域链可以被 with 语句和 catch 语句赋值为对象。尽管这些是简单对象,他们同样有属性(和原型链)。这

会导致这个作用域链查找有两个分支:(1)先看看自身的作用域链,(2)在每一个作用域链上,需要深入到这个域链的原型链(

如果这个链域有原型对象)。

Object.prototype.x = 10;

var w = 20;
var y = 30;

console.log( x ); // 10;

(function foo(){
    // "foo" local variables
    var w = 40;
    var x = 100;

    with({z:50}){
        coonsole.log( w, x, y, z ); //40,10,30,50
    }

    console.log( x, w ); // 100, 40

    console.log( window.w ); //20

})();

我们有如下结构图(在我们访问__parent__域链,会先访问 __proto__链)。

注意到,不是所有的全局对象实现继承自 Object.prototype。出现这种结果可能是在 SpiderMonkey 引擎里测试的。

直到所有的父变量对象存在,没什么特别的从内部函数获取父数据——我们遍历作用域链去找需要的变量。然而,正如我们上面提到的,

在一个上下文结束,它的所有状态和它自己也被销毁了。同时,一个内部函数可能会从父函数里返回。通常,这个返回的函数会被再次

激活由另一个上下文。那么如果一个之前被终止的含有一些自由变量的上下文又被激活将会怎样?在普遍的理论上,一个概念有助于

解决这个问题称为闭包,在ECMAScript里这个是直接与作用域链相关的。

原文地址:https://www.cnblogs.com/branches/p/4887326.html