柯里化函数实现
柯里化是把 接受 多个参数 的函数 变换成 接受一个 单一参数 的函数,并且返回 接受余下的参数而且返回结果的新函数 的技术。
// 更简洁、更现代化的方式
function curry(fun, ...args) {
if(args.length >= fun.length) {
return fun(...args)
} else {
return (...args2) => curry(fun, ...args, ...args2)
}
}
一、柯里化函数实现
1、可递归调用式:addCurry(1)(2)
let multiple = (a, b, c) => a * b * c;
// 调用方式1
let processMultiple = processCurry(multiple);
let res = processMultiple(2)(3)(4); //24
// 调用方式2
let processMultiple1 = processCurry(multiple, 3);
let res1 = processMultiple1(4)(5); // 60
var processCurry = function(fn) {
const args = [...arguments].slice(1);
const length = fn.length;
return function () {
const newArgs = [...args, ...arguments];
if (length - newArgs.length < 1) {
return fn.apply(this, newArgs);
} else {
return processCurry.call(this, fn, ...newArgs);
}
}
}
2、简单实现:addCurry(2)
let add = (a,b) => a + b;
var addCurry = curry(add, 1);
addCurry(2);
function curry(fn) {
const args = [...arguments].slice(1);
return function () {
return fn.apply(null, [...args, ...arguments]);
};
};
// 但是不支持 addCurry(1)(2) 形式的调用
二、逻辑解构
代码层面理解一下:一个 currying 的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值【延迟运行】,而是继续返回另外一个函数,刚才传入的参数在函数形成的 闭包 中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值
// 普通的add函数
function add(x, y) {return x + y}
add(1, 2) // 3
// 柯里化后 - 先用一个函数接收 x 然后返回一个函数去处理 y 参数 - 功能如下:
function curryingAdd(x) {
return function (y) {return x + y}
}
curryingAdd(1)(2) // 3
优点:
- 1、参数复用 - 固定某些参数后的函数封装
- 2、提前返回 - 可以先操作某些参数后 自执行 一次,后续调用就不用仿佛再计算
- 3、延迟计算 - 和ES6 的
bind
方法一样,只返回函数体,不执行
// 1、参数复用
// 多个不同域名下的请求
function ajax(type, url, data) {
var xhr = new XMLHttpRequest();
xhr.open(type, url, true);
xhr.send(data);
}
// 使用:虽然 ajax 这个函数非常通用,但在重复调用的时候 - 'POST'参数冗余
ajax('POST', 'www.test.com', "name=kevin")
ajax('POST', 'www.test2.com', "name=kevin")
ajax('POST', 'www.test3.com', "name=kevin")
// 利用 curry
var ajaxCurry = curry(ajax);
// 以 'POST' 类型请求数据
var post = ajaxCurry('POST');
post('www.test.com', "name=kevin");
post('www.test2.com', "name=kevin");
// 以 POST 类型请求来自于 www.test.com 的数据
var postFromTest = post('www.test.com');
postFromTest("name=kevin");
postFromTest("name=Alice");