美文网首页
函数柯里化

函数柯里化

作者: 梦晓半夏_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