• 函数柯里化详解


    柯里化(Currying)是一种函数转化方法,是高阶函数(接收函数作为参数的函数)的一 种,它将一个接收多参数的函数转化为接收部分参数的函数。柯里化后的函数只传 递部分参数来调用,并返回一个新的函数,去处理剩余的参数,是逐步传参的过程。

    举个🌰:

     

    1. function add(x,y) {
    2. return x+y;
    3. }
    4. add(2,3);//返回值是3

    上面代码可以转换成:

    1. function add(x) {
    2. return function(y) {
    3. return x+y;
    4. }
    5. }
    6. add(1)(2);//返回值是3

    一个常见的面试题,用柯里化的方式实现一个函数,使add(1,2,3);add(1)(2,3);add(1)(2)(3);返回的结果与

    1. function add(x,y,z) {
    2. return x+y+z
    3. }

    的返回结果一致。

    下面一段代码引入其他玩家写过的代码,原文地址:函数柯里化_前端纸飞机的博客-CSDN博客_函数柯里化

    1. function add(x,y,z) {
    2. return x+y+z
    3. }
    4. function curry(fn, args) {
    5. //fn.length:形参个数,num为固定值
    6. var num = fn.length;
    7. var args = args || [];
    8. return function() {
    9. //arr用于收集传入的参数
    10. var arr =[].slice.call(arguments);
    11. //将之前收集的参数加入arr
    12. [].push.apply(arr, args);
    13. //若参数小于num,递归调用继续收集参数
    14. if (arr.length < num) {
    15. return curry.call(this, fn, arr);
    16. }
    17. //参数达到num,则执行fn
    18. return fn.apply(this, arr);
    19. }
    20. }
    21. const _add = curry(add);
    22. _add(1,2,3);//6
    23. _add(1)(2,3);//6
    24. _add(1)(2)(3);//6

     代码解析:

    上面核心函数curry中频繁的使用了call和apply函数,下面逐条解析代码含义

    1.

    let arr =[].slice.call(arguments);

    arguments是curry函数return的function所接收的参数,如上例中_add(1,2,3)中的1,2,3就是arguments。arguments是一个类数组,类数组,顾名思义,即很像数组,但不是数组。

    1. function add(x,y){
    2. console.log(arguments);
    3. return x+y;
    4. }

     上述代码执行add(1,2);打印的arguments的值如下图:

     其本质是一个对象,所以通过arguments[0]可以取到第一个参数1,arguments[1]可以取到第二个参数2.

    slice是数组的一个方法,可以获取目标数组内指定元素,可以接收0-2个参数。不接收参数时,可以获取到整个目标数组。如:

    1. let arr = [1,2,3];
    2. let result = arr.slice();
    3. console.log(result);

     上述代码中result的结果为:[1,2,3]

    [].slice.call()相当于Array.prototype.call()。[].slice.call(arguments)即通过call方法改变this指向,使arguments可以使用数组中的slice方法,可以理解为arguments.slice(),即let arr =[].slice.call(arguments),arr的值其实是将arguments参数转化为一个数组;

    2.

    [].push.apply(arr, args);

    上述代码的用意是将args参数push到arr数组中,那么为什么没有直接使用arr.push(args)?因为在args定义的时候有这样一句:

    let args = args || [];

    也就是说,args可能是curry传进来的参数,如果没有传入参数,那么就初始化成一个数组,当args是数组的时候,arr.push(args),就是向arr中push进一个数组,那么arr就变成了二维数组了。但代码的本意是使用arr保存传进来的参数,因此不能直接push。

    [].push.apply(arr, args),通过apply的参数特性,将args数组中的元素push到arr当中,如args的值是[1,2,3],[].push.apply(arr, args)相当于arr.push(1,2,3)。

    3.

    1. if (arr.length < num) {
    2. return curry.call(this, fn, arr);
    3. }

    curry.call(this, fn, arr),相当于递归调用,再调用一遍自己(curry函数),同时传入两个参数,fn和arr。

    4.

    return fn.apply(this, arr);

    fn.apply(this, arr)即调用fn函数,arr做为参数。

     以上是对实现一个柯里化函数的分解式讲解。

  • 相关阅读:
    配置 4G 模块为WAN口上网
    【OpenVINO™】在C#中使用 OpenVINO™ 部署 YOLOv10 模型实现目标
    多实例数据库备份脚本 mysql
    5. 虚拟化特性介绍
    ESP8266/esp32接入阿里云物联网平台点灯控制类案例
    ELF:加载过程
    OpenMMLap之Hook机制详解
    docker安装apisix全教程包含windows和linux
    Python对于时间相关模块的学习记录(time,datetime等模块)
    Python基础之MySql数据库交互
  • 原文地址:https://blog.csdn.net/xiao1215fei/article/details/126015355