閉包
1 2 3 4 5 6 7 8 9 10 11
| function storeMoney() { var money = 500; return function (price) { money = money + price; return money } }; var mingMoney = storeMoney(); console.log(mingMoney(50)); // 550 console.log(mingMoney(50)); // 600 console.log(mingMoney(50)); // 650
|
這邊可以發現 mingMoney
的值有繼續被增加,原因是實際上釋放記憶體的條件是「當變數無法被引用時就會釋放記憶體」,而現在這個函式被綁定在全域變數上,所以它能夠不斷的呼叫,所以記憶體並不會被釋放。
再來看下一個範例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function storeMoney() { var money = 500; return function (price) { money = money + price; return money } }; var mingMoney = storeMoney(); console.log(mingMoney(50)); // 550 console.log(mingMoney(50)); // 600 console.log(mingMoney(50)); // 650
var jayMoney = storeMoney(); console.log(jayMoney(1000)); // 1500 console.log(jayMoney(1000)); // 2500 console.log(jayMoney(1000)); // 3500
|
這裡兩個變數各自呼叫了函式,所以它們會有各自的回傳結果。
也可以想成每次回傳都生成一個新的位址。
閉包申論
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function arrFunction(e) { var arr = []; for (var i = 0; i < 3; i++) { arr.push(function (e) { console.log(i); }); } console.log('i = '+ i); return arr; }
var fn = arrFunction(); fn[0](); fn[1](); fn[2]();
|
會造成全部都出現 3 是因為 var
的作用域是在 function
內,所以它會汙染到 for
外面的 i
。
解決方法很簡單 ↓
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| function arrFunction(e) { var arr = []; for (let i = 0; i < 3; i++) { arr.push(function (e) { console.log(i); }); } //console.log('i = '+ i); // 如果有這層程式碼會報錯,因為找不到 i 變數 return arr; }
var fn = arrFunction(); fn[0](); // 0 fn[1](); // 1 fn[2](); // 2
|
因為 let
的作用域是限制在 {}
,所以在 for
就已經把它限制住了。
閉包工廠
1 2 3 4 5 6 7 8 9 10
| function storeMoney(initValue) { var money = initValue || 500; return function (price) { money = money + price; return money } };
var mingMoney = storeMoney(100); // 起始 100 console.log(mingMoney(500)); // 增加 500
|
這裡利用了 var money = initValue || 500;
來做出預設值。
私有方法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| function storeMoney(initValue) { var money = initValue || 500; return { increase: function (price) { money += price; }, decrease: function (price) { money -= price; }, nowMoney: function (price) { return money; } }; };
var mingMoney = storeMoney(100); // 起始 100 mingMoney.increase(100); // 起始 100 + 100 = 200 mingMoney.increase(100); // 200 + 100 = 300 mingMoney.decrease(50); // 300 - 50 = 250 mingMoney.decrease(25); // 250 - 25 = 225 console.log(mingMoney.nowMoney()); // 最後會顯示 225
|
這是可以在回傳的時候加入一個物件,利用物件去做加減的運算。