# 手写函数柯里化

# 附上源码

const curry = (fn, arg) => {
  if (!Array.isArray(arg)) arg = [];
  return function() {
    const restArg = Array.from(arguments);
    const argLength = arg.length + restArg.length;
    const argArr = arg.concat(restArg);
    return argLength < fn.length ? curry(fn, argArr) : fn.apply(null, argArr);
  };
};

const convertToArray = (x, y, z) => {
  return [x, y, z];
};
const curriedConvertToArray = curry(convertToArray);
console.log(curriedConvertToArray(1)(2)(3)); // [1,2,3]
console.log(curriedConvertToArray(1, 2, 3)); // [1,2,3]
console.log(curriedConvertToArray(1, 2)(3)); // [1,2,3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 分析

函数柯里化实际上是将一个有多个参数的函数逐渐变为有固定参数的函数, 而这一过程就是柯里化. 比如有 f(x, y), 将其变为 f(1, y), 这个过程就是函数柯里化. 接下来将用 JS 代码实现curry函数:

1.curry函数接受两个参数, 第一个是被柯里化的函数, 第二个是被柯里化的函数的参数(是可传可不传的). 如果第二个参数不是数组那么将其初始化为一个空数组, 因为后面将会用到apply().

const curry = (fn, arg) => {
  if (!Array.isArray(arg)) arg = [];
};
1
2
3

2.返回一个新的函数, 而函数要做的事情就是柯里化. 我们先梳理一下内部逻辑, 如何判断柯里化完成? 首先, 获取到 fn 的参数个数, 然后再获取到已经柯里化的参数个数, 两者比较, 如果 fn 的参数个数大于柯里化参数个数, 那么表明柯里化还没有完成, 直到前者不大于后者时才能说明已经柯里化完成, 并执行 fn 函数且返回结果.

const restArg = Array.from(arguments);
const argLength = arg.length + restArg.length;
const argArr = arg.concat(restArg);
return argLength < fn.length ? curry(fn, argArr) : fn.apply(null, argArr);
1
2
3
4