如果我要遍歷一個陣列,
我只要給forEach傳一個匿名函式即可,很簡單;
let arr = ['a', 'b', 'c'];
arr.forEach((item, index) => {
console.log(item);
console.log(index);
})
如果我已經把匿名函式抽象出來,做成了一個公共的方法
(可能其他地方也會用的到)
那麼,這個遍歷會是這樣的;
let arr = ['a', 'b', 'c'];
let myFunc = (item, index) => {
console.log(item);
console.log(index);
}
arr.forEach(myFunc);
注意:只要把方法物件傳給forEach就可以嘍,引數什麼的,根本就不用關心;
如果這個方法在一個物件裡,那也沒什麼問題:
let obj = {
add(param, index) {
console.log(param);
console.log(index)
}
}
let arr = ['a', 'b', 'c'];
arr.forEach(obj.add);
但,如果涉及到物件的this,那就要出問題了:
let obj = {
name: 'allen',
add(param, index) {
console.log(this.name);
console.log(param);
console.log(index)
}
}
let arr = ['a', 'b', 'c'];
arr.forEach(obj.add);
輸出:
undefined
a
0
undefined
b
1
undefined
c
2
這是因為,add方法執行的時候,this物件指向的並不是obj,而是forEach的物件,forEach的物件是全域性物件golobal;
那想實現意圖怎麼辦呢?
最low的辦法就是給forEahc在套一個匿名函式
arr.forEach((item, index) => obj.add(item, index));
其次是給forEach方法再多傳遞一個引數:
arr.forEach(obj.add, obj);
這也不是什麼好主意,forEach你可以多傳一個obj進去,其他的類似forEach的方法,可不一定允許你多傳一個物件進去哦!
更好的辦法是:
arr.forEach(obj.add.bind(obj));
bind建立了一個新函式,這個函式跟obj.add一樣,唯一不同的是,新函式把this繫結了obj
也就是說把add方法繫結給了接收者obj;
現在假設我們的add方法,還需要另外一個引數title,而且這是第一個引數:
add(title, param, index) {
console.log(title);
console.log(param);
console.log(index)
}
那該如何是好呢?
你可以直接在bind方法裡直接傳遞這個引數:
arr.forEach(obj.add.bind(obj, "mytitle"));
最終的程式碼是:
let obj = {
add(title, param, index) {
console.log(title);
console.log(param);
console.log(index)
}
}
let arr = ['a', 'b', 'c'];
arr.forEach(obj.add.bind(obj, "mytitle"));
輸出結果是:
mytitle
a
0
mytitle
b
1
mytitle
c
2
將函式與其引數的一個子集繫結的技術稱為函式的柯里化;
比起顯式的封裝函式,這樣做更簡潔!
(一般人也更不容易看懂你的程式碼,哈哈哈!)