likes
comments
collection
share

灵活的柯里化(currying)和闭包的美妙结合--函数add

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

前言

那什么是柯里化呢?

  • 从函数式编程中借用来的一个概念,它是指将原来接受多个参数的函数转换为一系列使用单一参数的函数的技术。换句话说,柯里化是将一个多参数函数转换为一系列嵌套的单参数函数的过程。总的来说,柯里化是一种强大的编程范式,它改变了我们思考和构造函数的方式,使代码更加灵活和模块化。

正文

我们在构造函数add时,会通过传入两个形参,返回它们的和:

但是要注意,基于代码的优雅性和健全性有两个注意点

  • 判断传入的实参的类型
  • 判断传入的实参的个数是否和形参的个数相等
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));
console.log(add('a', 2));
console.log(add(2));

灵活的柯里化(currying)和闭包的美妙结合--函数add

那我们想要一个一个的传入实参,该怎么实现呢?

我们可以通过闭包的结合来实现这个需求,一次只接收一个参数:

function add2(a) {
    return function (b) {
        return a + b;
    }
}

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

思考一下,如果我传入的参数不定,又该如何实现呢?

函数收集参数

定义了一个函数curry(fn)

  • 使用es5,函数里有一个 arguments arguments[1] -> arguments[arguments.length - 1]
const curry = function(fn) {
    // 参数对象
    for (let i = 0; i < arguments.length; i++) {
        console.log(arguments[i]);
    }
}

function add3(a, b, c, d) {
    return a + b + c + d;
}

curry(add3, 1, 2);

灵活的柯里化(currying)和闭包的美妙结合--函数add

  • 使用es6让我们的代码运行简洁...argsrest运算符 curry(fn, ...args)
  • 问题是什么? 即使用了箭头函数 arrow function, 我又去使用了es5 里面的arguments 箭头函数里没有arguments,违反了es6的简洁 应该使用rest 运算符
const curry = (fn, ...args) => {
    console.log(args);
}
function add3(a, b, c, d) {
    return a + b + c + d;
}

curry(add3, 1, 2);

灵活的柯里化(currying)和闭包的美妙结合--函数add

实现的大概思路(柯里化的思想):

  • 定义一个函数curry用于慢慢的收集参数,直到收集到的实参的个数等于函数add定义的形参的个数,通过正则表达式 args.length >= fn.length ? fn(...args) : (..._args) => curry(fn, ...args, ..._args);来实现():

分析:

  • 首先判断 args.length >= fn.length:如果已经收集到的参数数量(args.length)大于等于原函数fn期望的参数数量(fn.length),这意味着我们已经有了足够的参数去直接调用fn
  • 当条件满足时,使用扩展运算符(...)将args数组展开,并将这些参数传递给fn函数,从而执行该函数并返回结果。
  • 当条件不满足时,也就是收集到的参数还不够调用原函数fn,则返回一个新的柯里化函数:_args是新函数接收的参数,也是一个数组,代表下一步传入的参数,这个新的柯里化函数继续收集参数(..._args),并将已有的参数(...args)与新收集的参数合并,再递归调用curry函数,直到参数足够调用原函数fn,直到收集到的实参的个数大于或者等于函数add定义的形参的个数时,把实参传入进行函数的执行。
const curry = (fn, ...args) => 
    args.length >= fn.length
    ? fn(...args)
    : (..._args) => curry(fn, ...args, ..._args);

// 原函数
// 柯里化,参数慢慢 收集
const add4 = (a, b, c, d) => {
    return a + b + c + d;
}

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

灵活的柯里化(currying)和闭包的美妙结合--函数add

结语

快去试试吧!

灵活的柯里化(currying)和闭包的美妙结合--函数add

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