純函數以及為什么要用純函數


什么函數是純的?

純函數的定義是:

1.   如果函數的調用參數相同,則永遠返回相同的結果。它不依賴於程序執行期間函數外部任何狀態或數據的變化,必須只依賴於其輸入參數。

2.   該函數不會產生任何可觀察的副作用,例如網絡請求,輸入和輸出設備或數據突變(mutation)。

這就是純的函數。 如果一個函數符合上述 2 個要求,它就是純函數。 你可能在過去甚至無意地情況下編寫過純函數。

在我們研究一個函數一個純或不純之前,讓我們先討論一下可怕的“副作用”。

 

什么是可觀察的副作用?

一個可以被觀察的副作用是在函數內部與其外部的任意交互。這可能是在函數內修改外部的變量,或者在函數里調用另外一個函數等。

注: 如果純函數調用純函數,則不產生副作用依舊是純函數。

副作用來自,但不限於:

•    進行一個 HTTP 請求

•    Mutating data

•    輸出數據到屏幕或者控制台

•    DOM 查詢/操作

•    Math.random()

•    獲取的當前時間

副作用本身並不是毒葯,某些時候往往是必需的。 但是,對於要保持純粹的函數,它不能包含任何副作用。當然,並非所有函數都需要是純函數。 我將在稍后討論這個情況。

不過首先,讓我們來看一些純的和不純的函數對比的例子......

 

純函數的例子

以下是一個計算產品稅后價格(英國稅率是20%)的純函數的例子:

function priceAfterTax(productPrice) { return (productPrice * 0.20) + productPrice;}

 

它符合我們所說的兩條純函數的定義。不依賴於任何外部輸入,不改變任何外部數據、沒有副作用。

即使你用同樣的輸入運行運行這個函數 100,000,000 次它依舊產生同樣的結果。

 

非純函數

我們已經看了純函數的例子,現在一起來看一個非純函數(Impure function)的 JavaScript 例子:

var tax = 20;

function calculateTax(productPrice) {

    return (productPrice * (tax/100)) + productPrice;

}

暫停片刻,看看你是否能看出為什么這個函數不純。

其中函數的計算結果取決於外部 tax 變量,而純函數不能依賴外部變量。它沒有滿足定義中的第一個要求,因此這個函數是不純的。

 

為什么說純函數在 JavaScript 很重要?

純函數在函數式編程中被大量使用。而且諸如 ReactJS 和 Redux 等優質的庫都需要使用純函數。

不過,純函數也可以用在平常的 JavaScript 開發中使用,不一定要限死在某個編程范例中。 你可以混合純的和不純的函數,這完全沒問題。

並非所有函數都需要是純的。 例如,操作 DOM 的按鈕按下的事件處理程序就不適合純函數。 不過,這種事件處理函數可以調用其他純函數來處理,以此減少項目中不純函數的數量。

 

可測試性和重構

另一個使用純函數的原因是測試以及重構。

使用純函數的一個主要好處是它們可以直接測。 如果傳入相同的參數,它們將始終產生相同的結果。

同時純函數還使得維護和重構代碼變得更加容易。你可以放心地重構一個純函數,不必操心沒注意到的副作用搞亂了整個應用而導致終調試地獄。(譯注:如果項目中充斥着副作用,那么函數/模塊之間的邏輯可能互相交織耦合,在后期新增邏輯時可能由於依賴復雜而難以重構,更常見的是開發為了應付需求而不斷的引入新的副作用到原本的邏輯上從而導致代碼變得越來越糟糕。)

正確地使用純函數可以產生更加高質量的代碼。並且也是一種更加干凈的編碼方式。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM