前言:函数柯里化属于一种代码设计模式,可以理解成将一个函数在参数传递上做出优化,使得函数的应用变得更加灵活。本文先讲述什么是柯里化以及柯里化有什么用途,最后封装一个将函数柯里化的函数。
一、什么是函数柯里化
函数柯里化就是把接受多个参数的函数变成可连续接收单个参数的函数。三个之和函数的柯里化例子如下:
const sum = (a, b, c) => a + b + c;
console.log(sum(1, 2, 3));
// curry
const sum1 = (a) => (b) => (c) => a + b + c;
console.log(sum1(1)(2)(3));
💥也可以实现类似sum(1,2)(3)
这种形式的柯里化,柯里化(https://en.wikipedia.org/wiki/Currying)实际上是一种计算机科学中的通用方法,在实际编程中可以有多种实现或是变化。
二、函数柯里化有什么用
函数柯里化在具体代码中只是一种代码设计模式,优化代码质量,具体好处有以下几点:
参数复用。如下类型校验的例子
const checkByRegExp = (regExp, str) => regExp.test(str);
// 校验手机号
console.log(checkByRegExp(/^1\d{10}$/, "12345678910"));
// 校验邮箱
console.log(checkByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/, "test@163.com"));
可以简易柯里化
const curryingCheckByRegExp = (regExp) => (str) => regExp.test(str);
// 校验手机
const checkPhone = curryingCheckByRegExp(/^1\d{10}$/);
// 校验邮箱
const checkEmail = curryingCheckByRegExp(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
console.log(checkPhone("15152525634"));
console.log(checkPhone("13456574566"));
console.log(checkEmail("fsds@163.com"));
console.log(checkEmail("fdsf@qq.com"));
核心的使用场景就是将多个按逻辑层划分的函数组装使用,这样代码逻辑层设置的更加合理,在很多SDK源码中经常见到(eg:https://github.com/ueberdosis/tiptap/tree/main/packages/core)
三、函数柯里化的封装
上述两个例子都各自实现一套函数柯里化的函数代码,也可以封装一个curry
函数来对传入的函数进行封装柯里化。具体可以根据传入的函数形参个数来进行设计。
function _curry(fn, len, ...args) {
return function (...params) {
const _args = [...args, ...params];
return _args.length >= len
? fn.apply(this, _args)
: _curry.call(this, fn, len, ..._args);
};
}
const curry = (fn, len = fn.length) => _curry.call(this, fn, len);
上述三数之和例子可以改写如下:
const result = curry(sum);
console.log(result(1)(2)(3));
上述校验逻辑代码可以改写如下:
const curryPhone = curry(checkByRegExp)(/^1\d{10}$/);
const curryEmail = curry(checkByRegExp)(/^(\w)+(\.\w+)*@(\w)+((\.\w+)+)$/);
console.log(curryPhone("12345678910"));
console.log(curryEmail("test@qq.com"));
评论区