JavaScript的靜態做用域

  • JS是靜態做用域。比較下面兩段代碼:
  • 代碼一
    function f(){
        alert(x);
    }
    
    function g(){
        var x = 100;
        f();
    }
    
    g()
  • 代碼二
    function g(){
        var x =  100;
        function f(){
            alert(x);
        }
        f();
    }
    
    g();
  • 代碼一會報錯:顯示x沒有defined;代碼二alert:100;
  • 代碼一報錯緣由:函數在建立(聲明)的時候首先向內部屬性[[scope]]中壓入當前的環境指針,代碼一的狀況兩個函數都首先壓入window;而在函數執行/調用的時候,則會在[[scope]]頂部壓入本身的環境指針,指向本身的活動對象。如此一來,f()的[[scope]]中並無指向g()的指針,而是直接指向window,而它自己的環境和window並無爲x定義,因此會報錯。
  • 代碼二:按照上述的原理,f的scope依次指向:f()自己活動對象、g()的活動對象、(g的活動對象又指向)window對象;造成了一條三層的做用域鏈,而g()執行的時候,內部的f()一樣執行,並在g的活動對象中找到x的定義和值,即alert:100;
  • 閉包通常採用函數表達式的方式建立,執行到此語句的時候同時聲明並賦值,至關於代碼二的狀況。所以很容易與外部環境造成做用域鏈。
    注意到若是用new Function()建立函數,scope[0]會指向window。
  • 代碼一,若是在聲明一個全局變量:var x = 100,則代碼一會alert:100。
相關文章
相關標籤/搜索