您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

一文快速了解JS中的柯里化(Currying)

2025/3/30 21:17:00发布42次查看
本篇文章带大家快速了解一下javascript中的柯里化(currying),有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。
柯里化将多参数函数转换为一元(单参数)函数。【相关推荐:javascript学习教程】
柯里化函数一次接受多个参数。所以如果你有
greet = (greeting, first, last) => `${greeting}, ${first} ${last}`;greet('hello', 'bruce', 'wayne'); // hello, bruce wayne
可以写成这种形式
curriedgreet = curry(greet);curriedgreet('hello')('bruce')('wayne'); // hello, bruce wayne
如何正确的使用?正确的使用“柯里化”是因为某些curry函数在使用上更加灵活。currying 在理论上很棒,但是在 javascript 中为每个参数调用一个函数会很累。
ramda 的 curry函数可以让你curriedgreet像这样调用:
// greet requires 3 params: (greeting, first, last)// these all return a function looking for (first, last)curriedgreet('hello');curriedgreet('hello')();curriedgreet()('hello')()();// these all return a function looking for (last)curriedgreet('hello')('bruce');curriedgreet('hello', 'bruce');curriedgreet('hello')()('bruce')();// these return a greeting, since all 3 params were honoredcurriedgreet('hello')('bruce')('wayne');curriedgreet('hello', 'bruce', 'wayne');curriedgreet('hello', 'bruce')()()('wayne');
请注意,你可以选择一次性给出多个参数。此实现在编写代码时更有用。
如上所示,你可以在没有参数的情况下永远调用此函数,并且它将始终返回一个需要剩余参数的函数。
工作原理相同const curry = (f, arr = []) => (...args) => ((a) => (a.length === f.length ? f(...a) : curry(f, a)))([...arr, ...args]);
让我们一起重构和欣赏它。
我还在debuggerchrome 开发人员工具中添加了一些语句来检查它。
curry = (originalfunction, initialparams = []) => { debugger; return (...nextparams) => { debugger; const curriedfunction = (params) => { debugger; if (params.length === originalfunction.length) { return originalfunction(...params); } return curry(originalfunction, params); }; return curriedfunction([...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');
【相关视频教程推荐:web前端 】
以上就是一文快速了解js中的柯里化(currying)的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product