天天看點

06-JavaScript作用域及作用域鍊

一、作用域

  • 作用域定義:變量(變量的作用域又稱為上下文)和函數生效的區域。
  • [ [scopes] ]:每個JavaScript函數都是一個對象,對象中有些屬性我們可以通路,但有些是不可以通路的,這些屬性僅供JavaScript引擎讀取。[ [scopes] ]就是其中一個。[ [scopes] ] 指的就是我們所說的作用域,其中存儲了運作期上下文的集合(上篇文章提到的AO和GO,詳情移步JS預編譯)
  • 運作期上下文:當一個函數在執行的時候,會建立一個執行期上下文。一個執行期上下文定義了一個函數執行時的環境,函數每次執行時所對應的的執行上下文是不同的,是以多次調用函數時會導緻建立多個執行上下文,當函數執行完畢時,執行上下文被銷毀。
06-JavaScript作用域及作用域鍊
需要注意的是我們可以在浏覽器的控制台中看到該屬性,但是我們是無法通路的。

 二、作用域鍊

  • 作用域鍊:[ [scopes] ]中所存儲的執行期上下文的集合,這個集合呈鍊式結構,我們把這種鍊式連接配接叫做作用域鍊。
  • 查找變量:從作用域鍊的頂端依次向下查找

 三、代碼分析

function f1(){         
            function f2(){
                var b = 2;
                console.dir(f2);
            }
             var a = 1;      
             f2();             
        }

        var c = 3;
        f1();
           

這時列印出來的是f2函數的結構。我們看一下其中它上面的 [ [scopes] ]:

06-JavaScript作用域及作用域鍊
我們來分析一下代碼執行時發生了什麼:
  1. 當 f1 函數聲明時  f1. [ [ scopes ] ]  0: => GO對象
  2. 當 f1 函數被調用執行時  f1. [ [ scopes ] ]  0 :=> f1 AO對象

                                                                           1:=> GO對象

    1.當 f2 函數聲明時 f2. [ [ scopes ] ]  0 :=> f1 AO對象

                                                             1:=> GO對象

    2.當 f2 函數調用執行時 f2. [ [ scopes ] ]  0 :=> f2 AO對象

                                                                    1:=> f1 AO對象

                                                                    2:=> GO 對象

因為 f2 函數時在 f1中定義的是以 f2 在聲明時它的作用域鍊0的位置是 f1 的AO對象,其次才是全局GO對象。

他們之間的指向,隻是指針的位址,是以當執行期上下文銷毀時,銷毀的其實是他們之間的連線也就是位址(指針),而被建立出來的AO對象包括AO對象内挂載的屬性以及值還是存在的,隻是現在的函數名無法指向這塊AO對象的位址了。