1. 程式人生 > 實用技巧 >JavaScript 中的純函式

JavaScript 中的純函式

前言

純函式是一個常見的概念,在日常工作中也經常會遇到,它其實非常簡單,今天我們來了解一下它的好處以及為什麼要使用它。

兩個特點

一個函式,如果符合以下兩個特點,那麼它就可以稱之為純函式

  1. 對於相同的輸入,永遠得到相同的輸出
  2. 沒有任何可觀察到的副作用

相同輸入得到相同輸出

我們先來看一個不純的反面典型:

let greeting = 'Hello'

function greet (name) {
  return greeting + ' ' + name
}

console.log(greet('World')) // Hello World

上面的程式碼中,greet('World'),是不是永遠返回Hello World? 顯然不是,假如我們修改greeting的值,就會影響greet函式的輸出。即函式greet其實是依賴外部狀態

的。

那我們做以下修改:

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出來:

const user = {
  username: 'savokiss'
}

function validate (user) {
  return user.username.length > 4;
}

const isValid = validate(user)

這樣validate函式就不會修改任何外部的狀態了~

電腦刺繡繡花廠 http://www.szhdn.com

廣州品牌設計公司https://www.houdianzi.com

為什麼要用純函式?

你可能聽過純函式有不少優點,如果你經手過各種難維護的函式,你就更應該考慮使用純函式。

可測試性(Testable)

讓我們先用不純的greet方法來做單元測試:

// jest 語法
describe('greet', function() {
  it('shows a greeting', function() {
    expect(greet('Savo')).toEqual('Hello Savo')
  });
});

如果我們修改了greeting變數為Hi,上面的測試就會失敗了,這本質上不應該發生。

那我們如果換成純函式版本的greet,所有都是那麼自然~ 只需要修改單元測試中傳入的引數即可!

可快取性(Cacheable)

純函式可以根據輸入來做快取。實現快取的是一種叫作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中的那個函式為純函式的基礎上。

可移植性 / 自文件化(Portable / Self-Documenting)

由於純函式是自給自足的,它需要的東西都在輸入引數中已經宣告,所以它可以任意移植到任何地方。

並且純函式對於自己的依賴是誠實的,這一點你看它的形參就知道啦~正所謂形參起的好,註釋不用搞~(雙押!)純函式就是這麼個正直的小可愛~