阅读 78

认识一下函数柯里化| 8月更文挑战

什么是函数柯里化

函数柯里化,是把函数的多个参数拆分,变成接收小于原来参数个数(一般是一个)的函数。然后该函数返回还是函数,可以继续接受参数,直到没有参数传入或者传入的参数和定义的参数已经相等了,才执行函数。

结合例子来看看:

正常的add函数:

function add (a, b) {
    return a + b
}

add(1, 1) // 2
复制代码

把函数改成柯里化:

function add (a) {
    return function (b) {
        return a + b
    }
}

add(1)(1) // 2
复制代码

这个只是个是很简单的版本,只是想通过这个例子让你们认识下柯里化。

认识了柯里化之后,下面看看怎样改进。

改进的函数柯里化

大家可以看到,上面的add函数只能传2个参数,传多了没效果,传少了也不行

我期待的add函数不需要固定参数,可以动态变化

第一种写法

function curry(fn) {
    const len = fn.length
    return function anonymous(...args) {
        if(args.length >= len) {
           return fn.apply(null, args)
        } else {
           return anonymous.bind(this, ...args)
        }
     }
}
function add (a,b,c) {
    return a + b + c
}
add = curry(add)
add(1)(1)(1) // 3
add(1)(1,1) // 3
add()(1,1,1) // 3
复制代码

解析:

  • 这里是把add函数当作参数传入curry中,记录add函数的长度(接受几个参数),返回一个新函数
  • 在新函数里面判断如果函数传入的参数大于等于add函数的长度,则直接执行函数
  • 如果小于则继续返回该函数。直到函数传入的参数大于等于add函数的长度,此时执行函数,然后返回。

这个函数是根据add定义的参数作判断,如果你定义的参数是2个,则传入2个参数就会执行,如果你定义的参数是3个,则传入3个参数就会执行。

这个就是需要定义add函数的时候要确定参数的个数。

如果我定义add函数的时候,不想确定参数的个数呢?

答案是可以的。

第二种写法

function curry(fn) {
    let args = []
    return function anonymous() {
        if(arguments.length === 0) {
           const params = [...args]
           args = []
           return fn.apply(null, params)
        } else {
           args.push(...arguments)
           return anonymous
        }
     }
}
function add (...args) {
   return args.reduce((acc, prev) => acc + prev)
}
add = curry(add)
add(1)(1)(1)() // 3
add(1)(1,1)() // 3
复制代码

解析:

这个写法可以支持add函数不定参数,原理是根据最后执行的时候如果是空参数,则执行该函数。 所以当你参数传完了之后再加上一个空参数的执行,就可以了。

再看看另一种写法:

第三种写法

function add(...args) {
  let fn = function (...args1) {
    args.push(...args1)
    return fn 
  }
  fn.toString = function () {
    return args.reduce((acc, prev) => acc + prev)
  }
  return fn
}
add(1)(1) == 2 // true
add(1,1) == 2 // true
add(1)(1)(1) == 3 // true
add(1)(1,1) == 3 // true
add(1)(1,1).toString() // 3
+add(1)(1,1) // 3
add(1)(1,1) + '' // 3
复制代码

解析: 这个是利用调用add函数时生成一个新函数,然后改写了这个新函数的toString方法并返回该新函数。

所以调用add函数都是返回函数,如果你console出来就是一个函数,因为改写了toString方法,所以可以利用隐私转换(如果不了解隐私转换,可以看看我之前这篇文章)或者调用toString方法去得到期望的值。

总结

以上就是函数柯里化的几种写法,它不局限于只有一种写法,可以灵活多变。大家可以都看看学习,找到适合自己的。希望对你们有帮助。

文章分类
前端
文章标签