首頁  >  文章  >  web前端  >  一文快速了解JS中的柯里化(Currying)

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

青灯夜游
青灯夜游轉載
2022-02-25 11:04:151825瀏覽

這篇文章帶大家快速了解一下Javascript中的柯里化(Currying),有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

一文快速了解JS中的柯里化(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 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 開發人員工具中加入了一些語句來檢查它。

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]);
  };
};

開始

貼上greetcurry進入您的控制台。然後進入curriedGreet = curry(greet)並開始瘋狂。

在第2 行暫停

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

#檢查我們看到的兩個參數,originalFunction並且greet預設initialParams為空數組,因為我們沒有提供它。移動到下一個斷點,哦等等……就是這樣。 是的! curry(greet)只傳回一個需要 3 個以上參數的新函數。在控制台中輸入curriedGreet以查看我在說什麼。

當你玩完這個之後,讓我們變得更瘋狂一點,然後做
sayHello = curriedGreet('Hello').

#在第4 行暫停

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

在繼續之前,在控制台中輸入originalFunction和。 initialParams請注意,即使我們在一個全新的函數中,我們仍然可以存取這兩個參數?這是因為從父函數傳回的函數享有其父函數的作用域。

繼承

在父函數傳遞之後,他們將參數留給孩子使用。有點像現實生活中的繼承。

curry最初給出originalFunctioninitialParams然後回傳一個「子」函數。這兩個變數還沒有被處理掉,因為也許那個孩子需要它們。如果他不這樣做,那麼這個範圍就會被清理乾淨,因為當沒有人提到你時,那就是你真正死去的時候。

好的,回到第4 行…

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

#檢查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将它们展平并组合成一个数组。

这就是好事发生的地方。

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

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

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

回到第 2 行

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

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

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

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

为什么?

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

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

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

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

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

sayHelloToJohnDoe = sayHelloToJohn('Doe')

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

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

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

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

结论

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前端 】

以上是一文快速了解JS中的柯里化(Currying)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:juejin.cn。如有侵權,請聯絡admin@php.cn刪除