今天我要講解的是閉包(Closure),在進入之前我們先來看一段程式碼,
首先準備一個隨機生成字串的函式
function randomString(length) {
let result = '';
let characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * characters.length));
}
return result;
};
接著在全域中新增一個變數和函式,並且執行該函式
let demoData = [];
function getData() {
for (let i = 0; i < 1000; i++) {
demoData.push(randomString(1000))
}
};
getData();
我們能看見這段程式碼佔記憶體空間 20.6 MB,
接著我們將變數移到函式內,再看一次佔多少記憶體空間
function getData() {
let demoData = [];
for (let i = 0; i < 1000; i++) {
demoData.push(randomString(1000))
}
};
getData();
此時會看見程式碼佔記憶體空間 815 KB,
在此附上 KB 和 MB 的單位轉換: 1 MB = 1024 KB
那麼為何所佔的記憶體變少呢?
那是因為在函式中的變數所佔的記憶體,
在函式執行結束後,此時函式內的變數沒被參考,
所以該變數所儲存的記憶體空間就被釋放掉,
因此所佔的記憶體就變少了
而當函式內的變數記憶體還保留時,這就是所謂的閉包(Closure)
當函式內的變數其值被保留,而不被記憶體釋放時,稱為閉包(Closure)
範例:
function storeMoney(){
let money = 1000;
return function(price) {
money += price;
return money
}
};
console.log(storeMoney);
console.log(storeMoney());
console.log(storeMoney()(100));
該範例中 storeMoney()
回傳匿名函式,而匿名函式中則回傳 money
,
在第一個 console.log()
中,會回傳 storeMoney()
整個函式,
在第二個 console.log()
中,會回傳匿名函式,
在第三個 console.log()
中,會回傳 1100
,
那為何會回傳 1100
呢?
那就跟它的作用域有關係了,
在匿名函式中因為沒有變數 money
所以向外查找該變數,
也因為向外查找這個動作,就讓 money
的值無法被釋放,
所以 money
的值必須保存起來,匿名函式中才能取用該變數做使用,
因此才會回傳 1100
接著我們將函式賦予到變數上
function storeMoney(){
let money = 1000;
return function(price) {
money += price;
return money
}
};
const wei = storeMoney();
console.log(wei(100)); // 1100
console.log(wei(100)); // 1200
console.log(wei(100)); // 1300
我們能看到回傳的結果會累加,
這是因為在 storeMoney()
中,
我們將 100
這個參數代入匿名函式進行相加,
而相加後的值也會保留起來不被釋放,
因此當我們不斷將參數帶入時, money
的值也會不斷累加,
還有因為我們是在函式中宣告變數,
因此這個範例中的 money
的值,只屬於 wei
這個變數
當我們再宣告其他變數時,其值是互不相關的
function storeMoney(){
let money = 1000;
return function(price) {
money += price;
return money
}
};
const wei = storeMoney();
console.log(wei(100)); // 1100
console.log(wei(100)); // 1200
console.log(wei(100)); // 1300
const ming = storeMoney();
console.log(ming(1000)); // 2000
console.log(ming(1000)); // 3000
console.log(ming(1000)); // 4000
以上就是今天閉包的解說,我們明天見!!