函数式编程之柯里化
柯里化函数:部分求值。将多变量函数拆解为单变量的多个函数的依次调用。
- 原理:利用闭包创建一个不销毁的私有域,将要保存的内容作为外部函数的变量,并且返回一个函数,然后执行这个函数。
例子:
function add(x, y) {
return x + y;
}
function curryAdd(x) {
return function (y) {
return x + y;
}
}
console.log(add(1, 2)); //3
console.log(curryAdd(1)(2)); //3
源码实现:
function currying(fn, ...args) {
// length: fn函数的参数个数 -- 如 add有三个参数
let length = fn.length;
let allArgs = [...args];
const result = (...newArgs) => {
// 合并参数 -- 合并后续传进来的参数 --如下面例子中的a(2)
allArgs = [...allArgs, ...newArgs];
// 判断参数是否达到三个,如果达到就调用fn函数
if (allArgs.length === length) {
return fn(...allArgs);
} else {
// 没达到则返回
return result;
}
}
// 第一次执行的时候,对应下面currying(add,1)
return result;
}
// 测试
const add = (a, b, c) => a + b + c;
// const a = currying(add, 1)(2)(3);
const a = currying(add, 1)(2)(3);
console.log(a);
优点:
-
参数复用
-
正则校验
-
发送请求
function ajax(method, url, data) { console.log(method, url, data); } var ajaxCurry = Curry(ajax); var postAjax = ajaxCurry('POST'); postAjax('www.test1.com', 'name=hehe&code=111'); postAjax('www.test1.com', 'name=hehe&code=222'); var postTest1Ajax = postAjax('www.test.com'); postTest1Ajax('name=hehe&code=11'); postTest1Ajax('key');
-
-
延迟执行
- 我们 JS 中经常使用的 bind,实现机制就是 Currying
缺点:
- 存取
arguments
对象通常比存取命名参数要慢一些 - 一些老版本的浏览器在
arguments.length
的实现上是相当慢的 - 使用
fn.apply(...)
和apply.call(...)
通常比直接调用fn(...)
稍微慢 - 创建大量嵌套作用域和闭包函数会带来开销,无论是内存还是速度上