Closure
JavaScript 的記憶體管理
垃圾回收器(garbage collector) 系統
- 追蹤記憶體分配的使用情況,以便自動釋放一些不再使用的記憶體空間
- 全域變數關閉瀏覽器頁面,才會回收
- 區域變數的值,沒有用到就會被自動回收
簡單理解
- 閉包 = 內層函式 + 外層函式的變數
- 當內層函式用到了外層的變數,就構成了閉包
- 內部函式除了能夠取得函式外部的變數,還可以記住這個變數
範例 1
function outer() {
const a = 1
function f() {
console.log(a)
}
f()
}
outer() // 1
範例 2
function outer() {
let i = 1
function fn() {
console.log(i)
}
return fn
}
const fun = outer()
fun() // 1
應用 1 — 狀態保存
- 通常會 return 一個匿名函式,可以取得到外層函式的變數
- 用一個變數來取出回傳的函式
- 因為
result
指向count
這個函式(全域),myCount
不會被回收 myCount
計算後的結果會被儲存下來
範例
//
function count() {
let myCount = 0
return function () {
myCount++
console.log(`被調用${myCount}次`)
}
}
const result = count()
result() // "被調用1次"
result() // "被調用2次"
應用 2 — 緩存機制
- 因為閉包原理,
cache
變數可以被 return 的函式取得 - 能夠用
cache
來放想要緩存的東西,在執行前先檢查是否存在快取 - 可以避免重複計算
function expensiveFunction() {
// 這裡是複雜的操作
console.log('Executing expensive operation...')
return 'Expensive Result'
}
function createCache() {
let cache = {}
return function (key, func) {
if (!cache[key]) {
cache[key] = func()
}
return cache[key]
}
}
const cachedFunction = createCache()
// 首次調用,將計算結果緩存
// 輸出: Executing expensive operation... Expensive Result
console.log(cachedFunction('test', expensiveFunction))
// 第二次調用,直接從緩存回傳結果
// 輸出: Expensive Result(不會再次執行 expensiveFunction)
console.log(cachedFunction('test', expensiveFunction))
應用 3 — 模擬私有變數
- 開發的程式碼內部細節,並不想讓外部來獲取時
- 可以避免變數被直接修改,維持穩定性
function createBankAccount(initialBalance) {
let balance = initialBalance // 私有變數
return {
deposit: function (amount) {
balance += amount
console.log(`存款後餘額:${balance}`)
},
withdraw: function (amount) {
if (amount <= balance) {
balance -= amount
console.log(`提款後餘額:${balance}`)
} else {
console.log('餘額不足')
}
},
getBalance: function () {
return balance // 提供對私有變數的讀取方式
}
}
}
const account = createBankAccount(100)
account.deposit(50) // 存款後餘額:150
account.withdraw(20) // 提款後餘額:130
console.log(account.getBalance()) // 130
console.log(account.balance) // undefined,無法直接訪問私有變數
需注意
- 當使用閉包時,因為變數會常駐在記憶體中不會清除
- 若使用過多,可能導致內存泄露(memory leak)
參考資料
# JavaScript # 閉包