重學js 第二篇, 函數式編程

1、什麼是函數式編程

  1. 函數式編程,指的是 函數 數學中的 映射關係,並不是單純的指函數本身
  2. 純函數,指的是 多次 輸入和輸出 一致的函數
  3. 有副作用的函數 指的是 依賴外部變量的 函數,因爲 內部的 執行結果 就變成了 不可控的
let arr = [1, 2, 3, 4, 5, 6, 7]

// 如下 slice 就是純函數
arr.slice(0, 3) // [1, 2, 3]
arr.slice(0, 3) // [1, 2, 3]
arr.slice(0, 3) // [1, 2, 3]
arr.slice(0, 3) // [1, 2, 3]

// splice 就不是純函數
arr.splice(0, 3) // [1, 2, 3]
arr.splice(0, 3) // [4, 5, 6]
arr.splice(0, 3) // [7]

函數式編程中比較 值得記錄的點

1、緩存

因爲純函數 是多次輸入和輸出一致的函數,所以可以使用 對象把結果緩存起來

 算法題中 著名 的 斐波那契 數列 就可以使用 緩存來進行 優化回調的問題

function memorize(fn) {
   const cache = {}
   return function () {
      const key = JSON.stringify(arguments)
      cache[key] = cache[key] || fn(...arguments)
      return cache[key]
   }
}

2.柯里化

柯里化 巧妙地利用了 函數 一等公民 以及 閉包 的 特點

柯里化 的 具體實現我就不講了,但是可以說一個 之前就在使用的實際應用場景

在 前端 和 後端 交互的過程中,會出現很多的枚舉值,但是大多數人 都是 使用 if else 完事

但是我們可以把枚舉值 都提取出來,如下所示

export const saleStatus = {
  '停售': 1,
  '已售罄': 2,
  '待售': 3,
  '發售中': 4
}

然後使用一個函數,將這個枚舉值 作爲 可以 符合 習慣,用 ‘1’ 這樣的值讀取的新函數

export const commonJudgeType = (enums, default_value = '--') => (status) => {
  for (const key in enums) {
    if (enums.hasOwnProperty(key)) {
      const st = enums[key];
      if (typeof st === 'object') {
        if (st.code === parseInt(status)) return key
      } else {
        if (st == status) return key
      }
    }
  }
  return default_value
}

export const judgeSale = commonJudgeType(saleStatus, '已售罄')

這裏返回了一個新的函數,同時 對傳入的 saleStatus 形成了一個閉包。

這樣使用 judgeSale 就可以輕易地 將對應的值給讀出來了

3、函數組合

在前面的文章中,以及網絡上的很多資料裏,都有介紹過 redux 中的 compose 函數,

使用這個函數 可以 把 一個函數的顆粒化變小,然後組合成爲 一個複雜的函數

 function compose(...funcs) {
  if (funcs.length === 0) {
    return arg => arg
  }
 
  if (funcs.length === 1) {
    return funcs[0]
  }
 
  // 每個函數的返回值 都會被 當做 一個
  return funcs.reduce((a, b) => (...args) => a(b(...args)))
}
function reverse(arr) {
  return arr.reverse()
}
function join(j) {
  return function(arr) {
    return return arr.join(j)
  }
}
function splite(s) {
  return function (str) {
    return str.split(s)
  }
}

如上面3 個函數

compose(join('-'), reverse, splite(' '))('hello world')
//  輸出的結果 就是 
//  "world-hello"

4. 函子對象

每一個函子 都是一個 盒子,包含了 當前傳入的值,不直接操作值。

所有的 操作 由函子完成,map 返回的是 一個包含新之的盒子

所以這個是 支持 鏈式調用

// 函子對象
class Container{
  static of (value) {
     return new Container(value)
  }
  // 對函數進行處理
  map(fn) {
    return Container.of(fn(this._value))
  }
  constructor(value) {
    this._value = value
  }
   join() {
     this._value
   }
}

5、正則表達式

這個 完全是抄來的,對於正則表達式 十竅通了九竅

/(\d{4})(\d{2})(\d{2})/.exec('20204040')

/(?<year>\d{4})(?<month>\d{2})(?<day>\d{2})/.exec('20204040')

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章