ホームページ >ウェブフロントエンド >jsチュートリアル >1 つの記事で JS でのカリー化をすばやく理解する
この記事では、JavaScript でのカリー化について簡単に理解できます。一定の参考価値があります。困っている友達は参考にしてください。すべての人に役立つことを願っています。
# カリー化は、複数パラメータ関数を単項 (単一パラメータ) 関数に変換します。 [関連する推奨事項: 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 関数がより柔軟に使用できるためです。カリー化は理論的には優れていますが、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]);
debuggerChrome Developer Tools にいくつかのステートメントを追加して確認しました。
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 =curried(greet) と入力して、夢中になり始めます。
originalFunction と
greet を確認します。 Default
initialParams は、指定していないため空の配列です。次のブレークポイントに移動して、ちょっと待ってください...それだけです。
はい!
curry(greet)3 つ以上のパラメータを必要とする新しい関数のみを返します。コンソールに
curriedGreet と入力して、私が話していることを確認してください。
sayHello = curriedGreet('Hello').
originalFunction と入力します。
initialParams 新しい関数を使用しているにもかかわらず、これら 2 つのパラメーターにアクセスできることに注目してください。これは、親関数から返された関数がその親関数のスコープを共有しているためです。
curry 最初に
originalFunction、
initialParams を与え、次に「子」関数を返します。これら 2 つの変数は、
おそらく子供が必要とするため、まだ破棄されていません。そうしないと、then 範囲がクリアされます。なぜなら、誰もあなたのことに言及しなくなったとき、その時があなたが本当に死ぬときだからです。
をチェックして、# であることを確認します。 ##['Hello']...配列?でも、
curriedGreet(['Hello']) ではなく、
curriedGreet('Hello') と言ったと思います。
正解:
'Hello'
curriedGreet を呼び出しましたが、
rest 構文 のおかげで、
になりました #'こんにちは'['こんにちは'].本当ですか? !
の作業を容易にするために、残りのような構文を使用して配列内の各パラメーターをキャプチャします。 次の
debugger
ステートメントに進みましょう。
您可能已经注意到第 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前端 】
以上が1 つの記事で JS でのカリー化をすばやく理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。