函数柯里化——小心一点炫技

看到柯里化(Currying),我相信爱好篮球的程序员一定会想到斯蒂芬·库里(Stephen Curry),常常投出不讲理的三分,让对手和队友目瞪口呆。函数柯里化也要讲究"得分效率"哦,在使用它时,应该考虑可读性与维护性,不要一不小心多炫啦。

函数柯里化


一、概念

定义: 它是将多参数函数转化为一系列单参数函数的技术,以逻辑学家Haskell Curry名字命名。

核心思想:将一个接受多个参数的函数转化为一系列链式函数调用,每个函数接受原函数的一个参数,并返回一个新的函数,直到所有参数都被接收为止。

二、为什么能实现?

一等公民的函数: 在JavaScript中,函数可以像变量一样被赋值给变量,作为参数传递给其他函数,或者从函数中返回。这是实现柯里化的基础。

闭包: 闭包允许一个函数访问并操作其外部作用域中的变量。在柯里化中,每次返回的新函数都会形成一个闭包,保持对外部函数中变量的引用,以便在后续调用中继续使用。

不定参数列表: 在箭头函数中使用 ...args 可以捕获所有传入的参数作为一个数组,这使得函数可以接受任意数量的参数,非常适用于实现柯里化求和这样的功能。

三、arguments与rest参数

arguments:

  • 函数运行时参数管理对象 --> 类数组对象
  • Object.prototype.toString.call(arguments) ==[object Arguments]
  • 具有for .length的能力,但是forEach,join reduce等方法是没有的。
javascript 复制代码
function sum() {
    let total = 0;
    for (let i = 0; i < arguments.length; i++) {
        total += arguments[i];
    }
    return total;
}
console.log(sum(1, 2, 3, 4),Object.prototype.toString.call(arguments));

rest参数

  • 从ES6开始,JavaScript引入了rest参数语法,它允许你在一个函数中收集不定数量的参数到一个数组中。
  • rest参数必须是函数参数列表中的最后一个参数。

现代JavaScript倾向于使用rest参数而不是 arguments,因为它提供了更好的语义清晰度和更丰富的数组操作能力。

javascript 复制代码
function sum(...numbers) {
    return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // 输出:10

四、柯里化

  • add()函数实现一个简单的函数柯里化
javascript 复制代码
function add(x) {
    return function(y) {
        return x + y;
    };
}

const add5 = add(5); 
console.log(add5(3)); // 输出 8

add(5)的执行结果返回新函数add5后,add5在接受参数3,add5(3)的执行结果输出8。

在实际的应用中,它可以用于创建更加灵活和可重用的函数。例如,在一个需要多个参数的复杂函数中,可能在不同情况下只要设置某些参数,而其他的参数保持未确定的状态。通过柯里化,你可以创建一个函数家族,每个函数都针对特定场景进行了优化。

  • 更复杂的函数柯里化----接受任意参数并求和。
ini 复制代码
const curryAdd = (...args) => {
    let total = args.reduce((acc, val) => acc + val, 0);

    const foo = (...moreArgs) => {
        if (moreArgs.length > 0) {
            return curryAdd(...args, ...moreArgs);
        } else {
            return total;
        }
    };
    
    return foo;
};

const curriedAdd = curryAdd();
console.log(curriedAdd(1,2)(2,2)(3,4)(4,6)());

在这个更加复杂的柯里化中,curryAdd函数可以接受任意数量参数,计算合后返回内部函数foo,当foo被调用时,接受到更多的参数,它会递归调用curryAdd并将新的参数与已有参数合并,没有更多参数时,返回total。

注: reduce方法接受一个回调函数作为参数,这个函数接受两个参数,一个当前值,一个当前数组元素,这个回调函数会在数组的每个元素上调用一次。在接受一个初始值,这里为0。

相关推荐
web13093320398几秒前
前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案
前端
王小王和他的小伙伴3 分钟前
解决 vue3 中 echarts图表在el-dialog中显示问题
javascript·vue.js·echarts
学前端的小朱7 分钟前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
outstanding木槿12 分钟前
react+antd的Table组件编辑单元格
前端·javascript·react.js·前端框架
小k_不小1 小时前
C++面试八股文:指针与引用的区别
c++·面试
好名字08211 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
摇光931 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务
隐形喷火龙1 小时前
element ui--下拉根据拼音首字母过滤
前端·vue.js·ui
m0_748241121 小时前
Selenium之Web元素定位
前端·selenium·测试工具
风无雨1 小时前
react杂乱笔记(一)
前端·笔记·react.js