成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

JavaScript 數組 reduce 總是不會用?看看這 5 個例子就懂了!

開發 前端
相信不少初學者曾經都被 JavaScript 數組的 reduce方法困擾過,一直搞不明白到底怎么用。reduce方法是按順序對數組每個元素執行某個函數,這個函數接收上一次執行結果作為參數,并將結果傳給下一次調用。

[[355931]]

相信不少初學者曾經都被 JavaScript 數組的 reduce方法困擾過,一直搞不明白到底怎么用。reduce方法是按順序對數組每個元素執行某個函數,這個函數接收上一次執行結果作為參數,并將結果傳給下一次調用。reduce方法用得好可以簡化復雜的邏輯,提高代碼可讀性。通過下面幾個例子可以幫你快速理解reduce的用法。

1.數字數組求和

這是reduce最常見的入門級例子。如果用傳統的for循環是這樣的:

 

  1. function sum(arr) { 
  2.   let sum = 0; 
  3.   for (const val of arr) { 
  4.     sum += val; 
  5.   } 
  6.   return sum
  7.  
  8. sum([1, 3, 5, 7]); // 16 

如果用 reduce():

 

  1. function sum(arr) { 
  2.   const reducer = (sum, val) => sum + val; 
  3.   const initialValue = 0; 
  4.   return arr.reduce(reducer, initialValue); 
  5.  
  6. sum([1, 3, 5, 7]); // 16 

reduce()函數的第一個參數是一個reducer函數,第二個參數是初始值。在每個數組元素上執行reducer函數,第一個參數是“累進值”。累進值的初始值是initialValue,并且在每一輪調用后更新為reducer函數的返回值。

為了幫助理解,可以用for循環實現一個簡單的reduce()函數:

 

  1. function reduce(arr, reducer, initialValue) { 
  2.   let accumulator = initialValue; 
  3.   for (const val of array) { 
  4.     accumulator = reducer(accumulator, val); 
  5.   } 
  6.   return accumulator; 

2.對象數組數字屬性值求和

單看 reduce() 本身,大家更多的感受是它的晦澀難懂,而不是有多好用。如果僅僅是為了給數字數組求和,用for循環可能來得更直觀。但是,當你把它跟其他數組方法(比如filter和map)結合使用時,才能感受到它的強大和方便。

舉個栗子,假設有個對象數組,每個對象都有個total屬性。對這些total求和:

 

  1. const lineItems = [ 
  2.   { description: 'Eggs (Dozen)', quantity: 1, price: 3, total: 3 }, 
  3.   { description: 'Cheese', quantity: 0.5, price: 5, total: 2.5 }, 
  4.   { description: 'Butter', quantity: 2, price: 6, total: 12 } 
  5. ]; 

用reduce可以這樣寫:

  1. lineItems.reduce((sum, li) => sum + li.total, 0); // 17.5 

這樣是能得到最終結果,但是代碼的可組合性就沒那么好,可以做些優化,把total屬性提前提取出來:

  1. lineItems.map(li => li.total).reduce((sum, val) => sum + val, 0); 

第二種方式為什么更好?因為這樣就可以把求和的邏輯抽象到一個單獨的函數sum()中,方便以后重用。

 

  1. //匯總 total  
  2. lineItems.map(li => li.total).reduce(sumReducer, 0); 
  3.  
  4. //  匯總 quantity 
  5. lineItems.map(li => li.quantity).reduce(sumReducer, 0); 
  6.  
  7. function sumReducer(sum, val) { 
  8.   return sum + val; 

這種抽象比較重要,因為你覺得 sumReducer() 邏輯不會變,其實不然。比如,這個求和邏輯并沒有考慮到0.1 + 0.2 !== 0.3的問題。(參考 為什么 0.1 + 0.2 = 0.300000004)如果有了這個抽象,要修復這個缺陷就比較方便了。比如:

 

  1. const { round } = require('lodash'); 
  2.  
  3. function sumReducer(sum, val) { 
  4.   // 保留2位小數 
  5.   return _.round(sum + val, 2); 

3.求最大值

reduce()通常用來求和,但它的功能遠不止這個。累進值accumulator 可以是任意值:數字,null,undefined,數組,對象等。

舉個栗子,假設有個日期數組,要找出最近的一個日期:

 

  1. const dates = [ 
  2.   '2019/06/01'
  3.   '2018/06/01'
  4.   '2020/09/01', // 這個是最近日期,但是怎么找到它? 
  5.   '2018/09/01' 
  6. ].map(v => new Date(v)); 

一種方法是給數組排序,找最后一個值。看上去可行,但是效率沒那么高,并且用數組的默認方法給日期對象排序其實是有點小問題的。不只是日期對象,任何類型的值在sort()方法中比較,都會默認先轉成字符串比較,最終結果可能并不是你想要的。

 

  1. const a = [4,1,13,2]; 
  2. // 驚不驚喜,意不意外? 
  3. a.sort(); // [1, 13, 2, 4] 

這里就可以用reduce()來處理:

 

  1. // 這里是用 `>` 和`<` 比較日期對象,因此不會有問題 
  2. const maxDate = dates.reduce((max, d) => d > max ? d : max, dates[0]); 

4.分組計數

假設有個對象數組,每個對象上有個age屬性:

 

  1. const characters = [ 
  2.   { name'Tom', age: 59 }, 
  3.   { name'Jack', age: 29 }, 
  4.   { name'Bruce', age: 29 } 
  5. ]; 

怎樣返回一個對象,包含每個age的人物角色數量?比如這樣: { 29: 2, 59: 1 }.

用 reduce() 的實現方式如下:

 

  1. const reducer = (map, val) => { 
  2.   map[val] = map[val] || 1; 
  3.   ++map[val]; 
  4.   return map; 
  5. }; 
  6. characters.map(char => char.age).reduce(reducer, {}); 

5.Promise 動態鏈式調用

假設你有一個異步函數數組,想要按順序執行:

 

  1. const functions = [ 
  2.   async function() { return 1; }, 
  3.   async function() { return 2; }, 
  4.   async function() { return 3; } 
  5. ]; 

如果是靜態的Promise代碼,我們直接在代碼里鏈式調用就行了。但如果是動態的Promise數組,可以用reduce串起來:

 

  1. // 最后 `res`的結果等價于`Promise.resolve().then(fn1).then(fn2).then(fn3)` 
  2. const res = await functions. 
  3.   reduce((promise, fn) => promise.then(fn), Promise.resolve()); 
  4. res; // 3 

當然,reduce 能做的事情還有很多,它本質上是對數組元素執行某種“累進”操作,最終返回單個值。

本文轉載自微信公眾號「1024譯站」,可以通過以下二維碼關注。轉載本文請聯系1024譯站公眾號。

 

責任編輯:武曉燕 來源: 1024譯站
相關推薦

2021-03-16 15:12:57

CompletableFuture機制java

2024-08-12 12:25:25

SpringMVC開發

2018-09-13 10:40:40

Linux命令find

2024-09-09 08:36:36

Java操作遠程服務器

2020-09-01 14:17:03

WindowsDefender微軟

2020-05-14 08:59:28

API網關性能

2020-12-18 09:45:33

DockerLinux命令

2022-02-22 08:25:51

typeScript泛型概念泛型使用

2020-11-09 09:03:35

高并發多線程ThreadLocal

2020-09-27 06:50:56

Java互聯網注解

2021-07-13 12:21:34

PythonRPC通信

2019-04-17 09:01:17

2012-05-02 15:38:49

金山快盤網盤

2021-03-22 08:20:48

5G工業互聯網

2021-11-10 07:47:48

Traefik邊緣網關

2022-08-12 15:58:34

Docker

2019-11-28 16:48:00

華為Mate X

2017-09-19 19:07:00

ZStack混合云災備

2020-10-21 10:02:16

架構運維技術

2019-09-03 09:30:46

ss 命令SocketLinux
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 激情在线视频网站 | 亚洲国产成人精品久久久国产成人一区 | 91视频正在播放 | 日韩黄a | 日本综合在线观看 | 四虎影视免费在线 | 中文字幕一区二区三区不卡在线 | 日日摸日日碰夜夜爽亚洲精品蜜乳 | av中文字幕在线 | 一级黄色片免费在线观看 | 国产成人精品一区二 | 日本爱爱 | 亚洲91精品 | 欧美一区成人 | 人人干97 | 久久久精品影院 | av一级久久| 天堂一区二区三区 | 天天干天天想 | 激情网五月天 | 国产日日操 | 成人激情视频免费在线观看 | 丝袜一区二区三区 | 亚洲视频在线免费观看 | 日韩伦理一区二区三区 | 一级国产精品一级国产精品片 | 国产99久久久久 | 毛片一区二区三区 | 天天狠狠 | 日韩有码一区 | 香蕉大人久久国产成人av | av久久 | 五月免费视频 | 欧美在线视频网 | 欧美日韩视频在线播放 | 国产精产国品一二三产区视频 | 91精产国品一二三区 | 成人三级在线播放 | 中文字幕在线一区 | 欧美一级片 | 九九热精品在线 |