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



    前言

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

    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()时,才利用前面保存的所有参数,真正开始进行求值计算。

  • 相关阅读:
    Oracle/PLSQL: Atan Function
    P30 JComboBox下拉列表框
    LuatOS-SOC接口文档(air780E)-- gpio - GPIO操作
    【MySQL从入门到精通】【高级篇】(十一)Hash索引、AVL树、B树与B+树对比
    Blink SQL内置函数大全
    java基础面试题:说说协程,进程和线程的区别和联系
    机器学习之查准率、查全率与F1
    多媒体内容理解在美图社区的应用实践
    计算机网络的常见面试题
    promise时效架构升级方案的实施及落地 | 京东物流技术团队
  • 原文地址:https://blog.csdn.net/weixin_45045689/article/details/126337087