likes
comments
collection
share

柯里化思想结合闭包解题与es6的部分特性讲解

作者站长头像
站长
· 阅读数 69

柯里化(Currying)

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

简单来说,就是将一个多参数的函数拆分成一系列单参数函数的组合。

柯里化的优点

  1. 提高函数的灵活性和复用性:可以根据不同的需求逐步构建参数。
  2. 延迟执行:可以先准备好部分参数,在合适的时候再提供其他参数来执行函数。
  3. 参数定制:更方便地对函数的参数进行定制和组合。

柯里化思想的应用

  1. 函数组合:可以通过柯里化将多个简单函数逐步组合成更复杂的函数。
  2. 参数配置:方便对函数的参数进行灵活的配置和定制,适应不同场景需求。
  3. 延迟计算:先准备部分参数,在合适时机再完成计算。
  4. 创建特定功能的函数变体:基于柯里化可以快速生成具有特定参数设置的函数版本。
  5. 提高代码可读性和可维护性:使函数的调用和参数传递逻辑更加清晰直观。 以add函数为例:首先实现两数相加

正常来说,我们首先就是接收两个参数然后直接return和。但是这样存在一些问题,比如传入的类型可能不对导致程序崩溃、数据参数数量也不确定,导致程序健壮性弱

function add(a, b) {
    // 存在的问题 数据类型,数据参数数量
    if (arguments.length != 2) {
        console.log('参数错误');
        return;
    }

    if (typeof a != 'number' || typeof b != 'number') {
        console.log('类型错误');
        return;
    }

    return a + b;
}
console.log(add(1, 2));

因此我们加上了typeof做类型判断,但是这样还是存在参数不定的问题。

我们接下来的想法是调用一次函数,我们可以把这个值给保留下来,例如:

// add2 = add(2)
// add2(4)=6

这样就自然而然的使用到闭包的概念了。

function add() {
    let sum = 0;
    for (let i = 0; i < arguments.length; i++) {
        sum += arguments[i];
    }
    return function () {
        let newSum = 0;
        for (let j = 0; j < arguments.length; j++) {
            newSum += arguments[j];
        }
        return sum + newSum;
    }
}

add2 = add(2)
console.log(add2);
console.log(add2(4));

通过这种方式,我们第一次调用,如果只传入一个值,则会得到0+这个值,保留sum,通过闭包传递给子函数,第一次调用返回了一个函数,接下来我们可以继续调用,这就是一种柯里化的思想(慢慢收集、延迟执行、提高函数的灵活性以及复用性)

但是我们注意到,这样子写是不是有点违背es6给我们带来的新风向?我们想把代码写的越来越简洁

  • es6为我们带来了箭头函数
  • 但是箭头函数没有arguments关键字来获取参数,怎么办?
  • 箭头函数虽然没有arguments关键字,但是有... rest运算符
const curry = (fn, ...args) =>
    // console.log(args.length, fn.length);
    args.length >= fn.length ? fn(...args) : (..._args) => curry(fn, ...args, ..._args)
// 原函数
const add = (x, y, z, m) => x + y + z + m;

const curryAdd = curry(add, 1)(2)(3)(4);
console.log(curryAdd);

在这份代码中我们能看到,我们首先使用了一个原函数add,实现我们最初的想法(4数相加),因此这个可以作为原函数,另外,我们写了一个柯里化函数curry,通过三元运算符判断,传入的值是否为4个,如果满足四个,直接调用原函数做add操作,否则就递归调用curry继续收集参数。

注意点:

  • 箭头函数没有arguments关键字,可以使用rest运算符
  • 箭头函数的函数体如果只有一行代码,省略花括号的情况下,相等于也省去了return
  • 应用currying柯里化思想,逐步收集参数,提升程序的灵活性、复用性

最后

通过柯里化思想解题,将多参数函数转化为单参数函数组合。我们以add函数为例子,展现了从传统的实现到闭包与currying的结合,相信这种解题思想能为你在一些场景下带来帮助。

接下来我们又提到了es6的一些特性,箭头函数的简洁性,局限性,再通过rest运算符为柯里化带来一些便利,通过柯里化逐步收集参数,提升程序灵活性与复用性

转载自:https://juejin.cn/post/7379167443501482035
评论
请登录