js高程之做用域

咱們知道js執行環境有全局環境(window)和局部環境(通常指函數環境)之分。前端

        var num = 1;
        function calc(){
            var num = 2;
        }

上述代碼,雖然有兩個num變量,可是他們所在的執行環境倒是不一樣的,第一個num執行環境是全局執行環境(window),第二個執行環境是函數執行環境(calc函數)。瀏覽器

某個執行環境中的全部代碼執行完畢後,該環境被銷燬,保存在其中的全部變量和函數定義也隨之銷燬(全局執行環境直到應用程序退 出——例如關閉網頁或瀏覽器——時纔會被銷燬)。函數

每一個函數都有本身的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。 而在函數執行以後,棧將其環境彈出,把控制權返回給以前的執行環境。spa

1、環境棧3d

隨着程序按前後順序執行的時候,會生成各類環境(一個全局環境和n個函數環境),這些環境是由一個環境棧維護的,看代碼:code

 1         var sum = 0;
 2         function a(){
 3             var sum = 1;
 4             function b(){
 5                 var sum = 2;
 6                 function c(){
 7                     var sum = 3;
 8                     console.log(sum);
 9                 }
10                 c();
11             }
12             b();
13         }
14         a();

對應環境棧:對象

2、做用域鏈blog

當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈(scope chain)。做用域鏈的用途,是保證對執行環境有權訪問的全部變量和函數的有序訪問。做用域鏈的前端,始終都是當前執行的代碼所在環境的變量對象。ip

好比說,在c函數環境裏有一句:內存

console.log(sum);

這時,會在c函數環境的做用域鏈中搜索這個標識符(sum),搜索過程始終從做用域鏈的前端開始, 而後逐級地向後回溯,直至找到標識符爲止(若是找不到標識符,一般會致使錯誤發生)。

很幸運,一次就找到了,c環境裏就有sum標識符,那麼就直接輸出他的值(3);

若是c環境找不到,會繼續依次往下找:

 

好比下面的代碼將會輸出 1

        var sum = 0;
        function a(){
            var sum = 1;
            function b(){
                function c(){
                    console.log(sum);
                }
                c();
            }
            b();
        }
        a();

3、塊級做用域

在ES6以前,是沒有塊級做用域的,請看代碼

        for(var i = 1;i<10;i++){
            /* dosomething() */
        }
        console.log(i);//10


        {
            var name = 'Jack';
        }
        console.log(name);//Jack

        if(true){
            var age = 18;
        }
        console.log(age);//18

若是是在 C、C++或 Java 中:

for 語句初始化變量的表達式所定義的變量,只會存在於循環的環境之中;

由花括號封閉的代碼塊都有本身的做用域,變量會在 if 語句執行完畢後被銷燬;

可是,在JavaScript中:

由 for 語句建立的變量 i 即便在 for 循環執行結束後,也依舊會存在 於循環外部的執行環境中;

if 語句中的變量聲明會將變量添加到當前的執行環境。

在ES6以後,提供了塊級做用域申明關鍵字 let ,let申明的變量只能在 { } 所在的做用域內使用 :

        for(let i = 1;i<10;i++){
            /* dosomething() */
        }
        console.log(i);


        {
            let name = 'Jack';
        }
        console.log(name);

        if(true){
            let age = 18;
        }
        console.log(age);

控制檯輸出:

4、垃圾收集機制

正如你們所熟知的,咱們寫的每個變量都是存在於內存中的(具體是棧內存),可是系統內存畢竟有限,不能一直寫一直往內存裏面放,這尼瑪分分鐘內存泄漏。

因此對於那些已經沒用的變量(垃圾)須要進行清除處理。

垃圾收集器必須跟蹤哪一個變量有用哪一個變量沒用,對於再也不有用的變量打上標記,以備未來收 回其佔用的內存。

用於標識無用變量的策略可能會因實現而異,但具體到瀏覽器中的實現,則一般有兩 個策略。

Ⅰ.標記清除

當變量進入環境(例如,在函 數中聲明一個變量)時,就將這個變量標記爲「進入環境」。

而當變量離開環境時,則將其 標記爲「離開環境」。

從邏輯上講,永遠不能釋放進入環境的變量所佔用的內存,由於只要執行流進入相應的環境,就可能會用到它們。

相關文章
相關標籤/搜索