JavaScript(六)作用域、作用域鍊
一、運作期上下文
- 定義: 當函數執行時,會建立一個稱為執行期上下文的内部對象。一個執行 期上下文定義了一個函數執行時的環境,函數每次執行時對應的執 行上下文都是獨一無二的。也就是說,多次調用一個函數會導緻建立多個執 行上下文,當函數執行完畢,它所産生的執行上下文被銷毀。
- 特别的是GO 是不在函數内函數建立前的運作期上下文,其餘都是AO。也即是GO時,其上下文時全局的;其他函數在執行時運作期上下文(如字面意思)為函數内。
- 運作期上下文即為上一篇文章涉及的GO、AO。
- 不過,正如上述所說,函數的每次執行會被建立運作期上下文,每次執行完也會被銷毀。
- 假如在連續調用兩次demo(),例如
//...任意前文
demo();//在調用時會建立一個AO,調用完銷毀。
demo();//調用時,會建立一個AO,調用完銷毀。
//注意! 倆個AO不為同一個
//... 任意後文
- 那麼在函數内如果調用一個函數呢,我們說過函數在執行時就會建立獨一無二的運作其上下文(也即是GO\AO),那麼對于這兩個建立和銷毀是如何呢?
//在這裡相當于有一個棧(先進後出,後進先出)
// 為了友善表示我們把外層函數執行時建立的AO稱為AO(外),内層則為AO(内)--(個人為了友善了解使用)
//那麼過程是這樣的:
// AO(外)-建立
// AO(内)-建立
// AO(内)-銷毀
// AO(外)-銷毀
//這樣看起來就是函數執行順序和執行完順序對應着建立和銷毀,的确是這樣。
demo(demo());
- 運作期上下文為函數執行時建立,那麼對于函數内部存在全局變量,或者函數外部的變量,以及為何如果一個變量在函數内外均有定義,為何在函數内輸出該值的話是最近的内部的呢?這個過程是怎麼樣的?以下作用域會講解。
二、作用域以及作用域鍊
- [[scope]]: 每個JavaScript函數都是一個對象,對象中有些屬性我們可以直接通路,但有些不可以。可以屬性僅供JavaScript引起存取。[[scope]]就是其中一個。
- [[scope]]指的是我們所說的作用域,其中存儲了運作期的上下問的集合。
- [[scope]]中所存儲的執行期上下文對象的集合,這個集合是成鍊式連結,我們把這種鍊式連結叫做作用域鍊。
示例一
function a() {
}
var glob = 100;
a();
示例一在執行時,有以下步驟
Step1: a 函數被定義時,發生以下過程
由上圖可見,a的[[scope]]放了一個scope chain 值連結清單的引用,scope chain連結清單内, 0 位置為放GO對象的一個引用,其具體内容也就是上一篇文章介紹的預編譯後的GO的情況(部分屬性未介紹)
Step2: a 函數被執行時,發生以下過程
當函數執行時,會産生該函數的運作期上下文AO,然後正如上圖的 AO,然後進入scope chain (具有棧的性質),AO會入棧,此時0的值為 AO對象的引用,1為GO。
當查找變量時, 從0的對應的表内先開始查找,之後再到1 ,也就是從作用域的頂端以此向下查找。
三、 拓展:
若a函數記憶體在b函數那麼情況時怎麼樣的呢?
首先是a定義,a執行,後在a中執行b前,b會繼承a的scope chain的所有内容,然後當執行b時(本文中所有執行時,均為執行的前一刻),會生成b的運作期上下文,可以為了形象記為bOA,然後進入scope chain,
此時b[[scope]]内容是 :
0 -->bOA
1 -->aOA
2 --> GA
此時,a[[scope]]内容是:
0 -->aOA
1 --> GA
- 其中,當 b的函數執行導緻aOA值發生變化的話,a[[scope]]也會變化,在scope chain 裡面隻是引用,可以想象為連線。
- 當該次b執行完成後,bOA就會被銷毀。
聲明: 學習資源為 渡一教育-Web前端開發 ,圖檔也出于此網址
以上,此為本人學習過程中的筆記,可能因為能力不足存在一些不足,還請大家多多包涵和給予建議,共同進步。如有問題,敬請私信。