從最簡單的例子開始。
var arr = [1, 2, 3, 4, 5];
sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prevres, cur, index);
return prevres + cur;
})
console.log(arr, sum);
輸出結果
1 2 1
3 3 2
6 4 3
10 5 4
[1, 2, 3, 4, 5] 15
reduce中回調函數的參數,這個回調函數中有4個參數,意思分別爲
prev: 第一項的值或者上一次疊加的結果值
cur: 當前會參與疊加的項
index: 當前值的索引
arr: 數組本身
首先我們要區分prev與cur這2個參數的區別,剛開始的時候我以爲他們是一種類型的,可是後來我發現我理解錯了。prev表示每次疊加之後的結果,類型可能與數組中的每一項不同,而cur則表示數組中參與疊加的當前項。在後邊我們可以結合實例來理解這個地方。
其次我們看到,上例中其實值遍歷了4次,數組有五項。數組中的第一項被當做了prev的初始值,而遍歷從第二項開始。
某同學的期末成績如下表示
var result = [
{
subject: 'math',
score: 88
},
{
subject: 'chinese',
score: 95
},
{
subject: 'english',
score: 80
}
];
如何求該同學的總成績?
很顯然,利用for循環可以很簡單得出結論
var sum = 0;
for(var i=0; i<result.length; i++) {
sum += result[i].score;
}
但是我們的宗旨就是拋棄for循環,因此使用reduce來搞定這個問題
var sum = result.reduce(function(prev, cur) {
return cur.score + prev;
}, 0);
這個時候,我給reduce參數添加了第二個參數。通過打印我發現設置了這個參數之後,reduce遍歷便已經從第一項開始了。
這第二個參數就是設置prev的初始類型和初始值,比如爲0,就表示prev的初始值爲number類型,值爲0,因此,reduce的最終結果也會是number類型。
因爲第二個參數爲累計結果的初始值,因此假設該同學因爲違紀被處罰在總成績總扣10分,只需要將初始值設置爲-10即可。
var sum = result.reduce(function(prev, cur) {
return cur.score + prev;
}, -10);
我們來給這個例子增加一點難度。假如該同學的總成績中,各科所佔的比重不同,分別爲50%,30%,20%,我們應該如何求出最終的權重結果呢?
解決方案如下:
var dis = {
math: 0.5,
chinese: 0.3,
english: 0.2
}
var sum = result.reduce(function(prev, cur) {
console.log(prev);
return cur.score + prev;
}, -10);
var qsum = result.reduce(function(prev, cur) {
return prev + cur.score * dis[cur.subject]
}, 0)
console.log(sum, qsum);
爲了計算出權重之後的總值,我們在回調函數內部修改了數組當前項,是使他和權重比例關聯襲來,並重新返回一個一樣的回調函數,將新修改的當前項傳入,就和之前的例子是一樣的了。
在segmentfault上看到一個面試題,問如何知道一串字符串中每個字母出現的次數?
我們可以運用reduce來解決這個問題。
我們在reduce的第二個參數裏面初始了回調函數第一個參數的類型和值,將字符串轉化爲數組,那麼迭代的結果將是一個對象,對象的每一項key值就是字符串的字母。運行感受一下吧。
var arrString = 'abcdaabc';
arrString.split('').reduce(function(res, cur) {
res[cur] ? res[cur] ++ : res[cur] = 1
return res;
}, {})
由於可以通過第二參數設置疊加結果的類型初始值,因此這個時候reduce就不再僅僅只是做一個加法了,我們可以靈活的運用它來進行各種各樣的類型轉換,比如將數組按照一定規則轉換爲對象,也可以將一種形式的數組轉換爲另一種形式的數組,大家可以動手去嘗試一樣。
[1, 2].reduce(function(res, cur) {
res.push(cur + 1);
return res;
}, [])
這種特性使得reduce在實際開發中大有可爲!但是需要注意點,在ie9一下的瀏覽器中,並不支持該方法