https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/001435119854495d29b9b3d7028477a96ed74db95032675000
重新學習reduce,這個是比較易懂的 (累計)
如何累計呢:
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
這個感覺特別像遞歸

累加
var arr = [1, 3, 5, 7, 9]; arr.reduce(function (x, y) { return x + y; });
累乘
'use strict'; function product(arr) {
var result = arr.reduce(function(x,y){
return x*y;
});
return result;
} // 測試: if (product([1, 2, 3, 4]) === 24 && product([0, 1, 2]) === 0 && product([99, 88, 77, 66]) === 44274384) { console.log('測試通過!'); } else { console.log('測試失敗!'); }
JavaScript中reduce()方法不完全指南
reduce() 方法接收一個函數作為累加器,數組中的每個值(從左到右)開始縮減,最終為一個值,是ES5中新增的又一個數組逐項處理方法,那reduce方法跟foreach、map等數組方法又有啥區別呢。
arr.reduce(callback[, initialValue]) — More From MDN
- callback(一個在數組中每一項上調用的函數,接受四個函數:)
- previousValue(上一次調用回調函數時的返回值,或者初始值)
- currentValue(當前正在處理的數組元素)
- currentIndex(當前正在處理的數組元素下標)
- array(調用reduce()方法的數組)
- initialValue(可選的初始值。作為第一次調用回調函數時傳給previousValue的值)
圖解參數
拋開上面晦澀難懂的語法介紹,下面我們直接上實例:
數組 arr = [1,2,3,4] 求數組的和
forEach 實現
var arr = [1,2,3,4],
sum = 0;
arr.forEach(function(e){sum += e;}); // sum = 10 just for demo
map 實現
var arr = [1,2,3,4],
sum = 0;
arr.map(function(obj){sum += obj});//return undefined array. sum = 10 just for demo
reduce實現
var arr = [1,2,3,4];
arr.reduce(function(pre,cur){return pre + cur}); // return 10
沒錯,reduce 專為累加這種操作而設計,為累加這類操作而設計的參數,十分方便。那么問題來了,reduce方法的參數到底有哪些用法呢?
參數分解
1. 不傳initialValue值
var arr = [1,2,3];
arr.reduce(function(pre,cur,index,arr){debugger;return pre+cur});
探查Arguments數組得到:
- 第一次debugger
- 第二次debugger
- 第三次debugger
return 6;
2. 傳入initialValue 值
var arr = [1,2,3]
arr.reduce(function(pre,cur,index,arr){debugger;return pre+cur},10);
- 第一次debugger
- 第二次debugger
- 第三次debugger
- 第四次debugger
return 16
可以看出傳入initialValue 會多遞歸一次,而initialValue的值的作用大家應該也明了了:為累加等操作傳入起始值(額外的加值)。
而callbackfn中的四個參數也可以在debugger的動態變化中查看出具有的特性。
那么利用reduce方法還可以做哪些事情呢?
更多實例
var arr = [1,2,3]
求乘積
var pro = arr.reduce(function(pre,cur,index,arr){return pre * cur})
求最大值
var max = a.reduce(function(pre,cur,inde,arr){return pre>cur?pre:cur;});
另外,如果你在NodeJs的環境中使用reduce幾乎沒有任何問題,但是如果你在客戶端的瀏覽器使用reduce方法,那可能就要兼容IE8以下的瀏覽器了。
當然,我們可以引入庫來解決這個問題,有趣的是,在jQuery官網中,有一個對reduce長達8年的討論 Add jQuery.reduce() 而Jquery官方至今仍然堅持reduce適合作為Jquery的一個插件存在。即使后來ES5中加入了reduce的實現。
This won’t be useful in the core, it can always be included in a plugin. —- by flesler
-
因此,如果在Jquery中使用reduce方法,需引入reduce插件 jQuery-reduce-plugin
-
underscorejs 中早已實現reduce方法 http://underscorejs.org/#reduce
至此,我們可以很形象的歸納出來forEach、map以及reduce的不同點:
- forEach 方法是將數組中的每一個值取出做一些程序員想讓他們做的事情
- map 方法 是將數組中的每一個值放入一個方法中做一些程序員想讓他們做的事情后返回一個新的數組
- reduce 方法 將數組中的每一個值與前面的被返回相加的總和(初試值為數組的第一個值或者initialValue)
Final: insert a little deeper
reduce方法在數組對象中的運用:
搬磚工小王拿到了這樣的數據格式: var arr = [ {name: 'brick1'}, {name: 'brick2'}, {name: 'brick3'} ]
希望得到這樣的數據格式: 'brick1, brick2 & brick3'
當然數組異常流:[ {name: ‘brick1’} ] 和 空數組傳入得到 'brick1'
和 空
Solution
var arr = [ {name: 'brick11'}, {name: 'brick12'}, {name: 'brick13'} ]
function carryBricks(arr){
return arr.reduce(function(prev, current, index, array){
if (index === 0){
return current.name;
}
else if (index === array.length - 1){
return prev + ' & ' + current.name;
}
else {
return prev + ', ' + current.name;
}
}, '');
}
返回結果: brick11, brick12 & brick13
此時進一步延伸如果原來有一堆磚已經堆好,傳入 initialValue值:
var arr = [ {name: 'brick11'}, {name: 'brick12'}, {name: 'brick13'} ]
var bricks = 'brick1, brick2, brick3, ' //已經堆好的磚
function carryBricks(arr,bricks){
return arr.reduce(function(prev, current, index, array){
if (index === 0){
return prev + current.name;
}
else if (index === array.length - 1){
return prev + ' & ' + current.name;
}
return prev + ', ' + current.name;
}, bricks);
}
返回結果: brick1, brick2, brick3, brick11, brick12 & brick13
-EOF-