柯里化函数实现

Posted by CodingWithAlice on July 21, 2021

柯里化函数实现

柯里化是把 接受 多个参数 的函数 变换成 接受一个 单一参数 的函数,并且返回 接受余下的参数而且返回结果的新函数 的技术。

一、柯里化函数实现

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, args = []) {
    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 processCur.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");