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

看到柯里化(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。

相关推荐
ZC跨境爬虫5 小时前
跟着 MDN 学 HTML day_9:(信件语义标记)
前端·css·笔记·ui·html
前端老石人6 小时前
HTML 字符引用完全指南
开发语言·前端·html
matlab_xiaowang6 小时前
Redux 入门:JavaScript 可预测状态管理库
开发语言·javascript·其他·ecmascript
幼儿园技术家6 小时前
前端如何设计权限系统(RBAC / ABAC)?
前端
前端摸鱼匠8 小时前
Vue 3 的v-bind合并行为:讲解v-bind与普通属性合并的规则
前端·javascript·vue.js·前端框架·ecmascript
REDcker8 小时前
浏览器端Web程序性能分析与优化实战 DevTools指标与工程清单
开发语言·前端·javascript·vue·ecmascript·php·js
donecoding9 小时前
一个 sudo 引发的血案:npm 全局包权限错乱彻底修复
前端·node.js·前端工程化
风骏时光牛马9 小时前
Raku正则匹配与数据批量处理实操案例
前端
nbwenren10 小时前
2026实测:Gemini 3 镜像站视觉能力实践——拍照原型图,一键生成 HTML+CSS 代码
前端·css·html
Lee川10 小时前
Prisma 实战指南:像搭积木一样设计古诗词数据库
前端·数据库·后端