从柯里化实现一个add方法讲起

247 阅读1分钟

当我们去面试时,不免会被面试官问到什么叫做函数柯里化

    柯里化(Currying)[1]是一种关于函数的高阶技术。它不仅被用于 JavaScript,还被用于其他编程语言。

    柯里化是一种函数的转换,它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)。

    柯里化不会调用函数。它只是对函数进行转换。

这个在很多博客上都有讲到,可能还会问到叫你手写出来

function curry(fn) {
  return _curry.call(this, fn, fn.length);
}
function _curry(fn, len, ...args) {
  return function(...params) {
    const _args = args.concat(params);
    if (_args.length >= len) {
      return fn.apply(this, _args);
    } else {
      return _curry.call(this, fn, len, ..._args);
    }
  }
}

以上都是通常的,还可能会问到

// 实现一个add方法,使计算结果能够满足如下预期:
console.log(add(1)(2)(3)) // 6;
console.log(add(1, 2, 3)(4)) // 10;
console.log(add(1)(2)(3)(4)(5)) // 15;

function add() {
  let args = [...arguments];
  function _add() {
    args = args.concat([...arguments]);
    return _add;
  }
  _add.toString = function() {
    return args.reduce((pre, cur) => {
      return pre + cur;
    })
  }
  return _add;
}

网上的答案都是这样的,但是复制到node,或者浏览器执行的话返回的都是一个函数,本来的题解的用意是console.log会隐式转换调用toString()方法,把_add函数添加属性,这样子就不会执行原型链中的Object.prototype.toString()方法。可实际上_add.toString是undefined,这是为什么呢?

最后发现console.log(add(1,2,3).toString()) 才行,没有隐式转换