柯里化
百度百科是这么解释的:
把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
这样解释有一点抽象,可以用例子来理解函数柯里化。
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
网友评论