一道有意思的题目

一道有意思的题目

三月 09, 2021 本文共计: 336 字 预计阅读时长: 1分钟

题目

1
2
3
4
5
6
/**
* add = num => num+10
* mult = num => num*2
* 实现一个fn = compose(mult, add)
* 使得fn(5) = 20
*/

答案一

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

const add = num => num + 10;
const mult = num => num*2;
const other = num => num *3;


const compose = function () {
const _o = Array.from(arguments) || [];
return function inner(...rest) {
if (!_o.length) { return }
if (_o.length > 1) {
return inner.call(null, _o.splice(0, 1)[0].apply(null, rest))
}

return _o[0].apply(null, rest);
}
}

方案二

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const add = num => num + 10;
const mult = num => num*2;
const other = num => num *3;

function compose(...funcs) {
if (funcs.length === 0) {
return arg => arg
}

if (funcs.length === 1) {
return funcs[0]
}

return funcs.reduceRight((a, b) => (...args) => a(b(...args)))
}

上面是比较好的两种方法,其中第一种是利用了递归的思路,第二种利用了reduce函数,实现了函数组合,至于函数组合的执行顺序,借助reduce&reduceRight来控制。

End

结尾处,可以再次引什出函数柯里化:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

// 计算两数之和
const carry = (f, o) => {
o = o || [];
const _len = f.length;

return function () {
const _o = [...o.slice(), ...Array.from(arguments)];

if(_o.length < _len) {
return carry.call(this, f, _o);
}

return f.apply(this, _o);
}
};

const sum = (a,b,c) => a+b+c;
const newSum = carry(sum);

console.log(newSum(1)(2)(3));

核心思维:借助闭包的活动对象,保留柯里参数,当柯里参数与被柯里函数的参数长度一致的时候执行。