composed例子
export default function compose(...funcs) {
// 对函数个数为0的情况特判
if (funcs.length === 0) {
return (arg) => arg;
}
// 对函数个数为1的情况特判
if (funcs.length === 1) {
return funcs[0];
}
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args))
);
}
const add1 = (x) => {
console.log("add1");
return x + 1;
};
const mul2 = (x) => {
console.log("mul2");
return x * 2;
};
const div3 = (x) => {
console.log("div3");
return x / 3;
};
const composedFunc = compose(add1, mul2, div3);
console.log(composedFunc(3));
运行日志
div3
mul2
add1
3
我们拆解的主要是这一行代码
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args))
);
funcs是一个数组,
reduce
arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
reduce有两个参数
- callback 执行数组中每个值 (如果没有提供 initialValue则第一个值除外)的函数,
- initialValue 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。
所以
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args))
);
等价于
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args)),
funcs[0]
);
对吧, 你是这样想的, 但是实际测试一下,
div3
mul2
add1
add1
4
原来的运行日志是3,
现在的运行日志是4,
说明上面的等价, 并不等价
实际上等价于这个
return funcs.reduce(
(a, b) =>
(...args) =>
a(b(...args)),
(x) => x
);
(x)=>x, 是个函数, 相当于数学上的, 如果是加法, 那就是0, 如果是乘法, 那就是1,
总之, 他不能有任何作用; 此处没有作用, 就是它的作用.
callback的四个参数
- Accumulator (acc) (累计器)
- Current Value (cur) (当前值)
- Current Index (idx) (当前索引)
- Source Array (src) (源数组)
(a, b) =>
(...args) =>
a(b(...args)),
a 是Accumulator (acc) (累计器)
b 是Current Value (cur) (当前值)
然后一直循环组合, 最后是这样的
a(b(c(d(e(f(g(x)))))))
我们可以把这些方法抽象为 f(x)
f 就相当于 a · b · c · d · e · f · g
整个reduce最后返回的是
(...args) =>
a(b(...args)),
也就是 f(x)