函数柯里化详解

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

举个🌰:

 

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

上面代码可以转换成:

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

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

function add(x,y,z) {
    return x+y+z
}

的返回结果一致。

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

function add(x,y,z) {
    return x+y+z
}

function curry(fn, args) {
    //fn.length:形参个数,num为固定值
    var num = fn.length;
    var args = args || [];
    return function() {
        //arr用于收集传入的参数
        var arr =[].slice.call(arguments);
        //将之前收集的参数加入arr
        [].push.apply(arr, args);
        //若参数小于num,递归调用继续收集参数
        if (arr.length < num) {
            return curry.call(this, fn, arr);
        }
        //参数达到num,则执行fn
        return fn.apply(this, arr);
    }
}

const _add = curry(add);

_add(1,2,3);//6
_add(1)(2,3);//6
_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是一个类数组,类数组,顾名思义,即很像数组,但不是数组。

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

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

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

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

let arr = [1,2,3];
let result = arr.slice();
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.

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

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

4.

return fn.apply(this, arr);

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

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值