乐趣区

柯里化

参考文章 Understanding Currying in JavaScript
译文 理解 JavaScript 的柯里化

首先柯里化是个什么?


百度的解释:
在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数 (最初函数的第一个参数) 的函数,并且返回接受余下的参数且返回结果的新函数的技术。

  // 现在有一个接受两个参数的函数 函数接受 3 个参数, 并返回 和
  function fn1(param1, param2, param3) {console.log(param1 + param2 + param3)
  }
  fn1('a', 'b', 'c') // abc

  // currying
  function curryingfn1(param1) {return function (param2) {return function (param3) {return (param1 + param2 + param3)
      }
    }
  }
  curryingfn1('a')('b')('c') // abc

  // 为了方便理解 可以依次执行
  const _cfn1 = curryingfn1('a')
  const _cfn2 = _cfn1('b')
  const _cfn3 = _cfn2('c')
  console.info({_cfn1, _cfn2, _cfn3})

得到的执行结果

这里的 fn1(‘a’, ‘b’, ‘c’)=> fn2(‘a’)(‘b’)(‘c’) 的过程就是 柯里化

附:使用箭头函数

  fn3 = (param1) => (param2) => (param3) => console.log('fn3', param1 + param2 + param3)
  fn3('a')('b')('c') // fn3 abc

以上,fn1 作为一个独立的函数已经被转换为一系列函数。

柯里化 能干什么呢?

  // 参数复用
  const regTest = (reg) => (text) => reg.test(text)
  const checkNum = regTest(/\d+/g)
  console.info(checkNum('aaa'), checkNum('123aaa')) //false true

附: 最近看到的一个面试题

// 实现方法
// fn(1) //1
// fn(1)(2) //5
// fn(1)(2)(3) //14

function curryingCount() {
    // 第一次执行时,定义一个数组专门用来存储所有的参数
    var _args = Array.prototype.slice.call(arguments);
    // 在内部声明一个函数,利用闭包的特性保存_args 并收集所有的参数值
    var _adder = function () {_args.push(...arguments);
      return _adder;
    };

    // 利用 toString 隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
    _adder.toString = function () {return _args.reduce(function (a, b = 0) {return a + b * b;});
    }
    _adder.value = _adder
    return _adder;
}
// 或者使用箭头函数!!注意~~~~, 箭头函数没有 this 和 arguments
curryingCount2 = (...arguments) => {
  // 第一次执行时,定义一个数组专门用来存储所有的参数
  const _args = Array.prototype.slice.call(arguments);
  // 在内部声明一个函数,arguments 作为参数传递值
  const _adder = (...arguments) => {_args.push(...arguments);
    return _adder;
  };

  // 利用 toString 隐式转换的特性,当最后执行时隐式转换,并计算最终的值返回
  _adder.toString = () => _args.reduce((a, b = 0) => a + b * b);
  return _adder;
}
退出移动版