1. 程式人生 > >javascript 閉包詳解

javascript 閉包詳解

一、什麼是匿名函式

建立一個函式並將它賦值給變數functionName,這種情況下建立的函式,即匿名函式。(函式表示式就是匿名函式)

 

二、閉包

1.什麼是閉包?

閉包就是能夠讀取其他函式內部變數的函式。

只有函式內部的子函式才能讀取區域性變數,因此可以把閉包簡單理解成“定義在一個函式內部的函式”。

我們只要把f2作為返回值,我們不就可以在f1外部讀取它的內部變量了嗎!

複製程式碼
function f1 () {
    var num = 1;
    function f2() {
        console.log(num)
    }
    return f2;
}
var result = f1();
console.log(result());  //1
複製程式碼
 

2、閉包的用途

閉包可以用在許多地方。它的最大用處有兩個,一個是前面提到的可以讀取函式內部的變數,另一個就是讓這些變數的值始終保持在記憶體中。

複製程式碼
function f1 () {
    var num = 1;
    function f2() {
        console.log(++num)
    }
    return f2;
}
var result = f1();
console.log(result());  //2
console.log(result());  //3
複製程式碼

原因就在於f1是f2的父函式,而f2的作用域綁上了f1函式的活動物件

和全域性變數物件(全家物件只有在網頁關閉時才會銷燬),這導致f2始終在記憶體中,而f2的存在依賴於f1,因此f1也始終在記憶體中,不會在呼叫結束後,被垃圾回收機制回收。

 

3.使用閉包的注意點

1)由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除。

2)閉包會在父函式外部,改變父函式內部變數的值。所以,如果你把父函式當作物件(object)使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函式內部變數的值。

複製程式碼
 var name = "The Window";
  var object = {
    name : "My Object",
    getNameFunc : function(){
      return function(){
                return this.name;   
     };   
    }
};
alert(object.getNameFunc()());  //The Window  匿名函式的執行環境具有全域性性,因此其this物件通常指向window。
複製程式碼

 

4.閉包的應用場景

1.使用閉包代替全域性變數

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 //全域性變數,test1是全域性變數 var  test1=111; function  outer(){      console.log(test1); } outer();  //111 console.log(test1);  //111   //閉包,test2是區域性變數,這是閉包的目的 //我們經常在小範圍使用全域性變數,這個時候就可以使用閉包來代替。 ( function (){      var  test2=222;      function  test(){          console.log( "測試閉包:" +test2);      }      test();  //測試閉包:222 } )(); console.log(test2);  //未定義,這裡就訪問不到test2 再如:
1 2 3 4 5 6 ( function (){      var  now =  new  Date();      if (now.getMonth() == 0 && now.getDate() == 1){          console.log( "Happy new year!" )      } })();

 

2.函式外或在其他函式中訪問某一函式內部的引數

1 2 3 4 5 6 7 8 9 10 function  test () {      var  num = 1;      function  other() {          console.log(++num)      }      return  other; } var  result = test(); console.log(result());   //2 console.log(result());   //3

  

3.利用閉包模仿塊級作用域

1 2 3 4 5 6 7 ( function (){      for ( var  i =0;i<5;i++){          console.log(i)      }      console.log(i);  //5  //本身只是到4,但這個地方還是訪問到了,所有輸出了5 })(); console.log(i);  //undefined  //利用閉包後,便形成了塊級作用域,讓外面訪問不到了。