手写函数柯里化

222 阅读1分钟

什么是函数柯里化?

函数柯里化主要用于给函数分步传递参数,每次传递参数进行处理,并返回一个更具体的函数来接受剩下的参数,这中间可以嵌套多层,直至返回最后的结果。

实现思路

  1. 接收一个处理数据的函数。
  2. 定义一个数组用于接收所有的参数。
  3. 返回一个函数,如果返回的函数接收的参数的长度是0,则返回fn执行的结果,如果不是0,则将参数push进数组中,并返回函数。

面试回答版

// 柯里化函数
const curry = (func) => {
    return function curryFunc(...args) {
        // 实参 < 形参, 返回一个函数,并等待接受剩余参数
        if (args.length < func.length) {
            return function () {
                // 合并每次调用函数时传递的参数
                return curryFunc(...[...args, ...Array.from(arguments)]);
            };
        }
        // 当实参 >= 形参时,直接执行函数返回结果
        return func(...args);
    };
};

function test(n1, n2, n3) {
    return n1 + n2 + n3;
}

const result = curry(test);
console.log('sum', result(1)(2)(3)); // 6
console.log('sum', result(1, 2)(1)); // 4
console.log('sum', result(1)(2)(1)); // 4
console.log('sum', result(1, 2, 1)); // 4

代码实现一(需要额外调用)

// 手写函数柯里化
const curring = function(fn) {
    const args = [];
    return function result(...rest) {
        if (rest.length === 0) {
            return fn(...args)
        } else {
            args.push(...rest);
            return result;
        }
    }
}
const sum = (...arg) => {
    return arg.reduce((pre,cur) => {
        return pre + cur
    },0)
}

curring(sum)(1)(2,5)(3)()

代码实现二(不需要额外调用)

// 手写函数科里化
// foo(1)(2)(3)
const sum = (arg) => {
    return arg.reduce((pre,cur) => {
        return pre + cur;
    },0)
};

const foo = (...args1) => {
    const sum1 = sum(args1);
    const fn = (...args2) => {
        const sum2 = sum(args2);
        return foo(sum1 + sum2); 
    }
    fn.toString = () => {
        return sum1;
    }
    return fn;
}
// 这种方式只能使用== 不能使用===
foo(1)(2)(3) == 6

但是这种方式只能使用==,不能使用===

代码实现三:sumOf版

/**
 * 实现一个累加器
 * add(1,2)(3).sumOf()
 * add(1)(2,3).sumOf()
 * add(1)(2)(3).sumOf()
 * add(1,2,3).sumOf()
 */

function Add() {
    if (!Add.nums) {
        Add.nums = [];
    }
    Add.nums.push(...arguments);
    return Add;
}
Add.sumOf = () => {
    return Add.nums.reduce((a, b) => a + b);
}

console.log(Add(1,2)(3).sumOf());