js中函数柯里化

282 阅读2分钟

什么是柯里化

定义:对一个多参数函数进行转换,转换成单一参数多次执行的函数
实际应用:接收一部分参数,返回一个函数接收剩余参数,接收足够参数后,执行原函数

示例:

const sum = (a, b, c) => {
  return a + b + c;
};

console.log(sum(1, 2, 3)); //6

// 柯里化之后的
const currySum = (a) => {
  return (b) => {
    return (c) => {
      return a + b + c;
    };
  };
};

console.log(currySum(1)(2)(3)); //6

柯里化的作用

降低通用性,提高适用性

写一个通用的Reg校验函数

const useRegCheck = (reg, str) => {
  return reg.test(str);
};

// 校验电话号码
const checkPhone1 = useRegCheck(/^1[34578]\d{9}$/, "13888888888");
const checkPhone2 = useRegCheck(/^1[34578]\d{9}$/, "13412345678");

// 校验邮箱
const checkEmail1 = useRegCheck(
  /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
  "1239asd@gmail.com"
);
const checkEmail2 = useRegCheck(
  /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/,
  "123asd@163.com"
);

这样做确实是没问题的,但是每次都要复制粘贴一遍正则,代码不够简洁。

使用函数柯里化,只用定义好校验规则传入第一个参数,生成一个适用某个校验的函数,每次校验只用传入校验内容即可。

const curryUseRegCheck = (reg) => {
  return (str) => {
    return reg.test(str);
  };
};

const checkPhone = curryUseRegCheck(/^1[34578]\d{9}$/);
const checkPhone1 = checkPhone("13888888888");
const checkPhone2 = checkPhone("13412345678");

const checkEmail = curryUseRegCheck(
  /^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$/
);

const checkEmail1 = checkEmail('123@163.com');
const checkEmail2 = checkEmail('12asd@gmail.com');

封装转换柯里化工具函数

const curry = (fn) => {
  return function curryFn(...args) {
    if (args.length >= fn.length) {
      return fn(...args);
    }
    return function (...args2) {
      return curryFn(...args.concat(args2));
    };
  };
};

验证一下

const sum = (a, b, c) => {
  return a + b + c;
};

const currySum = curry(sum);

console.log(currySum(1)(2)(3)); //6
console.log(currySum(1, 2)(3)); //6
console.log(currySum(1)(2, 3)); //6

项目中可以使用lodash提供的函数柯里化。lodash中的curry提供了占位符的功能,可以改变参数参入的顺序,使用lodash本体作为占位符,被占位的参数作为下一个函数的参数传入。

const { curry } = _;
const currySum = curry(sum);

console.log(currySum(1)(2)(3)); //6
console.log(currySum(1, 2)(3)); //6

// lodash 中的curry还提供了占位符的功能
const toArr = (a, b, c, d) => {
  return [a, b, c, d];
};

const curryToArr = curry(toArr);

console.log(curryToArr(1)(2)(3)(4)); // [1, 2, 3, 4]

console.log(curryToArr(1, _, 3)(2)(4)); // [1, 2, 3,4]