JavaScript 中的函数柯里化
JavaScript 是一种多范式语言,允许你自由地混合和匹配面向对象、过程式和函数式范式。最近,函数式编程的趋势日益增长。函数式编程风格不仅尝试将函数作为参数传递(即回调),而且还会返回函数。函数式编程的这一特性为我们带来了许多新颖且实用的概念。其中之一就是柯里化 (Currying)。
在本文中,我们将了解什么是柯里化以及它如何帮助我们使代码更干净、更简单。
什么是柯里化?
在深入探讨柯里化之前,我们首先需要理解函数的元数。函数的元数本质上就是它需要的参数的数量。
考虑以下两个例子 -
function addTwo(a, b) {
return a+b;
}
function addThree(a, b, c) {
return a + b + c;
}
在这种情况下,函数的元数addTwo
为 2,函数的元数addThree
为 3。
函数柯里化意味着将一个 N 元数的函数转换为 N 个不同的 1 元数的函数。
用更简单的话来说,柯里化就是重构函数的过程,以便它只接受一个参数,然后返回另一个接受下一个参数的函数,依此类推。
为了让您了解它的工作原理,让我们创建几个函数 -
// Un-curried function
function add(x, y) {
return x + y;
}
// Curried function
function addCurried(x) {
return function(y) {
return x + y;
}
}
add(1, 2); // Returns 3
addCurried(1)(2); // Returns 3
注意两者之间的区别。第一个函数是一个简单的函数,它接受两个参数——a
和b
,并将它们相加。而第二个函数addCurried
只接受一个参数,即a
,并返回另一个接受该参数的函数b
。两者给出的结果相同。
当我们无法一次性向函数提供所有参数时,柯里化会很有帮助。
每个函数调用都可以保存到一个变量中,该变量将保存返回的函数引用,并在下一个参数可用时接收该引用。让我们再举一个例子来更好地理解这一点——
// Curried function
function greet(msg) {
return function (name) {
console.log(msg, name);
};
}
let english = greet("Hello,");
let spanish = greet("Hola,");
let german = greet("Geuten Tag,");
german("Dwight"); // Prints "Geuten Tag, Dwight"
spanish("Oscar"); // Prints "Hola, Oscar"
english("Michael"); // Prints "Hello, Michael"
english("Jim"); // Prints "Hello, Jim"
注意柯里化是如何帮助我们避免反复传递同一个变量的。在本例中,变量msg
,当使用 调用时会打印“Hello” english
。这是一个很好的策略,可以避免频繁调用具有相同参数的函数。
ES6 模式
柯里化是函数式编程的一部分,这种柯里化函数也可以使用 ES6 中的箭头函数语法轻松编写,以获得更干净、更优雅的代码,如下所示:
const addCurried = x => y => x + y;
addCurried(1)(2); // Returns 3
部分应用函数
当我们谈论柯里化时,必然会提到偏应用函数的概念。柯里化和偏应用函数几乎是相同的概念,但有一个显著的区别。
偏函数应用是指一个函数返回另一个函数,但每个返回的函数可以接受多个参数。在柯里化中,返回函数只能接受一个参数。
让我们举一个简单的例子来说明这种差异-
// Curried function
function addCurried(x) {
return function (y) {
return function (z) {
return x + y + z;
};
};
}
// Partial Application function
function addPartial(x) {
return function (y, z) {
return x + y + z;
};
}
addCurried(1)(2)(3); // Returns 6
addPartial(1)(2, 3); // Returns 6
这两个概念的实现完全取决于用例和当时参数的可用性。但它们确实能帮助我们编写更简洁、更优雅的代码。
总结
在 JavaScript 函数式编程中,柯里化是一个非常有用的概念。正如我们所见,使用柯里化,我们可以让函数的功能更加明确,从而避免代码中潜在的重复,最终简化代码。
如果你喜欢这篇文章,欢迎在Twitter 上关注我 @afraz_momin。
我计划在未来几天撰写一些关于 JavaScript 的类似文章!