美文网首页
函数柯里化

函数柯里化

作者: 梦晓半夏_d68a | 来源:发表于2020-09-01 13:39 被阅读0次

柯里化

百度百科是这么解释的:

把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术

  这样解释有一点抽象,可以用例子来理解函数柯里化。

    function sayHello(country, city, name) {
      console.log(`大家好,我叫${name},来自${country}${city}`)
    }
    sayHello('中国', '上海', 'Lily')
    sayHello('中国', '上海', 'Nancy')
    sayHello('中国', '上海', 'Ava')

  将函数柯里化:

    function sayHello(country) {
      return function (city) {
        return function (name) { 
          console.log(`大家好,我叫${name},来自${country}${city}`)
        }
      }
    }
    let setInfo = sayHello('中国')('上海')
    setInfo('Lily')
    setInfo('Nancy')
    setInfo('Ava')
执行结果

代码分析:函数柯里化实际上就是把sayHello函数的 country、 city、name 三个参数变成了先用一个函数接收 country 然后返回一个函数接收 city 再返回一个函数接收 name 参数并在该函数内对参数进行打印。其实就是把一个多参数的函数,转化为单参数函数,并且返回接受余下的参数而且返回结果。一个柯里化了的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来,待到函数被真正需要求值的时候,之前传入的所有参数才会被一次性用于求值。

但是费这么大劲封装这么多层,有什么好处呢?
  上面的示例中正常来说直接调用sayHello函数就可以了,但是如果多次调用时前两个参数传值一致,就可以将前两个参数country、city进行复用,这样别的地方就能够直接调用setInfo 函数,让参数能够复用,调用起来更方便。

使用场景

  • 参数复用
  • 提前确认,避免多次判断
  • 延迟计算

简单封装一个函数柯里化方法

   function curry(fn) { 
      // 记录fn的形参个数
      let len = fn.length
      return function temp() {
        // 收集传递的实参
        let args = [...arguments]
        // 实参数量大于形参
        if (args.length > len) {
          return '实参个数超标'
        // 实参数量等于形参
        }else if (args.length === len) {
          return fn(...args)
        }else {
          // 返回函数继续传参
          return function () {
            return temp(...args, ...arguments)
          }
        }
      }
    }

测试封装效果:

   function sayHello(country, city, name) {
      console.log(`大家好,我叫${name},来自${country}${city}`)
    }
    let c1 = curry(sayHello)
    c1('中国')('上海')('Nancy')  // 大家好,我叫Nancy,来自中国上海

最后,再做一道经典面试题

实现一个add方法,使计算结果能够满足如下条件:
add(1)(2)(3)(4) = 10
add(1,2)(3)(4)) = 10
add(1, 2, 3)(4) = 10
add(1,2,3,4) = 10

代码实现

    function curry(fn) { 
      // 记录fn的形参个数
      let len = fn.length
      return function temp() {
        // 收集传递的实参
        let args = [...arguments]
        // 实参数量大于形参数量
        if (args.length > len) {
          return '实参个数超标'
        // 实参数量等于形参数量
        }else if (args.length === len) {
          return fn(...args)
        }else {
          // 返回函数继续传参
          return function () {
            return temp(...args, ...arguments)
          }
        }
      }
    }

    function addNum(a,b,c,d){
      return a+b+c+d;
    }
    let add = curry(addNum)
    console.log(add(1)(2)(3)(4)) // 输出10
    console.log(add(1,2)(3)(4)) // 输出10
    console.log(add(1,2,3)(4)) // 输出10
    console.log(add(1,2,3,4)) // 输出10

相关文章

网友评论

      本文标题:函数柯里化

      本文链接:https://www.haomeiwen.com/subject/pscqdktx.html