从一道面试题看函数柯里化


前言

前端面试问到闭包的作用,一般会说模块化及变量封装以及延长局部变量生命周期。函数柯里化一般需要延长局部变量生命周期,就用到闭包。今天面试官问以下问题:

sum(1, 2)  // 3
sum(1)(2)  // 3
sum(1, 2)(3)(4)// 10 
//怎样的柯里化能实现这个sum函数

开始我知道柯里化需要保存中间值,于是写出以下的代码。

function curry() {
  let reduce = 0;
  return function sum() {
    let len = arguments.length;
    for (let i = 0; i < len; i++) {
      reduce += arguments[i];
    }
    return reduce;
  }
}


let sum = curry()
console.log(sum(1, 2));// 3
sum(1)(2)  // 3
sum(1, 2)(3)(4)// 10 

运行结果:

在这里插入图片描述
结果显示这个函数不能循环调用。可是如果返回argument.callee那么能循环调用,可是不能知道每次调用完最终的值。结果是这题无解。

一、什么是函数柯里化?

函数柯里化(function currying)。currying 的概念最早由俄国数学家 Moses
Schönfinkel 发明,而后由著名的数理逻辑学家 Haskell Curry 将其丰富和发展,currying 由此得名。
currying 又称部分求值。一个 currying 的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。

二、实现函数柯里化

var currying = function (fn) {
  var args = [];
  return function () {
    if (arguments.length === 0) {
      return fn.apply(this, args);
    } else {
      [].push.apply(args, arguments);
      return arguments.callee;
    }
  };
};

var sum = (function () {
  var reduce = 0;
  return function () {
    for (var i = 0, l = arguments.length; i < l; i++) {
      reduce += arguments[i];
    }
    return reduce;
  };
})();

var sum = currying(sum); // 转化成 currying 函数
sum(100,300)(400)(100); // 未真正求值
sum(200); // 未真正求值
sum(300); // 未真正求值
console.log(sum());// 求值并输出:1400

总结

我们完成了一个 currying 函数的编写。当调用 sum()时,如果明确地带上了一些参数,表示此时并不进行真正的求值计算,而是把这些参数保存起来,此时让 sum 函数返回另外一个函数。只有当我们以不带参数的形式执行 sum()时,才利用前面保存的所有参数,真正开始进行求值计算。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值