reducer(概括函數)這種函數的名稱,是由數組的一個迭代方法reduce(概括)而來,你能夠參考MDN中的相關說明:數據庫
在JS語言中的數組reduce(概括)這個方法是一種應用於特殊狀況的迭代方法,它能夠藉由一個回調(callback)函數,來做先後值兩相運算,而後不斷縮減數組中的成員數量,最終返回一個值。reduce(概括)並不會更動做爲傳入的數組(調用reduce的數組),因此它也沒有反作用。一個簡單的例子以下:數組
const aArray = [0, 1, 2, 3, 4, 5] const sum = aArray.reduce(function(pValue, value, index, array){ return pValue + value }) console.log(sum) // 15
數組的reduce(概括)方法,還有另外一種語法樣式,是帶有初始值的,這會比較接近Redux中的reducer樣式,以下面的例子:瀏覽器
const initialState = 0 const sum = [1, 2, 3, 4, 5].reduce(add, initialState) function add(a, b) { // `a` 表明前一個狀態 // `b` 表明目前在數組中的項目 return a + b } console.log(sum) // 15
reduce(概括)方法具備分散運算的特色,常見於下面幾種應用之中:緩存
兩相比較最後取出特定的值(最大或最小值)框架
計算全部成員(值),總合或相乘dom
其它須要兩兩處理的狀況(組合巢狀數組等等)異步
不過,Redux中的reducer與數組中的reduce方法並不相同,其中最大的差別,是reducer並非對一整個列表進行概括運算,而是對一個action(動做)與目前的state進行概括運算,回傳出新的state。函數
當一個函數是純函數時,咱們能夠說
輸出
只取決於輸入
測試
對於函數來講,具備反作用表明着可能會更動到外部環境,或是更動到傳入的參數值。函數的區分是以 純(pure)函數 與 不純(impure)函數 二者來區分,但這不光只有無反作用的差別,還有其餘的條件。純函數(pure function)即知足如下三個條件的函數,如下的定義是來自於Redux的概念:優化
給定相同的輸入(傳入值),必定會返回相同輸出值結果(返回值)
不會產生反作用
不依賴任何外部的狀態
一個典型的純函數的例子以下:
const sum = function(value1, value2) { return value1 + value2 }
套用上面說的條件定義,你能夠用下面觀察來理解它是否是一個純函數:
只要每次給定相同的輸入值,就必定會獲得相同的輸出值: 例如傳入1與2,就必定會獲得3
不會改變原始輸入參數,或是外部的環境,因此沒有反作用
不依頼其餘外部的狀態,變量或常量
那什麼又是一個不純的函數?看如下的例子就是,它須要依賴外部的狀態/變量值:
let count = 1 let increaseAge = function(value) { return count += value }
在JavaScript中不純函數很常見,像咱們一直用來做爲輸出的console.log
函數,或是你可能會在不少例子看到的alert
函數,都是"不"純函數,這類函數一般沒有返回值,都是用來做某件事,像console.log
會更動瀏覽器的主控臺(外部環境)的輸出,也算是一種反作用。
每次輸出值都不一樣的不純函數一類,最典型的就是Math.random
,這是產生隨機值的內建函數,既然是隨機值固然每次運行的返回值都不同。
例如在數組的內建方法中,有一些是有反作用,而有一些是無反作用的,這個部份須要查對應API纔可以清楚。不會改變傳入的數組的,會在做完某件過後返回一個新數組的方法,就是無反作用的純函數(方法),而會改變原數組就算是不純函數(方法)了。
下面是兩個在數組中做一樣事情的不一樣方法,都是要取出只包含數組的前三個成員的數組。一個用splice
,另外一用是slice
,看起來都很像,連這兩個方法的名稱都很像,但倒是徹底屬於不一樣的種類:
// 不純粹(impure),splice會改變到原數組 const firstThree = function(arr) { return arr.splice(0,3) } // 純粹(pure),slice會返回新數組 const firstThree = function(arr) { return arr.slice(0,3) }
其餘有許多內建的或經常使用的函數都是免不了有反作用的,例如這些應用:
會改變傳參(對象、數組)的函數(方法)
時間性質的函數,setTimeout等等
I/O相關
數據庫相關
AJAX
純函數固然有它的特別的優勢:
代碼閱讀性提升
較爲封閉與固定,可重覆使用性高
輸出輸入單純,易於測試、調試
由於輸入->輸出結果固定,能夠緩存或做記憶處理,在高花費的應用中可做提升運行效率的機制
最後,並非說有反作用的函數就不要使用,並且要很清楚的理解這個概念,而後儘量在你本身的撰寫的通常功能函數上使用純函數,以及讓必要有反作用的函數獲得良好的管控。如今已經有一些新式的函數庫或框架(例如Redux),會特別強制要求在某些地方只能使用純函數,而具備反作用的不純函數只能在特定的狀況下才能使用。
注: 雖然在反作用與純函數的介紹中,咱們有提到一些調用外部API(console.log/alert)、時間(Date())、隨機(Math.random)也屬於有反作用的調用,但以等級來區分它們只算是"輕度"或"微量"的反作用,這些在reducer或Action Creators能不能用?答案是能夠用但也不要用,它會影響到純函數的一些優化。以在反作用的主題來講,異步運行纔是"中度"或"通常"等級的反作用,咱們談到反作用一般是指這個等級的。固然也有"重度"等級的反作用,那是另外一個層次的特殊應用狀況討論,例如組合出來的複雜異步運行流程結構。