柯里化&&反柯里化

298 阅读1分钟

函数柯里化

  • 把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数。
  • 优点:提高了代码的合理性,更重的它突出一种思想---降低适用范围,提高适用性。

例子一

function add(a, b, c, d, e, f) {
    return a + b + c + d + e + f;
}
let r = add(1, 2, 3, 4, 5, 6);

// 需要被curry的方法必须有固定长度参数
function curring(fn, arr = []) {
    let length = fn.length;
    return function(...args) {
        arr = [...arr, ...args];
        if (arr.length < length)
            return curring(fn, arr);
        else
            return fn(...arr);
    }
}

let r1 = curring(add)(1, 2)(3, 4)(5, 6);
console.log(r1);

例子二

function checkType(type, value) {
    return Object.prototype.toString.call(value) === `[object ${type}]`
}
let util = {};
let types = ['String', 'Number', 'Boolean', 'Null', 'Undefind'];
types.forEach(type => {
    util['is' + type] = curring(checkType)(type);
});

let r2 = util['isString']('123');
console.log(r2);

反柯里化-uncurrying

  • 作用就是扩大函数应用范围
let r1 = Array.prototype.join.apply([1, 2, 3], ['-']);
console.log(r1);
  • 弄个反柯里化函数让其动态生成新函数
let join = uncurrying(Array.prototype.join);
let r = join([1, 2, 3], '-');
console.log(r);
  • 简单写法
// 这种写法有个bug,保证值是原型的上的call方法 
// 比如刚好fn上有call方法 fn.call=()=>{};就会出问题
// function uncurrying(fn) {
//     return function(context, ...args) {
//         return fn.call(context, ...args);
//     }
// }
  • 升级成原型call方法写法
// function uncurrying(fn) {
//     return function(context, ...args) {
//         return Function.prototype.call.call(fn, context, ...args);
//     }
// }
  • 升级成原型apply方法写法
// function uncurrying(fn) {
//     return function(context, ...args) {
//         return Function.prototype.apply.call(fn, context, args);
//     }
// }

  • 升级成es6的 Reflect.apply
function uncurrying(fn) {
    return function(context, ...args) {
        return Reflect.apply(fn, context, args);
    }
}