记一题函数科里化题目

307 阅读1分钟

如何实现下面的科里化函数

/ 假设有一个 curry 函数可以做到柯里化
var addCurry = curry(add);
addCurry(1)(2) // 3

题目分析

通过curry处理后返回的函数addCurry,连续调用addCurry(1)(2)(3),只有在最后一次括号调用的时候才输出的结果。

  • 通过这个现象,我们分析下面几个问题
  1. 怎么样能实现addCurry(1)(2)(3)这样连续的括号调用呢?
    • 思考:每次括号调用完成后,我们是不是可以返回curry(add),直到最后一次才运行累加运算。
  2. 这时候问题来了,因为是连续调用,那怎么样才能知道当前这次调用的addCurry(val),是否是最后一次调用呢?
    • 通过获取传入addCurry的函数fn的fn.length,获取到fn的形参长度。这样就可以直到第几次调用可以累加结果了。
  3. 继续第二个问题,那之前输入的数据怎么样才能在最后一次拿到,然后进行累加运算呢?
    • 我们是不是可以通过闭包的形式保存每次调用传入的参数,留给最后一次累加。

代码实现以下

const curry = function(fn, args) {
    const length = fn.length; // 获取fn形参的长度
    let _args = args || []; // 用来保存每次addCurry调用传入的实参,既然要保存肯定要形成闭包
    
    return function() {
        for (let i = 0; i < arguments.length; i ++) {
            _args.push(arguments[i])
        }
        // 当前执行获取到所有参数的长度,小于length,说明还要继续传参,这时我们返回 addCurry(fn, _args),便于下一次的括号调用
        if (_args.length < length) {
            return curry(fn, _args)
        } else {
            return fn(..._args)
        }
    }
    
}

const add = function(a, b, c) {
    return a + b + c;
}

const addCurry = curry(add);
addCurry(1)(2)(3);
  • 记一次函数科里化简单实现的笔记