Open luckept opened 2 years ago
此处补充一个知识点,关于使用运算符来使匿名函数立即执行(PS:和本题的场景无关)
! function(x, y) { console.log(x + y) } (1, 2) // 3
+ function(x, y) { console.log(x + y) } (1, 2) // 3
- function(x, y) { console.log(x + y) } (1, 2) // 3
~ function(x, y) { console.log(x + y) } (1, 2) // 3
void function(x, y) { console.log(x + y) } (1, 2) // 3
function sum() {
let sum = 0
function t(...args){
sum += args.reduce((a,b) => a + b, 0)
return t
}
t.valueOf = function() {
return sum
}
t.toString = function () {
return sum+ ''
}
return t(...arguments)
}
不知是否可行
function sum(...nums) {
let acc = 0
const fn = (...nums) => (acc = nums.reduce((acc, cur) => acc + cur, acc), fn)
fn[Symbol.toPrimitive] = () => acc
return fn(...nums)
}
@luckept 可能二字去掉!
发个 Typescript 版 🙈
const curry = <T extends (...args: any[]) => any>(fn: T, maxArgsLen = 99) => {
const argsLen = fn.length || maxArgsLen;
const argList: any[] = [];
const callback = (...args: any[]) => {
argList.push(...args);
if (argList.length >= argsLen || args.length === 0) {
return fn(...argList);
} else {
return callback;
}
};
return callback;
};
// test 1
const sum = (num1: number, num2: number, num3: number) => num1 + num2 + num3;
const curredSum = curry(sum);
console.log(curredSum(1)(2)(9));
// test 2
const sumAny = (...args: number[]) => args.reduce((pre, curr) => pre + curr);
const curredSumAny = curry(sumAny, 5);
console.log(curredSumAny(1, 2, 3)(2)());
// test 3
const curredSumAny2 = curry(sumAny, 5);
console.log(curredSumAny2(1, 2, 3)(2)(1000));
要求如下
最终实现的迷惑版
如何理解上述最终实现
一行一行分析,第一步创建 acc = 0,其实是为了迷惑而迷惑,完全可以命名成其他诸如 sum 之类好理解的变量名,它的目的是用来闭包留存累加结果
第二步,如何理解形式为
const fn = () => (xxx, fn)
的代码而简写版只是为了利用逗号返回后一个值的特性,来省略代码
第三步,理解 acc = nums.reduce((acc, cur) => acc + cur, acc)
这里首先去掉迷惑的命名来理解,把闭包变量改名为 sum,上述代码变为
sum = nums.reduce((acc, cur) => acc + cur, sum)
,要注意的是这里的后一个 sum 就不再是利用逗号运算符的特性去返回 sum 了,而是每次让柯里化的闭包累加结果作为下一次 reduce 函数的初始值第四步,理解
fn[Symbol.toPrimitive] = () => acc
因为柯里化的返回结果永远是一个函数,而我们如何去通过这个函数获取到闭包对象的值呢?这里按题目要求可以看见最终输出的时候利用了
+
号,这会触发函数的转换,而 [Symbol.toPrimitive] 则可以定义转换的规则,把闭包值作为转换后的结果(当然,这里也可以利用 valueOf 和 toString)