iT邦幫忙

0

JavaScript 的閉包

  • 分享至 

  • xImage
  •  

在 JavaScript 中,閉包(Closure) 是指一個函數能夠記住並訪問它的詞法作用域(Lexical Scope),即使這個函數在其作用域之外被執行。閉包的特性使得它在以下情況下非常有用:

適用情況

  1. 封裝私有數據:在 JavaScript 中沒有內建的「私有屬性」,閉包可以模擬這種行為,讓一些數據無法被外部直接訪問。
  2. 創建工廠函數(Factory Functions):使用閉包構造多個具有相似行為的對象。
  3. 模擬狀態(Stateful Functions):閉包允許函數在多次調用之間保存數據,適合用於實現累加器等功能。
  4. 處理異步操作:閉包可以讓回調函數記住當前的上下文,這在事件處理或異步操作中非常重要。
  5. 函數柯里化(Currying):閉包用於將多參數函數轉化為單參數函數鏈式調用。

閉包範例

範例 1:封裝私有數據

使用閉包模擬私有屬性,讓外部無法直接修改內部數據。

function createCounter() {
  let count = 0; // 私有變量
  return {
    increment() {
      count++;
    },
    decrement() {
      count--;
    },
    getCount() {
      return count;
    }
  };
}

const counter = createCounter();
console.log(counter.getCount()); // 0
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2
counter.decrement();
console.log(counter.getCount()); // 1

範例 2:模擬狀態的工廠函數

使用閉包創建具有不同初始狀態的計數器。

function createCounter(initialValue) {
  let count = initialValue;
  return function () {
    count++;
    return count;
  };
}

const counterA = createCounter(5);
const counterB = createCounter(10);

console.log(counterA()); // 6
console.log(counterA()); // 7
console.log(counterB()); // 11
console.log(counterB()); // 12

範例 3:處理異步操作

閉包在回調函數中保存上下文數據。

function fetchData(url) {
  let cache = {};

  return function () {
    if (cache[url]) {
      console.log("Fetching from cache:", cache[url]);
      return cache[url];
    } else {
      console.log("Fetching from server...");
      const data = `Data from ${url}`; // 模擬服務器數據
      cache[url] = data;
      return data;
    }
  };
}

const getUserData = fetchData("https://api.example.com/user");
console.log(getUserData()); // Fetching from server...
console.log(getUserData()); // Fetching from cache: Data from https://api.example.com/user

範例 4:函數柯里化

閉包讓函數變成更靈活的形式。

function multiply(a) {
  return function (b) {
    return a * b;
  };
}

const double = multiply(2); // 創建一個函數,固定第一個參數為 2
const triple = multiply(3); // 創建一個函數,固定第一個參數為 3

console.log(double(4)); // 8
console.log(triple(4)); // 12

範例 5:事件處理中的閉包

閉包可以讓事件處理器記住它綁定時的上下文。

function setupButtons() {
  for (let i = 1; i <= 3; i++) {
    document.getElementById(`button${i}`).addEventListener("click", function () {
      console.log(`Button ${i} clicked!`);
    });
  }
}

在這裡,閉包使得每個事件處理器記住了綁定時的 i 值。

注意事項

  1. 內存占用:由於閉包引用了外部變量,這些變量無法被垃圾回收器回收,可能導致內存泄漏。需要在不需要時明確清理閉包引用。
  2. 可能引起意料之外的行為:在循環中使用閉包時需要注意作用域問題,避免共用同一個變量。

總結

閉包適合用於:

  • 封裝私有數據
  • 保存狀態
  • 創建靈活的工廠函數或柯里化
  • 處理異步操作和事件綁定
    閉包是 JavaScript 中強大而靈活的特性,適用於需要「記住某些信息」的場景。

圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 則留言

0
junelin2001
iT邦新手 5 級 ‧ 2024-12-12 09:41:47

謝謝 ChatGPT 老師

sharongao iT邦新手 5 級 ‧ 2024-12-12 23:03:43 檢舉

ChatGPT 真的好用

我要留言

立即登入留言