이 기사는 Javascript의 Currying에 대한 빠른 이해를 제공할 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
커링은 다중 매개변수 함수를 단항(단일 매개변수) 함수로 변환합니다. [관련 권장사항: javascript 학습 튜토리얼]
Curried 함수 여러 매개변수를 동시에 허용합니다. 따라서
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
기능이 더 유연하게 사용되기 때문입니다. 커링은 이론적으로는 훌륭하지만 JavaScript의 모든 매개변수에 대해 함수를 호출하는 것은 피곤할 수 있습니다. 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 honored curriedGreet('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]);
让我们一起重构和欣赏它。
我还在debugger
Chrome 开发人员工具中添加了一些语句来检查它。
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)
并开始疯狂。
检查我们看到的两个参数,originalFunction
并且greet
默认initialParams
Ramda의 curry(greet)
只返回一个需要 3 个以上参数的新函数。在控制台中输入curriedGreet
以查看我在说什么。
当你玩完这个之后,让我们变得更疯狂一点,然后做sayHello = curriedGreet('Hello')
.
在继续之前,在控制台中输入originalFunction
和。initialParams
请注意,即使我们在一个全新的函数中,我们仍然可以访问这两个参数?这是因为从父函数返回的函数享有其父函数的作用域。
在父函数传递之后,他们将参数留给孩子使用。有点像现实生活中的继承。
curry
最初给出originalFunction
,initialParams
然后返回一个“子”函数。这两个变量还没有被处理掉,因为也许那个孩子需要它们。如果他不这样做,那么这个范围就会被清理干净,因为当没有人提到你时,那就是你真正死去的时候。
检查nextParams
并看到它是['Hello']
……一个数组?但我以为我们说curriedGreet(‘Hello’)
,不是curriedGreet(['Hello'])
!
正确:我们调用curriedGreet
了 with 'Hello'
,但是多亏了rest 语法,我们变成 'Hello'
了['Hello']
.
curry
是一个通用函数,可以提供 1、10 或 10,000,000 个参数,因此它需要一种方法来引用所有参数。使用类似的 rest 语法捕获一个数组中的每个参数,使curry
' 的工作更容易。
让我们跳到下debugger
curry
기능을 사용하면 다음과 같이 currriedGreet
를 호출하세요.
[...initialParams, ...nextParams];🎜 한 번에 여러 매개변수를 제공하도록 선택할 수 있습니다. 이 구현은 코드를 작성할 때 더 유용합니다. 🎜🎜위에 표시된 것처럼 이 함수는 인수 없이 영원히 호출할 수 있으며 항상 나머지 인수가 필요한 함수를 반환합니다. 🎜
greet.length; // 3 iTakeOneParam = (a) => {}; iTakeTwoParams = (a, b) => {}; iTakeOneParam.length; // 1 iTakeTwoParams.length; // 2复制代码🎜리팩터링하고 함께 감상해 봅시다. 🎜🎜이를 확인하기 위해
디버거
Chrome 개발자 도구에도 몇 가지 명령문을 추가했습니다. 🎜curriedGreet('Hello', 'John', 'Doe'); curriedGreet('Hello', 'John')('Doe'); curriedGreet()()('Hello')()('John')()()()()('Doe');
greet
및 curry
를 콘솔에 붙여넣으세요. 그런 다음 currriedGreet = curry(greet)
로 가서 미쳐가기 시작하세요. 🎜originalFunction
및 greet
defaultinitialParams를 확인하세요. 는 우리가 제공하지 않았기 때문에 빈 배열입니다. 다음 중단점으로 이동하고 아 잠깐만요... 그게 다입니다.
예! curry(greet)
는 3개 이상의 인수를 사용하는 새 함수를 반환합니다. 제가 말하는 내용을 보려면 콘솔에 currriedGreet
를 입력하세요. 🎜🎜이 작업이 끝나면 좀 더 미친 듯이sayHello = curriedGreet('Hello')
를 해보세요.🎜originalFunction
을 입력하세요. initialParams
새로운 함수를 사용하고 있음에도 불구하고 여전히 이 두 매개변수에 액세스할 수 있다는 점에 주목하세요. 이는 상위 함수에서 반환된 함수가 상위 함수의 범위를 공유하기 때문입니다. 🎜curry
는 처음에 originalFunction
, initialParams
를 제공한 다음 "하위" 함수를 반환합니다. 이 두 변수는 제거하세요. 🎜그 아이에게 필요할지도 모르니까요. 그가 그렇지 않으면 그러면 범위가 지워집니다. 왜냐하면 아무도 당신을 언급하지 않으면 그때가 당신이 정말로 죽는 때이기 때문입니다. 🎜nextParams
를 확인하고 ['Hello']
인지 확인하세요. >...배열? 하지만 currriedGreet(['Hello'])
가 아니라 currriedGreet('Hello')
라고 말한 줄 알았어요! 🎜🎜정답: 'Hello'
로 currriedGreet
를 호출했지만 rest 구문 🎜, 우리는 됩니다 '안녕하세요' ['안녕하세요']
.🎜curry
는 1, 10 또는 10,000,000개의 매개변수를 제공할 수 있는 일반 함수이므로 모든 매개변수를 참조할 수 있는 방법이 필요합니다. curry
의 작업을 더 쉽게 만들기 위해 나머지 유사 구문을 사용하여 배열의 각 매개변수를 캡처합니다. 🎜🎜다음 디버거
문으로 넘어가겠습니다. 🎜您可能已经注意到第 12 行实际上在debugger
第 6 行的语句之前运行。如果不是,请仔细查看。我们的程序在第 5 行定义了一个调用函数curriedFunction
,在第 12 行使用它,然后我们debugger
在第 6 行点击了该语句。curriedFunction
调用的是什么?
[...initialParams, ...nextParams];
呸呸呸。查看params
第 5 行,您会看到['Hello']
. 两者initialParams
和都是数组,所以我们使用方便的扩展运算符nextParams
将它们展平并组合成一个数组。
这就是好事发生的地方。
第 7 行说“如果params
和originalFunction
长度相同,请greet
使用我们的参数调用,我们就完成了。” 这使我想起…
这就是curry
它的魔力!这就是它决定是否要求更多参数的方式。
在 JavaScript 中,函数的 .length
属性告诉你它需要多少个参数。
greet.length; // 3 iTakeOneParam = (a) => {}; iTakeTwoParams = (a, b) => {}; iTakeOneParam.length; // 1 iTakeTwoParams.length; // 2复制代码
如果我们提供的和预期的参数匹配,我们很好,只需将它们交给原始函数并完成工作!
但是在我们的例子中,参数和函数长度是不一样的。我们只提供了‘Hello’
,所以params.length
是 1,并且originalFunction.length
是 3 因为greet
需要 3 个参数:greeting, first, last
。
好吧,由于该if
语句的计算结果为false
,代码将跳到第 10 行并重新调用我们的主curry
函数。它重新接收greet
,这一次,'Hello'
并重新开始疯狂。
这就是递归,我的朋友们。
curry
本质上是一个无限循环的自调用,参数饥渴的函数,直到他们的客人满了才会休息。热情好客。
与以前相同initialParams
的参数,除了['Hello']
这次。再次跳过以退出循环。在控制台中输入我们的新变量,sayHello
. 这是另一个函数,仍然期待更多参数,但我们正在变得更加温暖......
让我们把火调大sayHelloToJohn = sayHello('John')
。
我们又在第 4 行了,而且nextParams
是['John']
。跳到第 6 行的下一个调试器并检查params
:它是['Hello', 'John']
!?
因为请记住,第 12 行说“嘿curriedFunction
,他'Hello'
上次和‘John’
这次都给了我。把他们两个都带进这个阵法[...initialParams, ...nextParams]
。”
现在curriedFunction
再次将length
这些params
与进行比较originalFunction
,因为2 我们移动到第 10 行并<code>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을 빠르게 이해하세요의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!