包 (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
已經執行完畢。
閉包的應用
- 資料私有化:
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
函式的作用域內,只能透過返回的閉包函式進行訪問和修改。
- 模擬塊級作用域:
在 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
元素的點選事件。
事件委託的應用
- 動態內容:
當頁面上有大量動態生成的元素時,使用事件委託可以簡化事件處理。
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); });
- 提高效能:
當需要為大量元素新增事件監聽器時,事件委託可以顯著提高效能,因為只需要為父元素新增一個事件監聽器,而不是為每個子元素新增。
<button id="addItem">Add Item</button> <ul id="parent"> <!-- 動態生成的列表項 --> </ul>
總結
閉包能夠訪問外部函式作用域中的變數,從而實現資料私有化和封裝;
事件委託利用事件冒泡機制,透過將事件監聽器新增到父元素上,簡化了事件處理,提高了效能。