高階函數及 map、reduce、filter 的實現

  • 2020 年 2 月 14 日
  • 筆記

函數

函數是函數式編程的工作單元與中心。函數是任何可調用你且可通過 () 操作求值的表達式。

JavaScript 函數有兩個支柱性的重要特性:一等函數和高階函數

一等函數就是最常見的,如:

function multiplier(a, b) {    return a * b  }    let square = function(x) {    return x * x  }    // lambda 表達式(箭頭函數)  let square = x => x * x

主要說說高階函數

高階函數

鑒於函數的行為與普通對象類似,其理所當然地可以作為其他函數的參數進行傳遞,或是由其他函數返回。這些函數則稱為高階函數。~JavaScript函數式編程指南p36~

例如 Array.sort 的 comparator 函數就是高階函數(傳送門:https://ainyi.com/41 -> sort 函數)

function add(a) {    return function(b) {      return a + b    }  }  add(1)(2)

上面例子,add 函數接收一個參數,並返回另一個接收第二個參數並把它們加在一起的函數

函數柯里化能夠很好地體現高階函數的應用

function currying(fn, length) {    length = length || fn.length;    return function (...args) {      return args.length >= length          ? fn.apply(this, args)        : currying(fn.bind(this, ...args), length - args.length)    }  }    const add = currying(function(a, b, c) {      console.log([a, b, c].reduce((a, b) => a + b))  })    add(1, 2, 3) // 6  add(1, 2)(3) // 6  add(1)(2)(3) // 6  add(1)(2, 3) // 6

兼容各種 add 調用的高階函數

詳情看我之前寫的文章 js 高階函數之柯里化

map、reduce、filter

此三種函數均為高階函數,如何實現這三個函數,接下來看看。

一般重寫對象的實例方法是通過 prototype,數組的所有實例方法、屬性都保存在 Array.prototype。只不過平常都是通過該對象的實例調用

通過 _.實例方法,該實例方法的 this 指針指向它

map 的實現

高階函數 map 能夠將一個迭代函數有序地應用於一個數組中的每個元素,並返回一個長度相等的新數組

function map(fn) {    let idx = -1,        len = this.length,        result = new Array(len)      while (++idx < len) {      result[idx] = fn(this[idx], idx, this)    }    console.log('myself')    return result  }  Array.prototype.map = map;  [1, 2, 3].map(ele => `#${ele}#`)  // myself  // ["#1#", "#2#", "#3#"]

reduce 實現

高階函數 reduce 將一個數組中的元素精簡為單一的值,該值是由每個元素與一個累計值通過一個函數計算得出的

function reduce(fn, accumulator) {    let idx = -1,        len = this.length      if (!accumulator && len > 0) {      accumulator = this[++idx]    }      while (++idx < len) {      accumulator = fn(accumulator, this[idx], idx, this)    }    console.log('myself')    return accumulator  }  Array.prototype.reduce = reduce;  [1, 2, 3].reduce((n, p) => n + p)  // myself  // 6    // 也可以指定第一個累計值  [1, 2, 3].reduce((n, p) => n + p, 100)  // myself  // 106

filter 的實現

高階函數 filter 能夠遍曆數組中的元素並過濾後返回一個新子集數組

function filter(fn) {    let idx = -1,        len = this.length        result = []      while (++idx < len) {      let value = this[idx]      if (fn(value, idx, this)) {        result.push(value)      }    }    console.log('myself')    return result  }  Array.prototype.filter = filter;  [1, 2, 3].filter(ele => ele >= 2)  // myself  // [2, 3]