閉包、執行環境、做用域鏈

閉包是指有權訪問另外一個函數做用域中的變量的函數,建立的常見方式就是在一個函數內部建立另外一個函數。

咱們來理解下執行環境和做用域鏈:
     1.執行環境有全局執行環境和函數執行環境之分。
     2.每次進入一個新的執行環境,都會建立一個用於搜索變量和函數的做用域鏈。
     3.函數的局部環境不只有權訪問函數做用域中的變量,並且有權訪問其包含(父)環境,由底向上乃至全局環境。
     4.變量的執行環境有助於肯定應該什麼時候釋放內存。

執行環境和做用域鏈
function createComparisonFunction(propertyName){
     return function(object1,object2){
     var value1=object1[propertyName];
     var value2=object2[propertyName];
     
     if(value<value2){
          return -1;
     }else if(value1>value2){
          retutn 1; 
     }else{
         return 0; 
     }
     };
}
//建立函數
var compareNames=createComparisonFunction ("name");
//調用函數
var result=compareNames({name:"joey"},{name:"ross"});
//接觸對匿名函數的引用,用於釋放內存
compareNames=null;
由於只是用於本身增強理解,就直接把圖片放在這裏了,由於用於文字實在很難描述出來做用域鏈的關係。
值得一提的是,每一個執行環境都有表示變量的對象--變量對象,全局環境中的變量對象始終存在,而內部函數的局部環境變量則只在函數執行過程當中存在。
而在這個例子中,createComparisonFunction()的做用域鏈包含兩個變量對象,一個自己的活動對象,一個全局變量對象,而匿名函數的做用域鏈包含着三個對象變量,多了一個自身的閉包活動對象,外面訪問不進來,裏面卻能夠訪問外面,因此也包含外部函數的活動對象和全局變量對象,重要的是,當外部函數執行完畢以後,它的活動對象也不會被銷燬,由於匿名函數的做用域連接仍然在引用這個活動對象,換句話說,外部函數返回後,其執行環境會銷燬,可是它的活動對象依然留在內存中,知道匿名函數被銷燬,外部函數的活動對象纔會被銷燬。



閉包與變量
function create(){
     var result=new Array();
     for(var i=0; i<10, i++){
          result[i]=function(){
              return i
          }
     }
}
//藍色的全局變量對象,紅色的是create()函數活動對象,綠色的閉包的活動對象。

做用域鏈的這種配置機制引出一個值得注意的反作用, 閉包只能取得包含函數中任何變量的最後一個值。
上面這句話是重點,這個代碼我起初沒看懂的,反覆理解了以後才懂,這個函數會返回一個函數數組, [0(),1().....9()],從0到9,而函數返回的 i  值應該對應函數名稱,便是0()裏面返回0,1()裏面返回1,以此類推,實際上每一個函數返回的都是10,由於 create()這個函數的做用域鏈保存這這個函數的活動對象,活動對象有result,還有i,函數調用後,變量 i 的值已是10,而且保存在活動對象裏,此時閉包去引用的都是同一個 i 。
相關文章
相關標籤/搜索