前幾篇一個陰錯陽差發現了 reduce,不小心產生了好感(?),於是很興奮的說要之後再找時間介紹,寫完 forEach 後突然就決定不然就介紹一下 reduce 好了,顆顆。
不過說是介紹,事實是我才疏學淺,只能算是跟各位分享我的研究結果,如果各位有什麼其他的想法也可以再幫我補充補充,那麼我們就開始來討論一下 reduce 到底怎麼使用吧。
這邊先引用MDN對 reduce 的一句話解釋:
reduce() 方法將一個累加器及陣列中每項元素(由左至右)傳入回呼函式,將陣列化為單一值。
用自己的話來解釋上面這段則大概是,reduce 方法會針對陣列中的每一個元素,傳入指定的函數,並且是由左至右,最後再回傳一個累加的值。其實我在 map 方法的時候有大概的用範例解釋了一下 reduce 方法,感覺 reduce 在搭配 map 也是十分的好用。
以下這個範例是 reduce 使用方法:
let num = [0, 1, 2, 3, 5, 7].reduce(function(a, b) {
return a + b;
}, 0);
console.log(num); // 18
也就是進行資料上的加總,而這也是陣列資料蠻常需要做的事。
簡單來說就是,陣列資料如果很多很複雜,reduce 方法可以將陣列資料展開處理;以底下的例子來說,arr 是一個多維陣列,而我們需要使用 reduce 將 arr 變成一維陣列。
let arr = [
[ 'a','b' ],
[ 'c', 'd', 'e' ],
[ 'f', 'g', 'h' ]
];
// 將所有元素都與之前代入的陣列相接起來,第一次處理時代入初始值空陣列
let newArr = arr.reduce(function(arr, element) {
return arr.concat(element);
}, []);
console.log(newArr); // ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
這個函數在這裡會被執行三次,第一次是 a , b 與空陣列相接後回傳,第二次是已經代入的 a , b 與 c , d , e 相接並回傳,第三次是 a , b , c , d , e 與 f , g , h 相接後回傳。
上面的例子可以看到,reduce 可以與前一個回傳的值再次運算。
reduce 也可以統計陣列內容,從範例來看,reduce 方法能計算物件出現的次數。
let arr = [
'牛肉麵',
'蛋餅',
'花椰菜',
'奶茶',
'義大利麵',
'牛肉麵',
'蛋餅'
];
// 計算出每種語言出現過幾次
let foodNum = arr.reduce(function(langs, langName) {
if (langs.hasOwnProperty(langName)) {
langs[langName]++
} else {
langs[langName] = 1;
}
return langs;
}, {});
console.log(foodNum); // {牛肉麵: 2, 蛋餅: 2, 花椰菜: 1, 奶茶: 1, 義大利麵: 1}
不太知道會不會有人跟我有一樣的疑問,但我仍然解釋一下 hasOwnProperty 方法好了。
hasOwnProperty 方法:
會回傳一個布林值,檢視物件自身屬性中是否有指定的屬性,如果具有帶指定名稱的屬性,hasOwnProperty 方法會回傳 true,否則回傳 false。
了解 hasOwnProperty 方法以後,上面範例其實可以猜到,是使用 hasOwnProperty 方法去檢查屬性名稱是否重複,如果重複就會疊加。
這個範例需要使用 Object.keys,keys 代表把物件的屬性抓出來變成陣列,把物件屬性取出來之後,再用名稱回去原物件查值,並且使用 reduce 做加總。
let data = {
'juice': 5,
'hamburger': 2,
'fries': 4,
'chicken-leg': 10,
'cola': 2
};
// 使用 Object.keys() 取得包含所有 key 的陣列
let result = Object.keys(data).reduce(function(prev, name) {
// 利用 key 取得原始物件中的值,然後加總
return data[name] + prev;
}, 0);
console.log(result); // 23
以上介紹的幾個 reduce 方法執行的小程式,覺得看了就興奮(?),雖然目前還是很簡易的幾個例子,不過可以看得出來在龐大的資料庫裡面,若是使用 reduce 方法,絕對是可以提升不少效率的,這裡已經讓我迫不及待把 reduce 延伸再延伸了,等我研究出更多實務上的寫法,再來與大家分享吧。
參考資料:
上手使用 JavaScript 的 Map、Reduce 吧!
Javascript 中的 for、foreach、 map與reduce的用法