做用域链是对象的集合,在代码的上下文里,他们提供给标识符进行查找的。数组
这个规则也很简单,相似于原型链:若是一个变量在它本身的做用域(本身的变量/激活对象)未找到的话,它会继续找它的闭包
父变量对象,依次类推。ide
对于上下文,标识符有: 变量的名称,函数声明,形参,等等。当一个函数查找它代码的标识符,这个标识符不是本地的变量(函数
或本地函数,或一个形参),这个变量就就称为自由变量。那么查找这些自由变量就会使用到做用域链。测试
一般状况下,做用域链是全部的父变量对象的集合,加上(在这个做用域链最前面的)这个函数自身的变量/激活对象。然而,这个spa
链域可能包含了其余的对象,好比,对象动态的添加到这个做用域链这个上下文执行期间,经过 with--对象,或捕获异常对象。prototype
当去查找某个标识符时,做用域链会从当前的激活对象开始查找,并(若是在自身的激活对象里没找到的话)继续向上查找,重复code
下去,同原型链同样。对象
var x = 10; (function foo(){ var y = 20; (function bar(){ var z = 30; /* x,y 是自由变量, 在bar的做用域链中, 他们会被查到在接下 来的对象(继bar的激 活对象) */ consloe.log( x + y + z ); })(); })()
咱们将会使用内部属性__parent__来链接做用域对象,这个内部属性会引用到这个做用域链的下个对象。另一种现实多是经过数组。blog
经过__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里这个是直接与做用域链相关的。