JavaScript 閉包基本指南

前端先鋒發表於2019-05-06

翻譯:瘋狂的技術宅 medium.freecodecamp.org/a-basic-gui…

Photo by Austin Distel on Unsplash

閉包是函式建立時作用域內所有變數的集合。要使用閉包,需要在另一個函式中建立一個函式,這種函式被稱為巢狀函式。內部函式可以訪問外部函式作用域中的變數(依靠閉包可以訪問外部函式作用域),即使在返回外部函式之後也是如此。每次建立巢狀函式時都會建立閉包。

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

通常,有兩種型別的作用域:

  • 全域性作用域
  • 區域性作用域

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

因此,JavaScript有函式作用域。沒有塊作用域。

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物件。

img

由於內部函式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功能可以實現這些功能。

結論

閉包是外部函式中的變數集合,它提供對內部函式作用域的訪問以保護全域性名稱空間。

閉包使開發人員能夠編寫像面嚮物件語言那樣的乾淨程式碼,這些程式碼不會混淆全域性和區域性變數的名稱。

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

歡迎關注前端公眾號【前端先鋒】,獲取更多前端乾貨。

JavaScript 閉包基本指南

相關文章