JavaScript 閉包指南

翻譯:瘋狂的技術宅
https://medium.freecodecamp.o...

本文首發微信公衆號:前端先鋒
歡迎關注,天天都給你推送新鮮的前端技術文章javascript


閉包是函數建立時做用域內全部變量的集合。要使用閉包,須要在另外一個函數中建立一個函數,這種函數被稱爲嵌套函數。內部函數能夠訪問外部函數做用域中的變量(依靠閉包能夠訪問外部函數做用域),即便在返回外部函數以後也是如此。每次建立嵌套函數時都會建立閉包。前端

在繼續瞭解閉包以前,首先了解一下JavaScript中的做用域鏈。java

一般,有兩種類型的做用域:程序員

  • 全局做用域
  • 局部做用域

在JavaScript中,函數內部的變量在外部是不可見的。可是在塊內的變量(if 或 while 之類)是可見的。面試

所以,JavaScript有函數做用域。沒有塊做用域。segmentfault

var a = 10;
function app(){
   var b = 2;
   console.log(a); // 10
   console.log(b); // 2
}
console.log(b); //   ReferenceError: b is not defined
app();

正像咱們已知的那樣,a 是一個全局變量而且 b 是一個局部變量,它是app函數獨有的數組

咱們沒法從局部做用域以外獲取局部變量的值。瀏覽器

使用嵌套函數 —— 函數內部的函數

var a = 10;
function app(){
     var b = 2;
     var d = 3;
  function add(){
     var c = a + b;
   }
 return add;
}
var x = app();
console.dir(x);

在這裏app是父函數,add函數是子函數。微信

  • 代碼中沒有用 console.log 而是用了console.dir 來輸出指定JavaScript對象的全部屬性,這有助於開發人員獲取對象的屬性
  • 變量 x 被分配給app函數,app函數返回add函數。所以咱們能夠看到add函數的全部對象屬性。

若是在瀏覽器中查看控制檯,能夠在Scopes數組中看到Closure對象。多線程

clipboard.png

因爲內部函數add訪問外部函數變量b 和 d,所以這2個變量將被添加到Closure對象中以供引用。

讓咱們看看下一個例子:

var a = 10;
var startFunc;
function app(){
      var b = 2;
   function add(){
      var c = a + b;
      console.log(c);
   }
   startFunc = add();
}
app(); // 調用app函數
startFunc; // 上面調用的app函數會將add函數賦值給startFunc並輸出c的值
  • 一個名爲 startFunc 的全局函數被分配給add函數,該函數是 app 函數的子函數。
  • 這隻有在調用 app 函數後纔有可能,不然 startFunc 將做爲全局變量而不被分配任何值

在JavaScript中使用閉包

不少人在編碼時會用到閉包,可是不明白用它的緣由。 JavaScript沒有像其餘面嚮對象語言同樣的訪問修飾符,例如 private,public,protected。不過咱們能夠利用函數來保護命名空間免受外部代碼使用的影響。

特別是在函數中,當即執行函數表達式(IIFE)是在聲明以後會當即執行的函數表達式。在聲明函數以後,你不須要去調用該函數。

IIFE的語法定義是:

(function(){
             //函數內部的變量和做用域
})();

舉個例子:

var studnetEnrollment = (function () {
    //私有變量,任何人都沒法改變
    //除了下面聲明的函數
     var count = 0;
     var prefix = "S";
    // 返回一個命名函數表達式
     function innerFunc() {
         count = count + 1;
         return prefix + count;
     };
 return innerFunc;
})();
var x = studnetEnrollment(); // S1
console.log(x);
var y = studnetEnrollment(); // S2 
console.log(y);

count和prefix是兩個私有變量,任何人都沒法進行更改,只能訪問內部函數(即代碼中的innerFunc)。只有名爲閉包的功能才能對此進行訪問。

  • 第一次調用studentEnrollment函數時,函數內的count變量由innerFunc函數遞增長1。
  • 第二次,增長上一個計數值,即 1 增長到 2
  • Closure功能能夠實現這些功能。

結論

閉包是外部函數中的變量集合,它提供對內部函數做用域的訪問以保護全局命名空間。

閉包使開發人員可以編寫像面嚮對象語言那樣的乾淨代碼,這些代碼不會混淆全局和局部變量的名稱。

編碼快樂...... !!!!!


本文首發微信公衆號:前端先鋒

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章

歡迎掃描二維碼關注公衆號,天天都給你推送新鮮的前端技術文章


歡迎繼續閱讀本專欄其它高贊文章:

相關文章
相關標籤/搜索