純函數 是一個常見的概念,在平常工做中也常常會遇到,它其實很是簡單,今天咱們來了解一下它的好處以及爲何要使用它。git
一個函數,若是符合如下兩個特色,那麼它就能夠稱之爲 純函數:編程
咱們先來看一個不純的反面典型:api
let greeting = 'Hello' function greet (name) { return greeting + ' ' + name } console.log(greet('World')) // Hello World
上面的代碼中,greet('World')
,是否是永遠返回 Hello World
? 顯然不是,假如咱們修改 greeting
的值,就會影響 greet
函數的輸出。即函數 greet
實際上是 依賴外部狀態 的。緩存
那咱們作如下修改:ide
function greet (greeting, name) { return greeting + ' ' + name } console.log(greet('Hi', 'Savo')) // Hi Savo
將 greeting
參數也傳入,這樣對於任何輸入參數,都有與之對應的惟一的輸出參數了,該函數就符合了第一個特色。函數式編程
反作用的意思是,這個函數的運行,不會修改外部的狀態。函數
下面再看反面典型:單元測試
const user = { username: 'savokiss' } let isValid = false function validate (user) { if (user.username.length > 4) { isValid = true } }
可見,執行函數的時候會修改到 isValid
的值(注意:若是你的函數沒有任何返回值,那麼它極可能就具備反作用!)測試
那麼咱們如何移除這個反作用呢?其實不須要修改外部的 isValid
變量,咱們只須要在函數中將驗證的結果 return
出來:ui
const user = { username: 'savokiss' } function validate (user) { return user.username.length > 4; } const isValid = validate(user)
這樣 validate
函數就不會修改任何外部的狀態了~
你可能聽過 純函數
有很多優勢,若是你經手過各類難維護的函數,你就更應該考慮使用 純函數
。
讓咱們先用不純的 greet
方法來作單元測試:
// jest 語法 describe('greet', function() { it('shows a greeting', function() { expect(greet('Savo')).toEqual('Hello Savo') }); });
若是咱們修改了 greeting
變量爲 Hi
,上面的測試就會失敗了,這本質上不該該發生。
那咱們若是換成純函數版本的 greet
,全部都是那麼天然~ 只須要修改單元測試中傳入的參數便可!
純函數能夠根據輸入來作緩存。實現緩存的是一種叫做 memorize
的技術。
下面的代碼來自 Vue 源碼:
/** * Create a cached version of a pure function. * 只適用於緩存 接收一個字符串爲參數的 fn */ export function cached (fn) { const cache = Object.create(null) return function cachedFn (str) { const hit = cache[str] return hit || (cache[str] = fn(str)) } } /** * Capitalize a string. */ export const capitalize = cached((str) => { return str.charAt(0).toUpperCase() + str.slice(1) })
capitalize
即爲緩存後的函數,若是屢次調用就會返回緩存後的值,從而節省計算資源,而這一切的前提都創建在傳入 cached
中的那個函數爲純函數的基礎上。
因爲純函數是自給自足的,它須要的東西都在輸入參數中已經聲明,因此它能夠任意移植到任何地方。
而且純函數對於本身的依賴是 誠實的,這一點你看它的 形參 就知道啦~正所謂 形參起的好,註釋不用搞~(雙押!)純函數就是這麼個正直的小可愛~
好啦,咱們已經大概瞭解了純函數,它對於咱們寫出良好代碼有着重要的意義,同時也是函數式編程中的精髓。原本本篇是想單純介紹純函數的,可是想起來了柯里化 (curry) 也沒有講過,那麼下次有機會就講一講柯里化吧~
We'll see!
本文首發於公衆號:碼力全開(codingonfire)
本文隨意轉載哈,註明原文連接便可,公號文章轉載聯繫我開白名單就好~