ホームページ  >  記事  >  ウェブフロントエンド  >  1 つの記事で JS でのカリー化をすばやく理解する

1 つの記事で JS でのカリー化をすばやく理解する

青灯夜游
青灯夜游転載
2022-02-25 11:04:151689ブラウズ

この記事では、JavaScript でのカリー化について簡単に理解できます。一定の参考価値があります。困っている友達は参考にしてください。すべての人に役立つことを願っています。

1 つの記事で JS でのカリー化をすばやく理解する

# カリー化は、複数パラメータ関数を単項 (単一パラメータ) 関数に変換します。 [関連する推奨事項: 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]);
  };
};

Start

greetcurry をコンソールに貼り付けます。次に、curriedGreet =curried(greet) と入力して、夢中になり始めます。

2 行目で一時停止します

1 つの記事で JS でのカリー化をすばやく理解する

表示される 2 つのパラメータ、

originalFunctiongreet を確認します。 DefaultinitialParams は、指定していないため空の配列です。次のブレークポイントに移動して、ちょっと待ってください...それだけです。 はい! curry(greet)3 つ以上のパラメータを必要とする新しい関数のみを返します。コンソールに curriedGreet と入力して、私が話していることを確認してください。

これで遊び終わったら、もう少し夢中になって、


sayHello = curriedGreet('Hello').

一時停止してみましょう。 4 行目

1 つの記事で JS でのカリー化をすばやく理解する

続行する前に、コンソールに

originalFunction と入力します。 initialParams 新しい関数を使用しているにもかかわらず、これら 2 つのパラメーターにアクセスできることに注目してください。これは、親関数から返された関数がその親関数のスコープを共有しているためです。

継承

親関数が渡された後、パラメータは子に渡されます。現実世界における相続のようなものです。

curry 最初に originalFunctioninitialParams を与え、次に「子」関数を返します。これら 2 つの変数は、おそらく子供が必要とするため、まだ破棄されていません。そうしないと、then 範囲がクリアされます。なぜなら、誰もあなたのことに言及しなくなったとき、その時があなたが本当に死ぬときだからです。

OK、4 行目に戻ります...

1 つの記事で JS でのカリー化をすばやく理解する

nextParams

をチェックして、# であることを確認します。 ##['Hello']...配列?でも、curriedGreet(['Hello']) ではなく、curriedGreet('Hello') と言ったと思います。 正解: 'Hello'

を使用して

curriedGreet を呼び出しましたが、rest 構文 のおかげで、 になりました #'こんにちは'['こんにちは'].本当ですか? !

curry は、1、10、または 10,000,000 個の引数を指定できる一般的な関数であるため、すべての引数を参照する方法が必要です。

curry

の作業を容易にするために、残りのような構文を使用して配列内の各パラメーターをキャプチャします。 次の debugger ステートメントに進みましょう。

现在是第 6 行,但请稍等。

您可能已经注意到第 12 行实际上在debugger第 6 行的语句之前运行。如果不是,请仔细查看。我们的程序在第 5 行定义了一个调用函数curriedFunction,在第 12 行使用它,然后我们debugger在第 6 行点击了该语句。curriedFunction调用的是什么?

[...initialParams, ...nextParams];

呸呸呸。查看params第 5 行,您会看到['Hello']. 两者initialParams和都是数组,所以我们使用方便的扩展运算符nextParams将它们展平并组合成一个数组。

这就是好事发生的地方。

1 つの記事で JS でのカリー化をすばやく理解する

第 7 行说“如果paramsoriginalFunction长度相同,请greet使用我们的参数调用,我们就完成了。” 这使我想起…

JavaScript 函数也有长度

这就是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本质上是一个无限循环的自调用,参数饥渴的函数,直到他们的客人满了才会休息。热情好客。

1 つの記事で JS でのカリー化をすばやく理解する

回到第 2 行

与以前相同initialParams的参数,除了['Hello']这次。再次跳过以退出循环。在控制台中输入我们的新变量,sayHello. 这是另一个函数,仍然期待更多参数,但我们正在变得更加温暖......

让我们把火调大sayHelloToJohn = sayHello('John')

我们又在第 4 行了,而且nextParams['John']。跳到第 6 行的下一个调试器并检查params:它是['Hello', 'John']!?

1 つの記事で JS でのカリー化をすばやく理解する

为什么?

因为请记住,第 12 行说“嘿curriedFunction,他'Hello'上次和‘John’这次都给了我。把他们两个都带进这个阵法[...initialParams, ...nextParams]。”

1 つの記事で JS でのカリー化をすばやく理解する

现在curriedFunction再次将length这些params与进行比较originalFunction,因为2 我们移动到第 10 行并<code>curry再次调用!当然,我们传递greet了我们的 2 个参数,['Hello', 'John']

1 つの記事で JS でのカリー化をすばやく理解する

我们已经很接近了,让我们完成这一切,并得到完整的问候!

sayHelloToJohnDoe = sayHelloToJohn('Doe')

我想我们知道接下来会发生什么。

1 つの記事で JS でのカリー化をすばやく理解する

11 つの記事で JS でのカリー化をすばやく理解する

11 つの記事で JS でのカリー化をすばやく理解する

结论

greet得到他的参数,curry停止循环,我们收到了我们的问候:Hello, John Doe.

多玩一些这个功能。尝试一次提供多个参数或不提供参数,随心所欲地疯狂。curry查看在返回预期输出之前必须递归多少次。

curriedGreet(&#39;Hello&#39;, &#39;John&#39;, &#39;Doe&#39;);
curriedGreet(&#39;Hello&#39;, &#39;John&#39;)(&#39;Doe&#39;);
curriedGreet()()(&#39;Hello&#39;)()(&#39;John&#39;)()()()()(&#39;Doe&#39;);

【相关视频教程推荐:web前端 】

以上が1 つの記事で JS でのカリー化をすばやく理解するの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事はjuejin.cnで複製されています。侵害がある場合は、admin@php.cn までご連絡ください。