前言
在使用redux的過程中,不免要用到中介軟體,用到中介軟體,就免不了使用compose方法來解決中介軟體層層巢狀的問題,那麼redux中的compose方法實現原來是怎樣的呢?
用法
compose(…functions)
這是函數語言程式設計中的方法,為了方便,被放到了 Redux 裡。
當需要把多個 store 增強器(中介軟體) 依次執行的時候,需要用到它。
引數
(arguments): 需要合成的多個函式。預計每個函式都接收一個引數。它的返回值將作為一個引數提供給它左邊的函式,以此類推。例外是最右邊的引數可以接受多個引數,因為它將為由此產生的函式提供簽名。(譯者注:compose(funcA, funcB, funcC) 形象為 compose(funcA(funcB(funcC()))))
返回值
(Function): 從右到左把接收到的函式合成後的最終函式。
一個例子
import {componse} from `redux`
function add1(str) {
return 1 + str;
}
function add2(str) {
return 2 + str;
}
function sum(a, b) {
return a + b;
}
let str = compose(add1,add2,add3)(`x`,`y`)
console.log(str)
//輸出結果 `12xy`
複製程式碼
上面程式碼compose(add1,add2,add3)(`x`,`y`)方法實際上等同於下面的程式碼
add1(add2(add3(`x`,`y`)))
複製程式碼
一步步解析compose方法內部的實現,首先從用法compose(add1,add2,add3)(`x`,`y`)來看,compose方法的執行結果顯然返回的是一個函式.
function compose(...fns){
return function(...args){ // args => [`x`,`y`]
...處理程式碼
}
}
複製程式碼
由於只有最右邊的中介軟體才能接受多個引數,我們先將它取出來,將多個的引數單獨傳給他
其他的中介軟體函式都只有一個引數,就是他右側中介軟體函式執行之後的返回值
function compose(...fns){
return function(...args){ // args => [`x`,`y`]
let last = fns.pop(); // sum
fns.reduceRight((val,fn)=>{
return fn(val)
},last(...args))
}
}
複製程式碼
我們來分析一下 fns.reduceRight中的執行
fns.reduceRight((val,fn)=>{
return fn(val)
},last(...args))
複製程式碼
第一次 val 為 sum(`x`,`y`) fn為 add2
第二次 val 為 add2(sum(`x`,`y`)) fn 為 add1
執行結束 返回 add1(add2(sum(`x`,`y`)));
這樣,compose的執行原理就基本解釋清楚了,但是,這個只是redux中compose方法以前的實現方法.現在redux中對於compose的實現換了一種更加優雅的方法
redux中compose方法最新實現
它摒棄了原來將最後一箇中介軟體函式提取出來的方法,直接一行程式碼將內部邏輯實現了
function compose(...fns){
return fns.reduce((a,b)=>(...args)=>a(b(...args)))
}
複製程式碼
我們還是以compose(add1,add2,sum)(`x`,`y`)為例對fns.reduce進行解析
fns.reduce((a,b)=>(...args)=>a(b(...args)))
//展開
function compose(...fns){
return fns.reduce((a,b)=>{
return (...args)=>{
return a(b(...args))
}
}
}
})
//第一次 執行 a為add1 b為add2
//第二次 執行 a為 (...args)=>{
return add1(add2(...args))
}
b為 sum
//執行結束 返回
(...args)=>{
return ((...args)=>{
return add1(add2(...args))
})(sum(...args))
}
//為了能更好的區分邏輯,我把這裡稍微改一下
(...args2)=>{
return ((...args)=>{
return add1(add2(...args))
})(sum(...args))
}
//等價於
(...args2)=>{
add1(add2(sum(...args2)))
}
//args2替換為[`x`,`y`]
add1(add2(sum(`x`,`y`)))
複製程式碼
邏輯總算是理清楚了,真的是有夠繞的
結語
每次原始碼閱讀與解析,總是能夠在不經意的角落發現令人讚歎的程式碼,程式設計的魅力大概就在這裡吧
如果覺得還可以,能在諸君的編碼之路上帶來一點幫助,請點贊鼓勵一下,謝謝!