JS中的柯里化Currying怎么用
JS中的柯里化Currying怎么用
这篇文章主要为大家展示了“JS中的柯里化Currying怎么用”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“JS中的柯里化Currying怎么用”这篇文章吧。
柯里化将多参数函数转换为一元(单参数)函数。
柯里化函数一次接受多个参数。所以如果你有
greet=(greeting,first,last)=>`${greeting},${first}${last}`;greet('Hello','Bruce','Wayne');//Hello,BruceWayne
可以写成这种形式
curriedGreet=curry(greet);curriedGreet('Hello')('Bruce')('Wayne');//Hello,BruceWayne
如何正确的使用?
正确的使用“柯里化”是因为某些curry
函数在使用上更加灵活。Currying 在理论上很棒,但是在 JavaScript 中为每个参数调用一个函数会很累。
Ramda 的 curry
函数可以让你curriedGreet
像这样调用:
//greetrequires3params:(greeting,first,last)//theseallreturnafunctionlookingfor(first,last)curriedGreet('Hello');curriedGreet('Hello')();curriedGreet()('Hello')()();//theseallreturnafunctionlookingfor(last)curriedGreet('Hello')('Bruce');curriedGreet('Hello','Bruce');curriedGreet('Hello')()('Bruce')();//thesereturnagreeting,sinceall3paramswerehonoredcurriedGreet('Hello')('Bruce')('Wayne');curriedGreet('Hello','Bruce','Wayne');curriedGreet('Hello','Bruce')()()('Wayne');
请注意,你可以选择一次性给出多个参数。此实现在编写代码时更有用。
如上所示,你可以在没有参数的情况下永远调用此函数,并且它将始终返回一个需要剩余参数的函数。
工作原理相同
constcurry=(f,arr=[])=>(...args)=>((a)=>(a.length===f.length?f(...a):curry(f,a)))([...arr,...args]);
让我们一起重构和欣赏它。
我还在debugger
Chrome 开发人员工具中添加了一些语句来检查它。
curry=(originalFunction,initialParams=[])=>{debugger;return(...nextParams)=>{debugger;constcurriedFunction=(params)=>{debugger;if(params.length===originalFunction.length){returnoriginalFunction(...params);}returncurry(originalFunction,params);};returncurriedFunction([...initialParams,...nextParams]);};};
开始
粘贴greet
并curry
进入您的控制台。然后进入curriedGreet = curry(greet)
并开始疯狂。
在第 2 行暂停
检查我们看到的两个参数,originalFunction
并且greet
默认initialParams
为空数组,因为我们没有提供它。移动到下一个断点,哦等等……就是这样。是的!curry(greet)
只返回一个需要 3 个以上参数的新函数。在控制台中输入curriedGreet
以查看我在说什么。
当你玩完这个之后,让我们变得更疯狂一点,然后做sayHello = curriedGreet('Hello')
.
在第 4 行暂停
在继续之前,在控制台中输入originalFunction
和。initialParams
请注意,即使我们在一个全新的函数中,我们仍然可以访问这两个参数?这是因为从父函数返回的函数享有其父函数的作用域。
继承
在父函数传递之后,他们将参数留给孩子使用。有点像现实生活中的继承。
curry
最初给出originalFunction
,initialParams
然后返回一个“子”函数。这两个变量还没有被处理掉,因为也许那个孩子需要它们。如果他不这样做,那么这个范围就会被清理干净,因为当没有人提到你时,那就是你真正死去的时候。
好的,回到第 4 行……
检查nextParams
并看到它是['Hello']
……一个数组?但我以为我们说curriedGreet(‘Hello’)
,不是curriedGreet(['Hello'])
!
正确:我们调用curriedGreet
了 with 'Hello'
,但是多亏了rest 语法,我们变成 'Hello'
了['Hello']
.
是吗?!
curry
是一个通用函数,可以提供 1、10 或 10,000,000 个参数,因此它需要一种方法来引用所有参数。使用类似的 rest 语法捕获一个数组中的每个参数,使curry
' 的工作更容易。
让我们跳到下debugger
一条语句。
现在是第 6 行,但请稍等。
您可能已经注意到第 12 行实际上在debugger
第 6 行的语句之前运行。如果不是,请仔细查看。我们的程序在第 5 行定义了一个调用函数curriedFunction
,在第 12 行使用它,然后我们debugger
在第 6 行点击了该语句。curriedFunction
调用的是什么?
[...initialParams,...nextParams];
呸呸呸。查看params
第 5 行,您会看到['Hello']
. 两者initialParams
和都是数组,所以我们使用方便的扩展运算符nextParams
将它们展平并组合成一个数组。
这就是好事发生的地方。
第 7 行说“如果params
和originalFunction
长度相同,请greet
使用我们的参数调用,我们就完成了。” 这使我想起…
JavaScript 函数也有长度
这就是curry
它的魔力!这就是它决定是否要求更多参数的方式。
在 JavaScript 中,函数的 .length
属性告诉你它需要多少个参数。
greet.length;//3iTakeOneParam=(a)=>{};iTakeTwoParams=(a,b)=>{};iTakeOneParam.length;//1iTakeTwoParams.length;//2复制代码
如果我们提供的和预期的参数匹配,我们很好,只需将它们交给原始函数并完成工作!
但是在我们的例子中,参数和函数长度是不一样的。我们只提供了‘Hello’
,所以params.length
是 1,并且originalFunction.length
是 3 因为greet
需要 3 个参数:greeting, first, last
。
那么接下来会发生什么?
好吧,由于该if
语句的计算结果为false
,代码将跳到第 10 行并重新调用我们的主curry
函数。它重新接收greet
,这一次,'Hello'
并重新开始疯狂。
这就是递归,我的朋友们。
curry
本质上是一个无限循环的自调用,参数饥渴的函数,直到他们的客人满了才会休息。热情好客。
回到第 2 行
与以前相同initialParams
的参数,除了['Hello']
这次。再次跳过以退出循环。在控制台中输入我们的新变量,sayHello
. 这是另一个函数,仍然期待更多参数,但我们正在变得更加温暖......
让我们把火调大sayHelloToJohn = sayHello('John')
。
我们又在第 4 行了,而且nextParams
是['John']
。跳到第 6 行的下一个调试器并检查params
:它是['Hello', 'John']
!?
为什么?
因为请记住,第 12 行说“嘿curriedFunction
,他'Hello'
上次和‘John’
这次都给了我。把他们两个都带进这个阵法[...initialParams, ...nextParams]
。”
现在curriedFunction
再次将length
这些params
与进行比较originalFunction
,因为2 < 3
我们移动到第 10 行并curry
再次调用!当然,我们传递greet
了我们的 2 个参数,['Hello', 'John']
我们已经很接近了,让我们完成这一切,并得到完整的问候!
sayHelloToJohnDoe = sayHelloToJohn('Doe')
我想我们知道接下来会发生什么。
结论
greet
得到他的参数,curry
停止循环,我们收到了我们的问候:Hello, John Doe
.
多玩一些这个功能。尝试一次提供多个参数或不提供参数,随心所欲地疯狂。curry
查看在返回预期输出之前必须递归多少次。
curriedGreet('Hello','John','Doe');curriedGreet('Hello','John')('Doe');curriedGreet()()('Hello')()('John')()()()()('Doe');
以上是“JS中的柯里化Currying怎么用”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注恰卡编程网行业资讯频道!
推荐阅读
-
JavaScript闭包用多会造成内存泄露吗
-
javascript中文乱码如何解决
-
PHP学习第十五天——JavaScript入门DOM对象:二
-
Node.js基本内容和知识点
简单的说node.js就是运行在服务端的JavaScript,起初段定位是后端开发语言,由于技术的不够成熟,一般小型项目...
-
PHP与Node.js:一个史诗般开发者的分享
-
JavaScript 中 find() 和 filter() 方法的区别
JavaScript在ES6上有很多数组方法,每种方法都有独特的用途和好处。在开发应用程序时,大多使用数组方法来获...
-
js怎么跟php结合使用
-
简单说说Node.js和JavaScript
Node.js是一个开源和跨平台的JavaScript运行时环境,在浏览器之外运行V8JavaScript引擎(...
-
前端开发工程师专业技能简历范文
-
JavaScript怎么实现淘宝网图片的局部放大功能