我們先來看一段閉包程式碼
function arrFunction() {
const arr = [];
for (var i = 0; i < 3; i++) {
arr.push(function(){
console.log(i);
});
};
console.log(arr);
return arr;
}
const fn = arrFunction();
fn[0]();
fn[1]();
fn[2]();
arrFunction()
是一個閉包,
我們在 arr
陣列中 push
三個函式,
那麼為何顯示的結果都是 3
而不是 0
、 1
、 2
呢?
我們可以在 arrFunction()
中,
觀察 for 迴圈執行完後的 i
值為何
function arrFunction() {
const arr = [];
for (var i = 0; i < 3; i++) {
arr.push(function(){
console.log(i);
});
};
console.log('i', i);
return arr;
};
const fn = arrFunction();
從結果得知當我們將 arrFunction()
賦予到 fn
時,
此時的 i
值就已經是 3
了,
因為此時 arrFunction()
的作用域中 i
最後結果為 3
,
因此執行 arr
內的函式時,只會取得 3
這個值,
那如果要顯示 0
、 1
、 2
的話,我們有兩種方法可以使用
function arrFunction() {
const arr = [];
for (var i = 0; i < 3; i++) {
(function(j){
arr.push(function(){
console.log(j);
});
})(i);
};
console.log(arr);
return arr;
}
const fn = arrFunction();
fn[0]();
fn[1]();
fn[2]();
此時可看到結果確實顯示 0
、 1
、 2
,
那是因為立即函式有自己的作用域,
當參數 i
代入立即函式時,
此時 arr
中的所取得的值就是作為參數帶進來的值,
因此結果才會顯示 0
、 1
、 2
let
宣告 i
function arrFunction() {
const arr = [];
for (let i = 0; i < 3; i++) {
arr.push(function(){
console.log(j);
});
};
console.log(arr);
return arr;
}
const fn = arrFunction();
fn[0]();
fn[1]();
fn[2]();
此時 i
的作用域在 for 迴圈的 {}
內
所以顯示結果為 0
、 1
、 2
function storeMoney(initValue) {
let money = initValue || 1000;
return function (price) {
money += price;
return money;
};
};
const mingMoney = storeMoney(300);
console.log(mingMoney(500)); // 800
const weiMoney = storeMoney(3000);
console.log(weiMoney(500)); // 3500
該範例我們透過閉包傳入不同的值,來做相同的事情,稱為工廠模式
function storeMoney(initValue) {
let money = initValue || 1000;
return {
increase: function(price){
money += price
},
decrease: function(price){
money -= price
},
value: function() {
console.log(money);
}
};
};
const mingMoney = storeMoney(300);
mingMoney.increase(200);
mingMoney.increase(200);
mingMoney.increase(200);
mingMoney.decrease(300);
console.log(mingMoney.value()); // 600
在範例中我們在 return
中回傳物件,
之後在物件中建立許多方法,
像這種使用閉包來回傳各種方法的行為,稱為私有方法