JavaScript 中的閉包和事件委託

最小生成树發表於2024-08-02

包 (Closures)

閉包是 JavaScript 中一個非常強大的特性,它允許函式訪問其外部作用域中的變數,即使在該函式被呼叫時,外部作用域已經執行完畢。閉包可以幫助我們實現資料的私有化、封裝和模組化,使程式碼更簡潔、易讀和可維護。

閉包的定義

簡單來說,閉包是指有權訪問另一個函式作用域中變數的函式。

function outerFunction() {
    let outerVariable = "I am outside!";

    function innerFunction() {
        console.log(outerVariable); // innerFunction 可以訪問 outerVariable
    }

    return innerFunction;
}

const closure = outerFunction();
closure(); // 輸出: I am outside!

在上述例子中,innerFunction 就是一個閉包,它可以訪問 outerFunction 中的 outerVariable,即使 outerFunction 已經執行完畢。

閉包的應用
  1. 資料私有化
function createCounter() {
    let count = 0;
    return function() {
        count++;
        return count;
    };
}

const counter = createCounter();
console.log(counter()); // 輸出: 1
console.log(counter()); // 輸出: 2
console.log(counter()); // 輸出: 3

在這個例子中,count 變數被封裝在 createCounter 函式的作用域內,只能透過返回的閉包函式進行訪問和修改。

  1. 模擬塊級作用域

在 ES6 之前,JavaScript 沒有塊級作用域,我們可以使用閉包來模擬塊級作用域。

for (var i = 1; i <= 3; i++) {
    (function(i) {
        setTimeout(function() {
            console.log(i);
        }, i * 1000);
    })(i);
}
// 輸出: 1, 2, 3 (每隔一秒輸出一個數字)

透過立即執行函式表示式 (IIFE),為每次迴圈建立了一個新的作用域,從而使 setTimeout 中的 i 保持正確的值。

事件委託 (Event Delegation)

事件委託是一種利用事件冒泡機制,將事件監聽器新增到父元素上,從而管理多個子元素事件處理的一種技術。它可以減少記憶體佔用,提高效能,特別是在需要處理大量動態生成的子元素事件時非常有用。

事件委託的定義

透過將事件監聽器新增到父元素上,當子元素的事件被觸發時,事件會冒泡到父元素,由父元素的事件監聽器進行處理。

<ul id="parent">
    <li>Item 1</li>
    <li>Item 2</li>
    <li>Item 3</li>
</ul>
document.getElementById('parent').addEventListener('click', function(event) {
    if (event.target.tagName === 'LI') {
        console.log(event.target.innerText); // 輸出點選的列表項的文字
    }
});

在這個例子中,我們只為 ul 元素新增了一個點選事件監聽器,但可以處理所有 li 元素的點選事件。

事件委託的應用
  1. 動態內容

當頁面上有大量動態生成的元素時,使用事件委託可以簡化事件處理。

const list = document.getElementById('parent');
document.getElementById('addItem').addEventListener('click', function() {
    const newItem = document.createElement('li');
    newItem.innerText = `Item ${list.children.length + 1}`;
    list.appendChild(newItem);
});

  1. 提高效能

當需要為大量元素新增事件監聽器時,事件委託可以顯著提高效能,因為只需要為父元素新增一個事件監聽器,而不是為每個子元素新增。

<button id="addItem">Add Item</button>
<ul id="parent">
    <!-- 動態生成的列表項 -->
</ul>

總結

閉包能夠訪問外部函式作用域中的變數,從而實現資料私有化和封裝;

事件委託利用事件冒泡機制,透過將事件監聽器新增到父元素上,簡化了事件處理,提高了效能。

相關文章