js 函数柯里化(Currying)

原文链接:https://blog.spiritling.cn/posts/c0f17b1f/

在计算机科学中,柯里化(Currying),又译为卡瑞化或加里化,是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

从一道面试题谈谈函数柯里化从一道面试题谈谈函数柯里化

题目:使用 js 实现 add(1)(2)(3)(4) 返回 10

函数柯里化要求多个参数转为单一参数,所以相当于

function add() {
    return Array.from(arguments);
}
// 调用:add(1, 2, 3, 4) => [1, 2, 3, 4]
// 转换为下面形式
function addCurrying() {
    // do something
}
// 调用:addCurrying(1)(2)(3)(4) => [1, 2, 3, 4]

闭包拿参数

闭包:定义在一个函数内部的函数,静态保存所有了父级作用域的内部函数。所以每次的值可以保存住,到了最后可以全部访问到

所以,我们先来一个闭包来拿取到所有参数

var add = function (value) {
    var result = [];
    result.push(value);
    // _add 函数就是一个闭包,拿取到父级作用域的值,因为_add函数已获取到父级数据,所以父级一直存在,没有释放
    var _add = function (value2) {
        result.push(value);
        return _add;
    };
    // 此方法调用返回数组
    _add.getResult = function () {
        return result;
    };
    return _add;
};

这样通过上面函数就可以实现基本的柯里化要求

执行:

// addCurrying(1)(2)(3)(4).getResult => [1, 2, 3, 4]
// addCurrying(1)(2)(3)(4)
// =>
/*
ƒ (value2) {
    result.push(value);
    return _add;
}
*/

重写内置函数返回结果

上面的代码虽然已经获取到所有的参数,但是返回结果并没有自动返回,而是需要调用函数才返回。

并且由于不知道参数长度,也就无法通过参数数组长度来及时返回结果。

那么有什么方法可以解决呢?🤔

当然有了,在 js 中函数是有原型链的,所以每个函数都继承了基本的一些方法。

当你定义一个函数后,你如果打印时只输入函数名,并不执行,则函数内部信息就被打印出来。

那么我们可以重写这个方法,来在结束后执行。

函数的 toString 方法可以打印函数体,所以我们改造下,让 toString 返回结果

//首先我们需要一个入口函数进行基本处理
var add = function (value) {
    //定义一个保存所有传入的参数的数组
    var result = [];
    // 将第一个传入的参数放置进去
    result.push(value);
    // 定义函数 _add 引用result变量,使其保持不被销毁掉
    var _add = function (subValue) {
        // 将参数push进入result中去
        result.push(subValue);
        // 返回函数 _add 进行下次一调用
        return _add;
    };
    // 将原生自带的toString 进行重写
    _add.toString = function () {
        return result;
    };
    // 返回 _add 函数进行下次调用
    return _add;
};

执行结果

  • add(1) => [1]
  • add(1)(2) => [1,2]
  • add(1)(2)(3) => [1,2,3]

执行流程图

结束

通过上面的研究,解决一个函数柯里化问题。

posted @ 2020-07-17 09:33  SpiritLing  阅读(307)  评论(0编辑  收藏  举报