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

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

相关推荐
小满zs6 分钟前
Next.js第十四章(缓存策略)
前端
低保和光头哪个先来16 分钟前
CSS+JS实现单例老虎机切换图片动画
前端·javascript·css
坐公交也用券19 分钟前
适用于vue3+pnpm项目自动化类型检查及构建的Python脚本
开发语言·javascript·python·typescript·自动化
IT_陈寒23 分钟前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升了40%
前端·人工智能·后端
LYFlied26 分钟前
【每日算法】LeetCode 76. 最小覆盖子串
数据结构·算法·leetcode·面试·职场和发展
小小鸟00830 分钟前
Vue响应式原理
前端·javascript·vue.js
努力学算法的蒟蒻31 分钟前
day36(12.17)——leetcode面试经典150
算法·leetcode·面试
lee57633 分钟前
鄙人的 Vue 3.0 商业级开源甘特图已经发布到 npm
前端·vue.js·npm·开源·甘特图
前端老曹35 分钟前
vue3 三级路由无法缓存的终终终终终终极解决方案
前端·javascript·vue.js
零Suger36 分钟前
React Router v7数据模式使用指南
javascript·笔记·react.js