做用域鏈是對象的集合,在代碼的上下文裏,他們提供給標識符進行查找的。數組
這個規則也很簡單,相似於原型鏈:若是一個變量在它本身的做用域(本身的變量/激活對象)未找到的話,它會繼續找它的閉包
父變量對象,依次類推。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裏這個是直接與做用域鏈相關的。