redux原理——ruduce函式和compose函式
reduce()合併函式核心:每次的返回值是一個函式,再用該函式去執行下一個陣列元素(陣列元素先執行傳入引數返回)
講redux之前首先要理解一個函式-----reduce()
語法 array.reduce(function(total, currentValue, currentIndex, arr), initialValue) 引數說明: 一、function(total,currentValue, index,arr) 必需。用於執行每個陣列元素的函式。 函式引數: total 必需。初始值, 或者計算結束後的返回值。 currentValue 必需。當前元素 currentIndex 可選。當前元素的索引 arr 可選。當前元素所屬的陣列物件。 二、initialValue 可選。傳遞給函式的初始值
reduce()函式有兩種用法,一般我們只用到了第一種,即累加(這裡不再舉例)
reduce() 方法接收一個函式作為累加器,陣列中的每個值(從左到右)開始縮減,最終計算為一個值。
還有一種比較高階的用法:
reduce() 可以作為一個高階函式,用於函式的 compose。
注:意思就是寫個函式 能將多個函式進行組合成一個函式,就是一元鏈式函式
注意: reduce() 對於空陣列是不會執行回撥函式的。
例子:這裡想到了陣列的reduce()函式
實現思路:要想實現一個這樣的函式,肯定是需要有一個遍歷的過程,一個函式的執行結果是另一個函式的引數,那這樣就需要有個累計的過程,綜合以上2點,想到陣列中有個reduce函式。這裡我們來看看reduce函式
接下來實現:chained函式
function chained(funcs) {
return function(input){
return funcs.reduce(function(input, fn){ return fn(input) }, input);
}
}
chained([f3,f2,f1])(2) //呼叫
函式解析:分為以下4個步驟解析
chained函式入參:funcs 函式陣列 返回值:入參為input的函式(這裡稱為鏈式回撥函式)
鏈式回撥函式:入參:input 初始值 返回值:reduce()函式 funcs 函式陣列 執行reduce()函式
reduce函式:入參:計算函式和初始值
計算函式:function(input, fn){ return fn(input) }
首次入參:input輸入值 fancs陣列的第一個元素 fn1
二次入參:fn1(input)執行後返回值 fancs陣列的第一個元素 fn1
...以此類推,知道fancs的陣列元素全部參與執行
抽象理解:reduce 英文意思:減少;縮小
A.reduce(function(total, currentValue, currentIndex, arr), initialValue) 可以理解為逐漸減少陣列A的元素,減少執行該過程是傳給回撥函式,用作新的入參,而減少後變為回撥函式的另一個入參(即total返回值)
陣列A元素變化示意圖:元素 ====> 入參 ====>返回值 ====> 入參 ====>……====>最終合成結果
——————————————————————————————————————————————————————
compose函式:函式原始碼參見:https://github.com/reduxjs/redux/blob/v3.7.2/src/compose.js
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
return funcs.reduce((a, b) => (...args) => b(a(...args))) //從左到右
}
將上面的寫法轉換為es5:
export default function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}
if (funcs.length === 1) {
return funcs[0]
}
//return funcs.reduce((a, b) => (...args) => b(a(...args)))
//下面函式是返回的compose函式
return funcs.reduce(
//下面返回函式是reduce的回撥函式 接收 入參 a, b
//a為fn1 ,b為fn2(沒有傳入初始值)
function(a,b){
//下面返回函式是reduce的回撥函式實際執行函式
return function(...args){ //這裡...args指的是compose函式傳入的引數
var transferVal = a(...args)
return b(transferVal)
}
}
)
}
chained([f3,f2,f1])(2) //呼叫
執行過程說明:
我們一步一步分解一下, funcs 初始化的值為 funcs = [fn1,fn2,fn3], reduce執行
第一步時
a = fn1
b = fn2
...args = 2
b(a(2)) = fn2(fn1(2))
(2) => b(a(2)) = (2) = > fn2(fn1(2))
第二步時
a = (2) = > fn2(fn1(2)) // 避免和後面混淆,rest引數名修改為 ag
b = fn3
b(a(...args)) = fn3( a(...args) ) = fn3(fn2( fn1(...args) )) // 這一步是關鍵,a(...args)執行後作為b函式的入參,也就是 ...ag = fn3(...args)
(...args) => b(a(...args)) = (...args) = > fn3(fn2(fn1(...args)))
所以最後返回的就是這樣的一個函式 (...args) = > fn3(fn2(fn1(...args)))
reduce()合併函式核心:每次的返回值是一個函式,再用該函式去執行下一個陣列元素(陣列元素先執行傳入引數返回)
說明:這裡是從左到右
從右到左寫為 funcs.reduce((a, b) => (...args) => a(b(...args)))