发布于 2026-01-05 2 阅读
0

通过实际应用理解 JavaScript 柯里化

通过实际应用理解 JavaScript 柯里化

你是否在 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,即使在多次计算中它没有改变。
  • 不可重复使用:如果您想在多笔交易中对同一客户类型应用折扣,则每次都必须指定类型。
  • 可扩展性问题:增加客户类型或折扣规则会使功能复杂化,并增加维护难度。

现在让我们使用柯里化函数来构建这个应用程序:
📌 使用柯里化函数:
柯里化允许您为各种客户类型创建可重用的函数。您无需不断提供相同的参数,而是可以为每种客户类型配置折扣逻辑。

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/_codepalette_/understanding-javascript-currying-with-a-real-world-application-51n9