# 函数柯里化

# 定义

在数学和计算机科学中,柯里化是一种将多个参数的一个函数,转换成一系列使用一个参数的函数的技术。

如何理解 多个参数的一个函数?

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

// 执行add函数,一次性传入两个参数即可
add(1,2) // 3
1
2
3
4
5
6

上面的add函数就是多个参数的一个函数。

假设有一个curry函数可以做到柯里化

var addCurry = curry(add)
addCurry(1)(2) // 3
1
2

# 应用场景

function isType(val, typing) {
  return Object.prototype.toString.call(val) === `[object ${typing}]`
}
console.log(isType('abc','String')) // true
1
2
3
4

柯里化的作用就是让函数变的更加具体。

上面的函数有两个参数,我们可以改造一下,这两个参数分两次传入。

function isString(typing) {
  return function (val) {
    return Object.prototype.toString.call(val) === `[object ${typing}]`;
  };
}

let myIsString = isString("String")
console.log(myIsString('abc'))
console.log(myIsString(123))
1
2
3
4
5
6
7
8
9

上面的函数,使用闭包的形式,将第一次传入的 String 缓存起来, 第一个函数返回一个函数,在调用这个函数,传入第二个参数。得到结果。

# 实现通用的柯里化函数

再来看一个例子:

function sum(a, b, c, d) {
  return a + b + c + d;
}
let sum1 = curry(sum);
let sum2 = sum1(1);
let sum3 = sum2(2, 3);
let res = sum3(4);
console.log(res);
1
2
3
4
5
6
7
8

我们想要实现上述例子中的curry函数。

这里面有一个关键的点:我们要记录每次调用时候传入的参数,并且和函数的参数个数进行比较。如果不满足总个数,就返回新函数,如果传入的个数和参数的个数一致,执行原来的函数。

function curry(fn) {
  const inner = (args = []) => {
    console.log(args); // []
  };
  return inner();
}
curry()
1
2
3
4
5
6
7

上面函数中,在curry函数内部定义了一个函数inner, 并且执行了这个函数。打印出来了初始化的默认参数args。 这是一个技巧,用于存储每次调用时候传入的参数。

function curry(fn) {
  const inner = (args = []) => {
    return args.length >= fn.length ? fn(...args): (...userArgs) => inner([...args,...userArgs])
  };
  return inner();
}
1
2
3
4
5
6

上面这个实现,多少有些不太好理解。

基于类型判断的那个例子,使用柯里化的思路实现一版:

function isType(typing,val) {
  return Object.prototype.toString.call(val) === `[object ${typing}]`
}
let isString = curry(isType('String'))
console.log(isString('abc'))

let isNumber = curry(isType('Number'))
console.log(isString(123))
1
2
3
4
5
6
7
8
最后更新时间: 3/9/2022, 6:54:04 AM