reduce的n種應用

轉自你應該知道的JS: reduce的n種應用

reduce是ES5中新引入的一個API。javascript

假如你還不知道reduce的用法,請先閱讀下MDN文檔中關於reduce的介紹。(不得不說,MDN文檔太強大了,裏面列舉了不少有用的方法)java

本文將介紹藉助reduce函數,利用其可以遍歷到數組的每個元素,而且次遍歷均可以使用上次遍歷結果的特性,實現的一些功能。編程

1.累和/累積

函數式編程

let arr = [1, 2, 3, 4, 5]

console.log(arr.reduce((prev, cur) => prev + cur)) // 15數組

複製代碼// 能夠實現另類的階乘 console.log(arr.reduce((prev, cur) => prev * cur)) // 120 複製代碼複製代碼

2.求最大值/最小值

let arr = [1, 2, 3, 4, 5]

console.log(arr.reduce((prev, cur) => Math.max(prev, cur))); // 5

console.log(arr.reduce((prev, cur) => Math.min(prev, cur))); // 1
複製代碼複製代碼

3. 數組去重

reduce接收兩個參數時,即reduce(fn, init), init將做爲fn的第一個參數prev傳入。函數

這裏,將一個空數組[]做爲去重後的新數組,經過作判斷,若是該容器內已經存在某元素,就啥也不作;反之,若是該容器內尚未一個元素,就將其推入容器。post

ui

let arr = [1, 2, 3, 1, 1, 2, 3, 3, 4, 3, 4, 5] let res = arr.reduce((prev, cur)=>{ !prev.includes(cur) && prev.push(cur) return prev }, []) 複製代碼console.log(res) // [ 1, 2, 3, 4, 5 ] 複製代碼複製代碼

4.實現map函數

map函數接收一個函數做爲參數,做爲參數的函數接收三個參數值,分別是遍歷數組的每一項元素,元素的索引和數組自己。這三個參數恰好和reduce函數接收的第一個函數參數的第二、三、4個參數是對應的。this

實現思路是,將每次遍歷的元素,做爲傳入的函數的參數,並將函數執行的結果放入新的數組中spa

let arr = [1, 2, 3] Array.prototype._map = function(cb) { if(typeof cb === 'function') { // this: 調用_map方法的當前數組對象 let arr = this; return arr.reduce((prev, item, index, array) => { prev.push(cb(item, index, array)) return prev }, []) } else { throw new Error(cb + ' is not function') } } 複製代碼let res = arr._map(n => n*2) console.log(res) // [ 2, 4, 6 ] 複製代碼複製代碼

5.實現filter函數

實現filter的思路和實現map是一致的,只不事後者是一股腦的把執行結果全放入數組中,而filter須要作一個判斷:若是filter函數傳入的參數(參數是一個函數)執行後有返回值,即通過了檢驗,纔將遍歷的當前元素放入數組中,若是沒有返回值,就忽略

let arr = [1, 2, 3, 4, 5];

Array.prototype._filter = function(cb) { if(typeof cb === 'function') { let arr = this; return arr.reduce((prev, item, index, array) => { cb(item, index, array) ? prev.push(item) : null return prev }, []) } else { throw new Error(cb + ' is not function') } }

複製代碼let res = arr._filter(n => n>2) console.log(res) // [ 3, 4, 5 ] 複製代碼複製代碼

6.實現compose

compose是函數式編程的核心思想,簡單說就是將若干個函數組合成一個函數來執行,而且每一個函數執行的結果都能做爲下一個函數的參數。這也是使用reduce實現compose的思路。

假設有兩個函數,做用分別是將字符串轉爲大寫,在字符串末尾追加感嘆號:

function toUpperCase(str) { return str.toUpperCase(); } 複製代碼function add(str) { return str += '!' } 複製代碼複製代碼

通常狀況下,會這樣使用:

var str = 'hello world'
var res = toUpperCase(str)
res = add(res)
console.log(res); // HELLO WORLD!
複製代碼複製代碼

使用compose後,效果是這樣的,執行fn,至關於依次執行了toUpperCaseadd:

var fn = compose(add, toUpperCase)
console.log(fn(str));// HELLO WORLD!
複製代碼複製代碼

接下來實現一下compose:

function compose() {
  let args = [].slice.call(arguments)

  return function (x) {
   // 由於compose()接收的函數參數,是從右往走順次執行的,
   // 因此這裏使用reduceRight, 用法和reduce一致,只不過是從右往左遍歷數組。
    return args.reduceRight((prev, cur) => {
      return cur(prev)
    }, x)
  }
}
複製代碼複製代碼

7.數組扁平化

數組扁平化,針對的是多維數組,將其扁平、展開,成爲一維數組。

let arr = [1, 2, '3js', [4, 5, [6], [7, 8, [9, 10, 11], null, 'abc'], {age: 12}, [13, 14]], '[]'];

function flatten(arr) { if(Array.isArray(arr)) { return arr.reduce((prev, cur) => { // 若是遍歷的當前項是數組,再迭代展平 return Array.isArray(cur) ? prev.concat(flatten(cur)) : prev.concat(cur) }, []) } else { throw new Error(arr + ' is not array') } }

複製代碼console.log(flatten(arr)); 複製代碼複製代碼

結束

固然,除了以上幾種,reduce還有更多種神奇的應用,等待着各位小夥伴的發現和使用。

相關文章
相關標籤/搜索