天天看點

JavaScript入門(六)作用域、作用域鍊JavaScript(六)作用域、作用域鍊

JavaScript(六)作用域、作用域鍊

一、運作期上下文

  • 定義: 當函數執行時,會建立一個稱為執行期上下文的内部對象。一個執行 期上下文定義了一個函數執行時的環境,函數每次執行時對應的執 行上下文都是獨一無二的。也就是說,多次調用一個函數會導緻建立多個執 行上下文,當函數執行完畢,它所産生的執行上下文被銷毀。
  • 特别的是GO 是不在函數内函數建立前的運作期上下文,其餘都是AO。也即是GO時,其上下文時全局的;其他函數在執行時運作期上下文(如字面意思)為函數内。
  • 運作期上下文即為上一篇文章涉及的GO、AO。
  • 不過,正如上述所說,函數的每次執行會被建立運作期上下文,每次執行完也會被銷毀。
  1. 假如在連續調用兩次demo(),例如
//...任意前文
    demo();//在調用時會建立一個AO,調用完銷毀。
    demo();//調用時,會建立一個AO,調用完銷毀。
    //注意! 倆個AO不為同一個
//... 任意後文
           
  1. 那麼在函數内如果調用一個函數呢,我們說過函數在執行時就會建立獨一無二的運作其上下文(也即是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 函數被定義時,發生以下過程

JavaScript入門(六)作用域、作用域鍊JavaScript(六)作用域、作用域鍊

由上圖可見,a的[[scope]]放了一個scope chain 值連結清單的引用,scope chain連結清單内, 0 位置為放GO對象的一個引用,其具體内容也就是上一篇文章介紹的預編譯後的GO的情況(部分屬性未介紹)

Step2: a 函數被執行時,發生以下過程

JavaScript入門(六)作用域、作用域鍊JavaScript(六)作用域、作用域鍊

當函數執行時,會産生該函數的運作期上下文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前端開發 ,圖檔也出于此網址

以上,此為本人學習過程中的筆記,可能因為能力不足存在一些不足,還請大家多多包涵和給予建議,共同進步。如有問題,敬請私信。

繼續閱讀