您现在的位置是:群英 > 开发技术 > web开发
JS的柯里化怎样使用,原理是什么
Admin发表于 2022-05-17 15:54:38649 次浏览
相信很多人对“JS的柯里化怎样使用,原理是什么”都不太了解,下面群英小编为你详细解释一下这个问题,希望对你有一定的帮助

柯里化将多参数函数转换为一元(单参数)函数。

柯里化函数一次接受多个参数。所以如果你有

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 行暂停

检查我们看到的两个参数,originalFunction并且greet默认initialParams为空数组,因为我们没有提供它。移动到下一个断点,哦等等……就是这样。 是的!curry(greet)只返回一个需要 3 个以上参数的新函数。在控制台中输入curriedGreet以查看我在说什么。

当你玩完这个之后,让我们变得更疯狂一点,然后做
sayHello = curriedGreet('Hello').

在第 4 行暂停

在继续之前,在控制台中输入originalFunction和。initialParams请注意,即使我们在一个全新的函数中,我们仍然可以访问这两个参数?这是因为从父函数返回的函数享有其父函数的作用域。

继承

在父函数传递之后,他们将参数留给孩子使用。有点像现实生活中的继承。

curry最初给出originalFunctioninitialParams然后返回一个“子”函数。这两个变量还没有被处理掉,因为也许那个孩子需要它们。如果他不这样做,那么这个范围就会被清理干净,因为当没有人提到你时,那就是你真正死去的时候。

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

回到第 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');

以上就是关于“JS的柯里化怎样使用,原理是什么”的相关知识,感谢各位的阅读,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注群英网络,小编每天都会为大家更新不同的知识。

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。

标签: js柯里化
相关信息推荐
2022-08-19 17:48:15 
摘要:python给我们提供了多个循环方法,比如while循环、for循环等,下面这篇文章主要给大家介绍了关于Python中最快的循环姿势,需要的朋友可以参考下
2022-12-24 11:04:58 
摘要:php数组里面能放中文。因为PHP是弱数据类型的编程语言,所以PHP中的数组可以存储任意多个、任意类型的数据,即数组元素的类型没有限制,可以是数字、布尔值、数组、字符串等;而字符串可分为纯英文字符串、纯中文字符串和中英混合字符串。
2022-07-20 17:52:48 
摘要:TCP的拆包/粘包也算是网络编程中一个比较基础的问题了,本文主要介绍了go语言处理TCP拆包/粘包,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
云活动
推荐内容
热门关键词
热门信息
群英网络助力开启安全的云计算之旅
立即注册,领取新人大礼包
  • 联系我们
  • 24小时售后:4006784567
  • 24小时TEL :0668-2555666
  • 售前咨询TEL:400-678-4567

  • 官方微信

    官方微信
Copyright  ©  QY  Network  Company  Ltd. All  Rights  Reserved. 2003-2019  群英网络  版权所有   茂名市群英网络有限公司
增值电信经营许可证 : B1.B2-20140078   粤ICP备09006778号
免费拨打  400-678-4567
免费拨打  400-678-4567 免费拨打 400-678-4567 或 0668-2555555
微信公众号
返回顶部
返回顶部 返回顶部