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

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

相关推荐
人工智能训练4 小时前
【极速部署】Ubuntu24.04+CUDA13.0 玩转 VLLM 0.15.0:预编译 Wheel 包 GPU 版安装全攻略
运维·前端·人工智能·python·ai编程·cuda·vllm
会跑的葫芦怪5 小时前
若依Vue 项目多子路径配置
前端·javascript·vue.js
xiaoqi9225 小时前
React Native鸿蒙跨平台如何进行狗狗领养中心,实现基于唯一标识的事件透传方式是移动端列表开发的通用规范
javascript·react native·react.js·ecmascript·harmonyos
jin1233226 小时前
React Native鸿蒙跨平台剧本杀组队消息与快捷入口组件,包含消息列表展示、快捷入口管理、快捷操作触发和消息详情预览四大核心功能
javascript·react native·react.js·ecmascript·harmonyos
烬头88217 小时前
React Native鸿蒙跨平台实现二维码联系人APP(QRCodeContactApp)
javascript·react native·react.js·ecmascript·harmonyos
pas1367 小时前
40-mini-vue 实现三种联合类型
前端·javascript·vue.js
摇滚侠8 小时前
2 小时快速入门 ES6 基础视频教程
前端·ecmascript·es6
2601_949833398 小时前
flutter_for_openharmony口腔护理app实战+预约管理实现
android·javascript·flutter
珑墨8 小时前
【Turbo】使用介绍
前端
军军君019 小时前
Three.js基础功能学习十三:太阳系实例上
前端·javascript·vue.js·学习·3d·前端框架·three