前言
在compose里面調(diào)用了Array.prototype.reduce方法心包,首先來分析一下這個(gè)方法的作用,詳細(xì)可以查看reduce文檔馒铃;
reduce
reduce方法蟹腾,是從左向右,對數(shù)組中的每個(gè)元素按照傳入回調(diào)函數(shù)和初始值進(jìn)行運(yùn)算区宇;舉個(gè)栗子:
let arr = [1,2,3,4,5];
let result = arr.reduce((a,b)=>{
return a+b;
});
console.log(result);
這個(gè)栗子最終會輸出
15
即相當(dāng)于做了以下的運(yùn)算:
((((1+2)+3)+4)+5)
即相當(dāng)于娃殖;
let arr = [1,2,3,4,5];
let add = (a,b)=>{
console.log(`${a}+$=`,a + b);
return a+b;
}
let result = arr.reduce((a,b)=>{
return add(a,b);
});
console.log(result);
有意思的事情
下面來看一個(gè)模擬redux插件的實(shí)現(xiàn)方式
let mynext = function(action){
console.log(action);
}
let wrapper0 = next=>action=>{
console.log('before');
let result = next(action);
console.log('after');
return result;
}
let wrapper1 = next=>action=>{
console.log('w1 before');
let result = next(action);
console.log('w1 after');
return result;
}
let wrapper2 = next=>action=>{
console.log('w2 before');
let result = next(action);
console.log('w2 after');
return result;
}
let result = compose(wrapper0,wrapper1,wrapper2);
console.log(result(mynext)('hello'));
最終輸出結(jié)果
看到結(jié)果是不是很驚訝议谷,這個(gè)就類似redux的中間件調(diào)用過程了炉爆,中間的是原始的store.dispatch,外面是各個(gè)插件wrapper2 ... 等的輸出結(jié)果。其實(shí)這就是redux實(shí)現(xiàn)插件的內(nèi)部機(jī)制芬首。
compose源碼解析
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) => a(b(...args)))
}
以上是ES6的源碼赴捞,在redux的lib文件夾下,有一份編譯好的ES5的源碼郁稍,如下
function compose() {
for (var _len = arguments.length, funcs = Array(_len), _key = 0; _key < _len; _key++) {
funcs[_key] = arguments[_key];
}
if (funcs.length === 0) {
return function (arg) {
return arg;
};
}
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(function (a, b) {
return function () {
return a(b.apply(undefined, arguments));
};
});
}
來看一下compose做了什么事情:
- 將arguments轉(zhuǎn)化為數(shù)組赦政;
- 在數(shù)組上,調(diào)用reduce方法耀怜,數(shù)組的內(nèi)部是function恢着,并且最終返回一個(gè)function;