理解JavaScript currying

345 阅读7分钟

Currying是一个来自lambda calculus的概念,但不要让它吓到你,它的实现非常简单。

Currying是一个函数,它一次接受一个参数,并返回一个期待下一个参数的新函数。它是一种函数的转换,将一个函数从可调用的f(a, b, c)转换为可调用的f(a)(b)(c)。

在这篇文章中,我们将探讨什么是Javascript中的currying,为什么以及在什么地方应该使用currying,以及如何通过代码实例实现它。

什么是JavaScript中的currying?

Currying简单地说,就是对有多个参数的函数进行评估,并将其分解为一连串有单个参数的函数。

换句话说,Currying是指一个函数--而不是一次性接受所有的参数--接受第一个参数并返回一个新的函数,后者接受第二个参数并返回一个新的函数,后者接受第三个参数,等等,直到所有参数都完成。

为什么我应该使用咖喱法?

有几个原因说明currying是理想的。

  • 夤缘是一种检查方法,可以确保你在进行之前得到你需要的一切
  • 它可以帮助你避免重复传递同一个变量
  • 它将你的函数分为多个小函数,这些小函数可以处理一个责任。这使你的函数变得纯粹,不容易出错和产生副作用。
  • 在函数式编程中,它被用来创建一个高阶函数
  • 这可能是个人偏好,但我喜欢它使我的代码可读。

咖喱的工作原理是什么?

Currying是一个接受多个参数的函数。它将把这个函数转化为一系列的函数,其中每个小函数都接受一个参数。

Noncurried version//
const add = (a, b, c)=>{
return a+ b + c
}
console.log(add(2, 3, 5)) // 10

Curried version//
const addCurry =(a) => {
return (b)=>{
return (c)=>{
return a+b+c
}
}
}
console.log(addCurry(2)(3)(5)) // 10

Javascript中的Currying在定义上可能有点难以理解,但随着我们的实现,它将变得清晰。

所以,让我们深入了解更多的代码例子。

例一。一个简单的、三参数的函数

首先,我将创建一个接受三个参数的简单函数。

const add =(a, b, c)=>{
return a+b+c
}
console.log(add(2, 3, 5)) // 10

输出这个函数后,结果是10

这里发生的事情是,这个函数是将我们所传递的所有数字参数相加。

现在,这第一个例子只是一个接受多个参数的简单函数。

我如何将一个现有的函数转换为诅咒版本?

例二。将一个现有的函数转换为一个诅咒函数

让我们试试这个第二个例子,看看如何实现咖喱函数。

在这个例子中,这个函数要接受一个参数并返回一系列的函数。

const addCurry =(a) => {
return (b)=>{
return (c)=>{
return a+b+c
}
}
}

这就是该函数的咖喱实现。如果我们输出这个,结果将是10

console.log(addCurry(2)(3)(5)) // 10

在第一个例子中,我们创建了一个函数addCurry ,它接受三个参数a,b, 和c, 将它们的总和a+b+c, (2)+(3)+(5),并将输出结果作为10

第二个例子显示了我们是如何实现同一个函数的,但是有一个咖喱版本,它接受一个参数a ,并返回一个接受另一个参数的函数b ,该函数返回一个接受另一个参数的函数c ,该函数返回它们的总和,这给我们带来了与例子一相同的输出:10

我们在这里所做的是一个嵌套的函数,所以这些函数中的每一个都需要一个参数,而这个参数又会返回另一个参数,并且这个函数在收到所有的参数之前不会完成。

例三。创建一个请求朋友的咖喱函数

在这个例子中,我们将创建一个简单的咖喱函数,一个用户向他的朋友John发送一个朋友请求。

const sendRequest(greet){
return function(name){
return function(message){
return `${greet} ${name}, ${message}`
}
}
}
sendRequest('Hello')('John')('Please can you add me to your Linkedin network?')

输出。

"Hello John, Please can you add me to your Linkedin network?"

我们创建了一个函数sendRequest ,它只需要一个参数,greet ,它返回人的名字和我们要发送给用户的信息。然后,当我们调用这个函数时,它就输出了信息。

基本咖喱技术与高级咖喱技术

基本的策反

const getPanCakeIngredients = (ingredient1) =>{
return (ingredient2) => {
return (ingredient3) => {
return ${ingredient1}, ${ingredient2}, ${ingredient3}; } } } getPanCakeIngredients('Egg')('flour')('milk');

这个代码例子是实现currying的基本方法。

在上面的例子中,我们创建了一个函数getPanCakeIngredients ,该函数将ingredient 1 作为一个参数,并返回一系列包含我们制作煎饼所需的其他成分的函数。

这个函数在收到所有参数之前并不完整,这意味着如果煎饼的成分不完整,这个函数就不会返回任何好的结果。

高级咖喱法

下面是一个高级咖喱的代码例子。

const curry =(fn) =>{
 return curried = (...args) => {
if (fn.length !== args.length){
return curried.bind(null, ...args)
}
return fn(...args);
};
}
const totalNum=(x,y,z) => {
return x+y+z 
} 
const curriedTotal = curry(totalNum);
console.log(curriedTotal(10) (20) (30));

在上面的例子中,我们创建了一个需要固定数量参数的函数。

它接收一个函数curry ,作为外层函数。这个函数是一个封装函数。它返回另一个名为curried 的函数,该函数接收一个带有扩散运算符的参数( ...args) ,它比较了函数长度fn length

函数长度意味着无论我们在这里传递多少参数,它都会反映在函数的长度属性中。

但是参数会每次都增加。如果我们需要的参数数量不相等,它将会返回curried 。如果我们调用bind,这将创建一个新的函数,我们将传递( ...args)

注意,bind会创建一个新的函数。

使用ES6的现代咖喱法

作为我的额外提示,这里有一个使用ES6箭头函数实现咖喱的现代方法。它可以帮助你写更少的代码。

const sendRequest = greet => name => message =>
`${greet} ${name}, ${message}`
sendRequest('Hello')('John')('Please can you add me to your Linkedin network?')

输出。

"Hello John, Please can you add me to your Linkedin network?"

Currying可以用来操作Javascript中的DOM

准备好将currying付诸行动了吗?这里有一个简单的CodePen例子,说明如何使用curry来操作DOM

诅咒DOM的例子

添加外部样式表/笔 任何在这里添加的URL都会按顺序添加,并在编辑器中的CSS之前。如果你链接到另一个笔,它将包括该笔的CSS。如果预处理器匹配,它将尝试在处理之前将它们结合起来。JavaScript预处理器Babel包括JJSX处理。

咖喱与部分应用

现在你知道Currying是如何工作的,那么Currying和部分应用之间有什么区别?这是程序员一直在问的一个问题。

我终于有了这个问题的答案。但在我用一些代码例子深入解释之前,我们最好先熟悉一下它们的定义。

  • Currying:一个接受多个参数的函数。它将把这个函数转化为一系列的函数,每一个小函数都接受一个参数,直到所有参数都完成为止
  • 部分应用:当一个函数被赋予的参数少于它所期望的参数时,它被部分应用,并返回一个期望剩余参数的新函数

知道了这些定义还不足以让我们理解它们的区别。你已经看到了咖喱的作用,但这是一个部分应用的例子。

const addPartial=(x,y,z) => {
return x+y+z 
}
var partialFunc= addPartial.bind(this,2,3);
partialFunc(5); //returns 10

我们在这里所做的并不是一个卷曲的版本,但是我们做了一个addPartial 函数的部分应用。我们创建了一个简单的函数,将一列数字相加并返回其输出。

注意,当一个函数传递的一些参数不完整时,它就被称为部分应用。

咖喱和部分应用其实没有什么不同,它们是相关的,但它们有不同的理论和应用。

部分应用将一个函数转换为另一个函数,但其算数较小。

结论

对于开发者来说,currying可能感觉很复杂。虽然它很难理解,但当你在你的JavaScript项目中实现它时,你会更好地学习它。

我已经在我的一些项目中实现了currying,并通过实践来学习。这些是我用currying做的一些事情。

  • 咖喱可以用来操作Javascript中的DOM
  • 它可以用来触发事件监听器
  • 当你想创建一个只接收单个参数的函数时,可以使用Currying。

谢谢你阅读这篇文章,如果你有任何意见,请随时留言。我很愿意向你学习。谢谢!

The postUnderstanding JavaScript curryingappeared first onLogRocket Blog.