閉包初窺

  不久前的面試中,面試官開門見山問我閉包是什麼,我啞然。就像this同樣,可能給我幾道關於this的題目我會作,可是要我說說什麼是this,我還真不知道從何提及,爲了face之後一樣的問題,查閱了一些資料在此簡單作下記錄。誠然,樓主對於閉包的理解還處在初級階段...面試

  簡單來講閉包擁有三個特性:閉包

1.函數嵌套函數
2.函數內部能夠引用外部的參數和變量
3.參數和變量不會被垃圾回收機制回收模塊化

  閉包是指有權訪問另外一個函數做用域中的變量的函數,建立閉包的最多見的方式就是在一個函數內建立另外一個函數,經過另外一個函數訪問這個函數的局部變量。使用閉包有一個優勢,也是它的缺點,就是能夠把局部變量駐留在內存中,能夠避免使用全局變量。全局變量在每一個模塊均可調用,這勢必將是災難性的。(因此推薦使用私有的,封裝的局部變量。)通常函數執行完畢後,局部活動對象就被銷燬,內存中僅僅保存全局做用域。但閉包的狀況不一樣!函數

  我以爲這段說明也很精彩:js裏的函數在運行結束以後,全部的過程當中產生的變量都會被銷燬(銷燬原則是無引用)
但在js的函數A裏定義一個函數B並在外部引用時,這條引用鏈上的變量都不會銷燬(即便A已經運行結束),這個函數B就叫作一個閉包。this

function fn() {
  var a = 0;
  function f() {
    console.log(a++);
  }
  return f;
}

var b = fn();
b();  // 0
b();  // 1
b();  // 2

  接着來看上面的例子,這是一段經典的閉包代碼,咱們看看代碼都幹了些什麼。spa

  首先要明確f函數便是所謂的閉包,咱們看到它嵌套在fn函數內,並且訪問了外部的變量a,同時console的結果也證實了變量a貯存在了內存中!爲何會這樣呢?緣由在於f被賦予給了一個全局變量b,致使始終存在在內存中,而f的存在必須依賴於fn,這致使fn也始終存在在內存中,因而變量a不會在執行後被垃圾回收機制回收。以上例子很好地避免了全局變量的使用,避免了全局變量的污染。code

  閉包還有什麼用?繼續一個經典的例子:對象

<ul>
  <li>0</li>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
</ul>
<script>
  var lis = document.getElementsByTagName('li');
  for(var i = 0; i < lis.length; i++) {
    ~function(i) {
      lis[i].onclick = function() {
        alert(i)
      };
    }(i)
  }
</script>

  咱們都知道不使用閉包的話,每一個li彈出的數字會是同樣的,這時的閉包就能把i的值儲存在內存中。blog

  閉包還可用於模塊化代碼,減小全局變量的污染:ip

var abc = (function(){ //abc爲外部匿名函數的返回值
  var a = 1;
  return function(){
    a++;
    alert(a);
  }
})();

abc(); //2     
abc(); //3

  閉包還可用於設置私有成員:

var obj = function(){
  var num = 0;
  function a() {
    num++;
    return num;
  }

  function b() {
    num++;
    return num;
  }

  return {
    a: a,
    b: b
  }
}();

console.log(obj.a()); // 1
console.log(obj.b()); // 2

  這樣就沒法修改num的值了,保護了私有成員。

  我的感受閉包和當即執行函數有着剪不斷理還亂的關係啊...

  樓主對於閉包的理解暫時到這裏了,若有不對或者補充之處還望留言~

相關文章
相關標籤/搜索