js设计模式

柯里化和自动柯里化函数实现

2021-09-14  本文已影响0人  瓯海

柯里化定义

维基百科定义

function foo(a, b, c) {
  return a + b + c;
}
//柯里化处理之后的函数
function sum(a) {
  return function (b) {
    return function (c) {
      return a + b + c;
    };
  };
}
console.log(foo(10, 20, 30));
console.log(sum(10)(20)(30));

foo函数接收三个函数,利用柯里化将三个参数返回相对应的函数去执行,每个函数执行一个对参数的操作
可以将上面的柯里化处理函数简化

const sum = (a) => (b) => (c) => a + b + c;

但是在将上面的例子来看,进行柯里化之后的函数,步骤繁琐,执行效率也不高,但是为什么还要将函数进行柯里化呢,这里就涉及到设计模式相关的,有一个重要的模式就是让函数的职责单一

function sum(a) {
  a = a + 2
  return function (b) {
     b = b * 2
    return function (c) {
       c = c ** 2
      return a + b + c;
    };
  };
}

柯里化还有一个重要的使用场景是对参数复用

function log(date, type, message) {
  console.log(
    `[${date.getHours()}:${date.getMinutes()}]:[${type}]:[${message}]`
  );
}
log(new Date(), 'debug', '参数错误');
log(new Date(), 'debug', 'not a function');
log(new Date(), 'debug', 'bad request');

以上面的例子来说,前两个参数是重复的,每次都要写同样的代码,唯一不同的是后面的message不同,如果有大量的日志需要重写,会非常麻烦,这时就可以用柯里化将参数复用

const log = (date) => (type) => (message) => {
  console.log(
    `[${date.getHours()}:${date.getMinutes()}]:[${type}]:[${message}]`
  );
};
//时间重复
const datelog = log(new Date());
datelog('debug')('参数错误');
datelog('request')('bad request');
//时间和类型重复
const dataAndType = log(new Date())('debug');
dataAndType('参数错误');
dataAndType('not a function');
dataAndType('bad request');

通过柯里化可以将重复的参数进行复用,减少了代码的冗余

自动柯里化函数实现

上面的柯里化函数都是手动实现的,接下来用一个函数来自动实现柯里化的过程

function currying(fn) {
  //传入需要处理的函数
  function curryied(...args) {
    //传入处理函数的参数
    /**
     * 1.fn(10,20,30)
     * 2.fn(10)(20)(30)
     * 3.fn(10,20)(30)
     */
    //第一种情况
    //函数调用时参数全部使用
    if (args.length >= fn.length) {
      return fn.apply(this, args); //直接返回当前调用的函数,并且绑定当前调用函数的this
    } else {
      //第二种情况
      //第二种情况和第三种情况是一样的,这里是将第二种情况转换为第三种情况,在转换为第一种情况
      //递归调用
      //此时args是10,args2是20,
      //现在是需要将传递过来的参数进行拼接,直到转变成第一种情况
      function curryied2(...args2) {
        return curryied.apply(this, [...args, ...args2]);
      }
      return curryied2;
    }
  }
  return curryied;
}

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

var curryadd = currying(add);
console.log(curryadd);
console.log(curryadd(10)(20)(30));
console.log(curryadd(10, 20, 30));
console.log(curryadd(10, 20)(30));

上一篇 下一篇

猜你喜欢

热点阅读