Skip to content

JS 柯里化的思考

Published: at 02:12 PMSuggest Changes

写博客的目的不是讲柯里化,而是学习过程中的一些思考。

这儿有一篇文章很好的讲了柯里化:柯里化(Currying)

问题 Level 0

实现 add 函数 1 + 2 + 3 + 4 = 10

console.log(add(1, 2, 3, 4)); // 10
console.log(add(1)(2)(3)(4)()); // 10

题解

function add() {
  let sum = [...arguments].reduce((a, b) => a + b);
  if (arguments.length > 1) return sum;
  return function (...args) {
    if (args.length == 0) return sum;
    return add([...args].reduce((a, b) => a + b) + sum);
  };
}

很简单的一道题,不过关键的是后面几道题,解的过程有了一些思考。

提升

Level 1

console.log(add(1, 2, 3, 4)());
console.log(add(1)(2)(3)(4)());
console.log(add(1)(2, 3)(4, 5, 6)());
console.log(add(1, 2, 3, 4)(5, 6)(7)());

题解

function add() {
  let sum = [...arguments].reduce((a, b) => a + b);
  return function (...args) {
    if (args.length == 0) return sum;
    return add([...args].reduce((a, b) => a + b) + sum);
  };
}

Level 2

和 Level 1 的区别是第一行 add(1, 2, 3, 4)后面少了个括号

console.log(add(1, 2, 3, 4));
console.log(add(1)(2)(3)(4)());
console.log(add(1)(2, 3)(4, 5, 6)());
console.log(add(1, 2, 3, 4)(5, 6)(7)());

Level 3

和 Level 2 的区别是后面两行,也少了个括号

console.log(add(1, 2, 3, 4));
console.log(add(1)(2)(3)(4)());
console.log(add(1, 2, 3, 4)(5, 6)(7));
console.log(add(1)(2, 3)(4, 5, 6));

题解

我觉得这个不太可能。。有解吧?

没想出来,占位,心态崩了。

Level 4

闲着没事扛一下,看看哪个大佬能解。

console.log(add(1, 2, 3, 4));
console.log(add(1)(2)(3)(4)());
console.log(add(1, 2, 3, 4)(5, 6)(7));
console.log(add(1)(2, 3)(4, 5, 6));
console.log(add(1)()(2)()(3)()(4)());
console.log(add(1, 2, 3, 4)()(5, 6)()(7));

搜集的一些有趣的代码

很眼熟的暴力题解吧

function add(a) {
  return function (b) {
    return function (c) {
      return a + b + c;
    };
  };
}
console.log(add(1)(2)(3)); // 6

利用了修改 toSting 方法

var add = function (m) {
  var temp = function (n) {
    return add(m + n);
  };
  temp.toString = function () {
    return m;
  };
  return temp;
};
console.log(add(3)(4)(5)); // 12
console.log(add(3)(6)(9)(25)); // 43

这个最有意思,隐式转换,解出来了,又没解出来,知道为什么吗?

let add = function add(...args) {
  const sum = args.reduce((acc, val) => acc + val, this);
  const chain = add.bind(sum);
  chain.valueOf = () => sum;
  return chain;
}.bind(0);

console.log('add(1, 2, 3, 4) = ' + add(1, 2, 3, 4));
console.log('add(1)(2)(3)(4) = ' + add(1)(2)(3)(4));
console.log('add(1, 2, 3, 4)() = ' + add(1, 2, 3, 4)());
console.log('add(1)(2) = ' + add(1)(2));
console.log('add(1, 2)(3) = ' + add(1, 2)(3));
console.log('add(1, 2, 3)(4, 5)(6) = ' + add(1, 2, 3)(4, 5)(6));

// 再跑一下这个用例看看
console.log(add(1, 2, 3, 4));
console.log(add(1)(2)(3)(4)());
console.log(add(1, 2, 3, 4)(5, 6)(7));
console.log(add(1)(2, 3)(4, 5, 6));

大开眼界的解法

这个是群友德巨(德国巨佬的简称)的解法,这个代码一贴出来,群里一片 66666

eval(
  `console.log(add(1, 2, 3, 4));
console.log(add(1)(2)(3)(4)());
console.log(add(1, 2, 3, 4)(5, 6)(7));
console.log(add(1)(2, 3)(4, 5, 6));
console.log(add(1)()(2)()(3)()(4)());
console.log(add(1, 2, 3, 4)()(5, 6)()(7));
`
    .replace(/(add)| /g, '')
    .replace(/(\(|\)|,)+/g, '+')
    .replace(/g\+/g, 'g(')
    .replace(/;/g, '0);')
);

Previous Post
JS 为什么是单线程的
Next Post
JSONP 与 CSP 的探究