# 柯里化(Currying)

# 高阶函数

将函数作为参数或者返回值是函数的函数

  • 例如

简单的分步加法函数

function add(a){
    return function(b){
        return a+b
    }
}
let add1 = add(1)
add1(2) === 1+2 // true
1
2
3
4
5
6
7

es6写法

let add = a => b => a + b
1
  • 再例如
function strTools(fn){
    return function(str){
        return fn(str)
    }
}
1
2
3
4
5

# 柯里化

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

上面的add例子就是柯里化的一个应用

柯里化后的函数,将第一个参数变量通过闭包存在了函数里面,然后原来需要n个参数的函数变成只需要n-1个参数的函数了

  • 经典的栗子
let add = (a, b) => a + b
console.log(add(2,3));//5
console.log(add(2,4));//6
console.log(add(2,5));//7
1
2
3
4

柯里化后

function add(a){
    return function(b){
        return a+b
    }
}
// es6
let add = a => b => a + b

let add2 = add(2)
console.log(add2(3)) // 5
console.log(add2(4)) // 7
console.log(add2(5)) // 6
1
2
3
4
5
6
7
8
9
10
11
12

es6写法中n个连续箭头组成的函数实际上就是柯里化了n-1次

也就是连续箭头函数就是多次柯里化函数的es6写法

let test = x => y => z => k => x + y + z + k
console.log(test(1)(2)(3)(4))//10
1
2

# 总结柯里化的功能

  • 惰性求值
  • 可以提前传递部分参数
  • 参数复用

# 一个通用的封装方法

function curry(fn, ...args) {
    return fn.length > args.length ? (...args2) => curry(fn, ...args, ...args2) : fn(...args)
}

function fn(a, b, c, d) {
    console.log(a + b + c + d)
}

fn = curry(fn)
fn(1)(2)(3, 4) // 10
1
2
3
4
5
6
7
8
9
10