JavaScript 系列之閉包(二)

這是我參與8月更文挑戰的第9天,活動詳情查看:8月更文挑戰緩存

3、閉包的應用

3.1 利用閉包實現模塊化開發

3.1.1 模塊模式

封裝了私有變量和方法,而只暴露了一個接口供外部調用。markdown

function cool() {
  let a = "cool";
  let b = [1, 2, 3];
  function doA() {
    console.log(a);
  }
  function doB() {
    console.log(b.join("!"));
  }
  return {
    doA: doA,
    doB: doB,
  };
}
let foo = cool();
foo.doA(); //cool
foo.doB(); //1!2!3
複製代碼

cool() 返回一個用對象字面量語法表示的對象閉包

這個對象中含有內部函數而不是內部數據變量的引用,保持內部數據變量是隱藏且私有的狀態。app

doA()doB()函數具備涵蓋模塊實例內部做用域的閉包,當經過返回一個含有屬性引用的對象的方式來將函數傳到詞法做用域外時,已經建立了閉包。ide

  • 模塊模式必需要有外部的封閉函數,該函數必須至少被調用一次(每次調用都會建立一個新的模塊實例)
  • 封閉函數必須返回至少一個內部函數,這樣內部函數才能在私有做用域中造成閉包,而且能夠訪問或者修改私有狀態。

3.1.2 單例模式

let foo = (function cool() {
  let a = "cool";
  let b = [1, 2, 3];
  function doA() {
    console.log(a);
  }
  function doB() {
    console.log(b.join("!"));
  }
  return {
    doA: doA,
    doB: doB,
  };
})();
foo.doA(); //cool
foo.doB(); //1!2!3
複製代碼

將模塊函數轉換成立 IIFE,當即調用這個函數並將返回值直接賦值給單例的模塊實例標識符 foo模塊化

3.2 利用閉包模擬塊級做用域

var data = [];
for (var i = 0; i < 3; i++) {
  (function () {
    var j = i;
    data[j] = function () {
      console.log(j);
    };
  })();
}
data[0](); //0
data[1](); //1
data[2](); //2
複製代碼

4、閉包的優缺點

4.1 優勢

  1. 緩存。將變量隱藏起來不被 GC 回收。
  2. 實現柯里化。利用閉包特性完成柯里化。

咱們能夠經過閉包來實現一個計數器,而不用擔憂全局變量的污染:函數

function foo() {
  let num = 0;
  return function() {
    num++;
    console.log(num);
  };
}
const f = foo();
f(); // 1
f(); // 2
複製代碼

4.2 缺點

  1. 內存消耗。閉包產生的變量沒法被銷燬。
  2. 性能問題。因爲閉包內部變量優先級高於外部變量,因此須要多查找做用域鏈的一個層次,必定程度影響查找速度。
function assignEvent() {
  let id = "123";
  document.getElementById("save-btn").onclick = function (event) {
    saveDocument(id);
  };
}
複製代碼

image.png

相關文章
相關標籤/搜索