6.1 閉包的概念
閉包是 JavaScript 中最強大和重要的概念之一。它們允許函數記住自己 的語法環境,即使在它們被執行完後。這次講座我們將討論閉包的概念, 其特徵並給出各種使用的例子。
JavaScript 中的閉包 (closure) 是函數與其被聲明時的語法環境的結合。 閉包允許函數「記住」並訪問其外部可見範圍中的變量和其他函數,即使在外部函數 被執行完後。
閉包的主要屬性:
- 語法環境:函數被聲明的上下文,包括聲明時可用的所有變量。
- 保持上下文:帶有閉包的函數可以在外部函數執行完後,仍保留對外部範圍中變量的訪問。
6.2 閉包的操作範例
範例 1: 簡單閉包
在這個範例中,innerFunction() 可以訪問其外部 領域的變量 outerVariable,即便在 outerFunction() 執行完後。
JavaScript
function outerFunction() {
let outerVariable = 'I am from the outer function';
function innerFunction() {
console.log(outerVariable);
}
return innerFunction;
}
const closure = outerFunction();
closure(); // 輸出: I am from the outer function
範例 2: 使用閉包的計數器
在這個範例中,計數器函數保存變量 count 的值,並在每次調用時遞增。
JavaScript
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
範例 3: 迴圈中的閉包
閉包常用來在迴圈中保存變量的值。
在這個範例中,數組 arr 中的每個函數透過 let 的塊級作用域 "記住" 其創建時 i 的值:
JavaScript
function createArrayWithClosures() {
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function() {
console.log(i);
};
}
return arr;
}
const closures = createArrayWithClosures();
closures[0](); // 輸出: 0
closures[1](); // 輸出: 1
closures[2](); // 輸出: 2
6.3 閉包的複雜使用場景
範例 1: 函數的部分應用 (partial application)
閉包允許創建部分應用的函數,保持某些參數為固定值。
在這個範例中,函數 multiply() 返回的函數會將傳遞給它的參數 b 與固定參數 a 相乘。
JavaScript
function multiply(a) {
return function(b) {
return a * b;
};
}
const double = multiply(2);
console.log(double(5)); // 輸出: 10
console.log(double(10)); // 輸出: 20
範例 2: 數據隱藏 (data hiding)
閉包可以用來創建私有變數和方法。
在這個範例中,變量 _name 和 _age 是私有的,只能通過對象的方法訪問:
JavaScript
function createPerson(name, age) {
let _name = name;
let _age = age;
return {
getName: function() {
return _name;
},
getAge: function() {
return _age;
},
setName: function(newName) {
_name = newName;
},
setAge: function(newAge) {
_age = newAge;
}
};
}
const person = createPerson('John', 30);
console.log(person.getName()); // 輸出: John
person.setName('Jane');
console.log(person.getName()); // 輸出: Jane
console.log(person.getAge()); // 輸出: 30
範例 3: 記憶化 (Memoization)
記憶化是一種優化技術,通過保存函數的結果來避免對相同輸入的重複計算。
在這個範例中,函數 memoize() 使用閉包來保存函數 fn() 計算結果的緩存:
JavaScript
function memoize(fn) {
const cache = {};
return function(...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
}
const result = fn(...args);
cache[key] = result;
return result;
};
}
function slowFunction(num) {
console.log('Computing...');
return num * 2;
}
const memoizedFunction = memoize(slowFunction);
console.log(memoizedFunction(5)); // 輸出: Computing... 10
console.log(memoizedFunction(5)); // 輸出: 10 (結果來自緩存)
GO TO FULL VERSION