1、什麼是函數式編程
- 函數式編程,指的是 函數 數學中的 映射關係,並不是單純的指函數本身
- 純函數,指的是 多次 輸入和輸出 一致的函數
- 有副作用的函數 指的是 依賴外部變量的 函數,因爲 內部的 執行結果 就變成了 不可控的
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')