柯里化和自動柯里化函數(shù)實現(xiàn)

柯里化定義

維基百科定義

  • 是把接收多個參數(shù)的函數(shù),變成接受一個單一參數(shù)(最初函數(shù)的第一個參數(shù))的函數(shù),并且返回接受余下的參數(shù),而且返回結(jié)果的新函數(shù)的技術(shù)
  • 柯里化聲稱 “如果你固定某些參數(shù),你將得到接受余下參數(shù)的一個函數(shù)”
    簡單講就是將函數(shù)的多個參數(shù)返回不同的函數(shù)執(zhí)行,將多個參數(shù)進(jìn)行執(zhí)行拆解成單步驟執(zhí)行,一個函數(shù)執(zhí)行一個步驟
    更簡單的講只傳遞給函數(shù)一部分參數(shù)來調(diào)用它,讓它返回一個函數(shù)去處理剩余的參數(shù)
    舉個例子
function foo(a, b, c) {
  return a + b + c;
}
//柯里化處理之后的函數(shù)
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函數(shù)接收三個函數(shù),利用柯里化將三個參數(shù)返回相對應(yīng)的函數(shù)去執(zhí)行,每個函數(shù)執(zhí)行一個對參數(shù)的操作
可以將上面的柯里化處理函數(shù)簡化

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

但是在將上面的例子來看,進(jìn)行柯里化之后的函數(shù),步驟繁瑣,執(zhí)行效率也不高,但是為什么還要將函數(shù)進(jìn)行柯里化呢,這里就涉及到設(shè)計模式相關(guān)的,有一個重要的模式就是讓函數(shù)的職責(zé)單一

  • 當(dāng)我們在進(jìn)行函數(shù)式編程,每一個函數(shù)都盡可能只處理一類或者一個問題,而不是將所有的問題交給一個函數(shù)進(jìn)行處理
  • 那么我們是否就可以將每次傳入的參數(shù)在單一的函數(shù)中進(jìn)行處理,處理完后在下一個函數(shù)中再使用處理后的結(jié)果
function sum(a) {
  a = a + 2
  return function (b) {
     b = b * 2
    return function (c) {
       c = c ** 2
      return a + b + c;
    };
  };
}

柯里化還有一個重要的使用場景是對參數(shù)復(fù)用

function log(date, type, message) {
  console.log(
    `[${date.getHours()}:${date.getMinutes()}]:[${type}]:[${message}]`
  );
}
log(new Date(), 'debug', '參數(shù)錯誤');
log(new Date(), 'debug', 'not a function');
log(new Date(), 'debug', 'bad request');

以上面的例子來說,前兩個參數(shù)是重復(fù)的,每次都要寫同樣的代碼,唯一不同的是后面的message不同,如果有大量的日志需要重寫,會非常麻煩,這時就可以用柯里化將參數(shù)復(fù)用

const log = (date) => (type) => (message) => {
  console.log(
    `[${date.getHours()}:${date.getMinutes()}]:[${type}]:[${message}]`
  );
};
//時間重復(fù)
const datelog = log(new Date());
datelog('debug')('參數(shù)錯誤');
datelog('request')('bad request');
//時間和類型重復(fù)
const dataAndType = log(new Date())('debug');
dataAndType('參數(shù)錯誤');
dataAndType('not a function');
dataAndType('bad request');

通過柯里化可以將重復(fù)的參數(shù)進(jìn)行復(fù)用,減少了代碼的冗余

自動柯里化函數(shù)實現(xiàn)

上面的柯里化函數(shù)都是手動實現(xiàn)的,接下來用一個函數(shù)來自動實現(xiàn)柯里化的過程

function currying(fn) {
  //傳入需要處理的函數(shù)
  function curryied(...args) {
    //傳入處理函數(shù)的參數(shù)
    /**
     * 1.fn(10,20,30)
     * 2.fn(10)(20)(30)
     * 3.fn(10,20)(30)
     */
    //第一種情況
    //函數(shù)調(diào)用時參數(shù)全部使用
    if (args.length >= fn.length) {
      return fn.apply(this, args); //直接返回當(dāng)前調(diào)用的函數(shù),并且綁定當(dāng)前調(diào)用函數(shù)的this
    } else {
      //第二種情況
      //第二種情況和第三種情況是一樣的,這里是將第二種情況轉(zhuǎn)換為第三種情況,在轉(zhuǎn)換為第一種情況
      //遞歸調(diào)用
      //此時args是10,args2是20,
      //現(xiàn)在是需要將傳遞過來的參數(shù)進(jìn)行拼接,直到轉(zhuǎn)變成第一種情況
      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));

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容