通过实际应用程序理解 JavaScript Currying

2025-05-28

通过实际应用程序理解 JavaScript Currying

您是否在 JavaScript 中见过“柯里化”这个词,并好奇它的含义?在本篇博文中,我们将探讨柯里化的概念,并通过一些简单的例子进行分解,并展示如何在实际场景中使用它,让您的代码更清晰、更灵活。

💡什么是柯里化?

柯里化是一种函数式编程方法,其中函数一次使​​用一个参数,而不是一次性使用所有参数。柯里化的函数会返回另一个函数,该函数接受下一个参数,直到所有参数都已提供。
简单来说,柯里化将一个包含多个参数的函数转换为一系列函数,每个函数只接受一个参数。

让我们使用现实生活中的类比和代码来理解:

🍔 做汉堡

想象一下在快餐店点一份汉堡。厨师会一层一层地制作你的汉堡:
第一层:面包(第一个参数)。
第二层:肉饼(第二个参数)。
第三层:配料(第三个参数)。

让我们使用常规函数柯里化函数为上述场景编写代码。📌
使用常规函数:
在常规函数中,所有成分都作为参数一次传递。

function makeBurger(bun, patty, topping) {
    return `Your burger has: ${bun} bun, ${patty} patty, and ${topping} topping.`;
}

const myBurger = makeBurger("Sesame", "Mix Veg", "Cheese");
console.log(myBurger); // Output: Your burger has: Sesame bun, Mix Veg patty, and Cheese topping.
Enter fullscreen mode Exit fullscreen mode

📌 使用柯里化函数:
在柯里化函数中,您一次传递一种成分。

function makeBurgerCurried(bun) {
    return function (patty) {
        return function (topping) {
            return `Your burger has: ${bun} bun, ${patty} patty, and ${topping} topping.`;
        };
    };
}

// Example usage
const chooseBun = makeBurgerCurried("Sesame");
const choosePatty = chooseBun("Mix Veg");
const myCurriedBurger = choosePatty("Cheese");

console.log(myCurriedBurger); // Output: Your burger has: Sesame bun, Mix Veg patty, and Cheese topping.
Enter fullscreen mode Exit fullscreen mode

✍️ 解释:
第一次调用: makeBurgerCurried("Sesame")接收"Sesame"并返回一个等待 patty 的新函数。

const chooseBun = makeBurgerCurried("Sesame");
console.log(chooseBun);
/* Output:
ƒ (patty) {
        return function (topping) {
            return `Your burger has: ${bun} bun, ${patty} patty, and ${topping} topping.`;
        };
} */
Enter fullscreen mode Exit fullscreen mode

第二次调用: chooseBun("Mix Veg")接收"Mix Veg"并返回另一个等待顶部的函数。

const choosePatty = chooseBun("Mix Veg");
console.log(choosePatty);
/* Output: 
ƒ (topping) {
    return `Your burger has: ${bun} bun, ${patty} patty, and ${topping} topping.`;
} */
Enter fullscreen mode Exit fullscreen mode

第三次调用: choosePatty("Cheese")接收"Cheese"并完成函数链,返回最终的汉堡描述。

const myCurriedBurger = choosePatty("Cheese");
console.log(myCurriedBurger); 
// Output: Your burger has: Sesame bun, Mix Veg patty, and Cheese topping.
Enter fullscreen mode Exit fullscreen mode

⭐ 简化的柯里化箭头函数

您可以使用箭头函数简化柯里化函数:

const  curriedArrowFunction = (bun) => (patty) => (topping) =>
    `Your burger has: ${bun} bun, ${patty} patty, and ${topping} topping`

const myArrowFunction = curriedArrowFunction("Sesame")("Mix Veg")("Cheese")
console.log(myArrowFunction); // Your burger has: Sesame bun, Mix Veg patty, and Cheese topping
Enter fullscreen mode Exit fullscreen mode

⁉️ 为什么要使用柯里化?

当你需要重用带有特定参数的函数时,柯里化尤其方便。它能够提升代码的重用性、可读性和模块化。

💻 实际应用:折扣计算器

假设你正在开发一个电子商务平台。折扣是根据客户类型计算的:

  • 老顾客可享受 10% 折扣。
  • 高级客户可享受 20% 的折扣。

现在,让我们先使用常规函数来构建它:
📌 使用常规函数:
使用常规函数进行折扣计算器可能会导致灵活性和代码复用性降低。您必须为每种类型的客户编写单独的函数,或者每次计算折扣时都传递所有参数。

function calculateDiscount(customerType, price) {
    if (customerType === "Regular") {
        return price * 0.9; // 10% discount
    } else if (customerType === "Premium") {
        return price * 0.8; // 20% discount
    }
}

console.log(calculateDiscount("Regular", 100)); // Output: 90
console.log(calculateDiscount("Premium", 100)); // Output: 80
Enter fullscreen mode Exit fullscreen mode

➖ 常规函数的局限性:

  • 重复逻辑:您必须每次传递 customerType,即使它在几次计算期间不会改变。
  • 不可重复使用:如果您想在多个交易中对一种客户类型应用折扣,则每次都必须指定类型。
  • 可扩展性问题:添加额外的客户类型或折扣规则会使功能变得复杂,并使其更难维护。

现在让我们使用 Curried 函数构建此应用程序:
📌 使用 Curried 函数:
Currying 允许您为各种客户类型创建可重用的函数。您可以为每种消费者类型配置折扣逻辑,而不必不断地提供相同的参数。

function createDiscountCalculator(discountRate) {
    return function (price) {
        return price * (1 - discountRate);
    };
}

// Create specific calculators for different customer types
const regularDiscount = createDiscountCalculator(0.1); // 10% discount
const premiumDiscount = createDiscountCalculator(0.2); // 20% discount

// Use them for calculations
console.log(regularDiscount(100)); // Output: 90
console.log(premiumDiscount(100)); // Output: 80
console.log(regularDiscount(200)); // Output: 180
Enter fullscreen mode Exit fullscreen mode

➕ 柯里化函数的优点:

  • 可重复使用性:一旦regularDiscount指定premiumDiscount,您将不需要在进一步的交易中再次指定折扣率。
  • 更简洁的代码:逻辑独立且专注。每个函数都只有一个职责:定义并应用折扣率。
  • 可扩展性:创建新的客户类型非常简单。例如:
const studentDiscount = createDiscountCalculator(0.15); // 15% discount
console.log(studentDiscount(100)); // 85
Enter fullscreen mode Exit fullscreen mode
  • 提高可读性:代码清晰地说明了其用途。regularDiscount函数指定了常客的折扣逻辑。

结论

柯里化一开始可能看起来很复杂,但正如我们所见,它是一个强大的概念,可以简化函数创建并使代码更清晰、更可重用。

现在您已经对此有了想法,请在下一个项目中尝试柯里化并见证奇迹的发生!

分享你的想法
你在项目中使用过柯里化吗?你遇到了哪些问题,又有哪些好处?请在下方评论区留言告诉我!

编码愉快!✨

文章来源:https://dev.to/thedevricha/understanding-javascript-currying-with-a-real-world-application-51n9
PREV
当您没有动力时,可以使用一些技巧让您再次编码👨‍💻。
NEXT
打破“高级工程师”的天花板 优化您的影响力,而不是输出 我的个人经历 为什么您不想成为首席工程师 总结