最近在項目裏摳語言包的過程中發現做了很多重複的工作,然後同事指點了一下reduce這個方法,彷彿打開了新世界的大門。遂重新學習了一下reduce的用法。在博客記錄一下。
提示:努力想把文章寫的精簡,但是覺得關於這個函數很多細節想寫。所以這篇觀感可能會是: 博主是個bb怪。
測試:
如果你能理解下列函數的原理,那麼這篇文章你完全沒有閱讀必要。
// 版本1
[...new Array(100).values()].map((item, index) => index + 2).reduce((a, b) => `${a} MINE_${b}: "", \n`, 'MINE_1: "",');
// 另一種寫法
[...new Array(100).toString().split(',').keys()].reduce((a, b) => `${a} MINE_${b}: "", \n`,'');
一、定義
array.reduce( function(accumulator, currentValue
, currentIndex, array), initialValue );
accumulator:上一次調用回調返回的值,或者是提供的初始值(initialValue)
currentValue:數組中正在處理的元素
currentIndex:數據中正在處理的元素索引,如果提供了 initialValue ,從0開始;否則從1開始。【可選】
array: 調用 reduce 的數組【可選】
initialValue:可選項,其值用於第一次調用 callback 的第一個參數。如果沒有設置初始值,則將數組中的第一個元素作爲初始值。【可選】這裏注意如果對一個空數組使用 [ ].reduce 方法會報錯。原因看下面例子。
array.reduce 的返回值是這個函數累計處理的結果。
// 用代碼解釋定義
let demo = [ 333, 222, 111 ];
//沒有定義initialValue
demo.reduce((acc, curVal) => { console.log(acc) })
// 輸出: 333, undefined, undefined
//定義initialValue爲1
demo.reduce((acc, curVal) => { console.log(acc)}, 1)
// 輸出: 1, undefined, undefined
//空數組不定義initialValue
[].reduce((a,b) => console.log(a))
// 輸出:Uncaught TypeError: Reduce of empty array with no initial value
// 因爲沒有定義初始值,a會默認取數組第一個值,而空數組,第一個值是undefined,所以報錯。
/* 說明:回調函數第一次執行時,accumulator 和currentValue的取值有兩種情況:如果調用reduce()時提供了initialValue,accumulator取值爲initialValue,currentValue取數組中的第一個值;如果沒有提供 initialValue,那麼accumulator取數組中的第一個值,currentValue取數組中的第二個值。輸出中有undefined 是因爲acc返回的是上一次函數返回的結果,但這裏我們函數僅是打印,沒有返回值,所以是undefined */
二、它可以方便的做一些事
數組求和
將數組轉化爲對象、計算數組中每個元素出現的次數、按屬性對數組分類
按順序運行promise
2.1 數組求和
let demo = [ { x: 1}, { x: 2 }, { x: 3} ],
demo.reduce((arr,val) => { return arr + val.x }, 0);
// return: 6
2.2 數組轉化爲對象
let demo = [
{
id: 1,
username: 'john',
sex: 1,
email: '[email protected]'
},
{
id: 2,
username: 'jerry',
sex: 1,
email: '[email protected]'
},
{
id: 3,
username: 'nancy',
sex: 0,
email: ''
}
];
demo.reduce( (acc,val) => { return {...acc, [val.username]: val} } , {} )
2.3 按順序執行promise
/**
* 直接抄官網的例子
* Runs promises from array of functions that can return promises
* in chained manner
*
* @param {array} arr - promise arr
* @return {Object} promise object
*/
function runPromiseInSequence(arr, input) {
return arr.reduce(
(promiseChain, currentFunction) => promiseChain.then(currentFunction),
Promise.resolve(input)
);
}
// promise function 1
function p1(a) {
return new Promise((resolve, reject) => {
resolve(a * 5);
});
}
// promise function 2
function p2(a) {
return new Promise((resolve, reject) => {
resolve(a * 2);
});
}
// function 3 - will be wrapped in a resolved promise by .then()
function f3(a) {
return a * 3;
}
// promise function 4
function p4(a) {
return new Promise((resolve, reject) => {
resolve(a * 4);
});
}
const promiseArr = [p1, p2, f3, p4];
runPromiseInSequence(promiseArr, 10)
.then(console.log); // 1200
2.4 數組去重
reduce當然也能做到,但是我更喜歡下面這個方式
let demo = [ 1, 1, 2, 3];
//一行完成數組去重並升序排序
[...new Set(demo)].sort();
參考鏈接:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce