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



    前言

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

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

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

    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 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    运行结果:

    在这里插入图片描述
    结果显示这个函数不能循环调用。可是如果返回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
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28

    总结

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

  • 相关阅读:
    第十章 单调栈 part03 84. 柱状图中最大的矩形
    WPF真入门教程30--顺风物流单据管理系统
    Python编程-- BS4解析
    Android 包体积优化(未完成)
    用Python做一个软件,你想看的视频可以能看 ~ 当然必须是正经的
    猿创征文|11个开发者必备工具,赶快收藏
    计算机网络期末复习-Part2
    xpath获取带命名空间节点注意事项
    spring如何解决循环依赖
    手把手教你用python做一个年会抽奖系统
  • 原文地址:https://blog.csdn.net/weixin_45045689/article/details/126337087