《JavaScript設計模式與開發實踐》之閉包和高階函數

閉包和高階函數

  • 函數式語言的鼻祖是 LISP
  • JavaScript在設計之初參考了 LISP兩大方言之一的 Scheme,引入了 Lambda表達式、閉包、高階函數等特性。

閉包

閉包的形成與變量的作用域以及變量的生存周期密切相關。

變量的作用域

  • 變量的作用域,就是指變量的有效范圍。
  • 變量的搜索是從內到外而非從外到內的。

變量的生命周期

  • 對于全局變量來說,全局變量的生存周期當然是永久的,除非我們主動銷毀這個全局變量。
  • 對于局部變量來說,當退出函數時,它們都會隨著函數調用的結束而被銷毀。
 var foo = function() {
   var a = 1;
   return function() {
     a++;
     alert(a);
   }
 };

var f = foo();
f(); // 輸出:2
f(); // 輸出:3
f(); // 輸出:4
f(); // 輸出:5

變量f 返回了一個匿名函數的引用,它可以訪問到 foo()被調用時產生的環境,而局部變量a 一直處在這個環境里。既然局部變量所在的環境還能被外界訪問,這個局部變量就有了不被銷毀的理由。在這里產生了一個閉包結構,局部變量的生命看起來被延續了。

另一個經典例子,我們通過循環來給每個 div 綁定 onclick 事件,按照索引順序,點擊第 1個 div 時彈出0,點擊第 2個 div 時彈出 1,以此類推。

<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
var nodes = document.getElementsByTagName( 'div' );
for ( var i = 0, len = nodes.length; i < len; i++ ){
      nodes[ i ].onclick = function(){
      alert ( i );
    }
};

把每次循環的 i 值都封閉起來。當在事件函數中順著作用域鏈中從內到外查找變量 i 時,會先找到被封閉在閉包環境中的 i

閉包的更多作用

封裝變量

閉包可以幫助把一些不需要暴露在全局的變量封裝成“私有變量”。

 var mult = function() {
   var a = 2;
   for (var i = 0, l = arguments.length; i < l; i++) {
     a = a * arguments[i];
   }
   return a;
 };
console.log(mult(1, 2, 3)); //輸出 12
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容