成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

一道題看透函數(shù)柯里化

marser / 3421人閱讀

摘要:對于函數(shù)的柯里化應(yīng)該不陌生,簡單來說技術(shù)是一種通過把多個參數(shù)填充到函數(shù)體中,實現(xiàn)將函數(shù)轉(zhuǎn)換為一個新的經(jīng)過簡化的使之接受的參數(shù)更少函數(shù)的技術(shù)。

對于函數(shù)的柯里化(currying)應(yīng)該不陌生,簡單來說 Currying 技術(shù)是一種通過把多個參數(shù)填充到函數(shù)體中,實現(xiàn)將函數(shù)轉(zhuǎn)換為一個新的經(jīng)過簡化的(使之接受的參數(shù)更少)函數(shù)的技術(shù)。當(dāng)發(fā)現(xiàn)正在調(diào)用同一個函數(shù)時,并且傳遞的參數(shù)絕大多數(shù)都是相同的,那么用一個Curry化的函數(shù)是一個很好的選擇.

下面利用閉包實現(xiàn)一個curry化的加法函數(shù), 我們簡單理解一下 curry 化:

function add(x, y){
    if(x && y) return x + y;
    if(!x && !y) throw Error("Cannot calculate");
    return function(newx){
        return x + newx;
    };
}
add(3)(4); //7
add(3, 4); //7
var newAdd = add(5);
newAdd(8); //13
var add2000 = add(2000);
add2000(100); //2100

這樣做其實很類似 bind:

function add(a, b){
  console.log(a+b);
  return a + b;
}

add(3, 4);   //7
add.bind(null, 3)(4);   //7
var newAdd = add.bind(null, 5);
newAdd(8);   //13
var add2000 = add.bind(null, 2000);
add2000(100); //2100

同理也可以使用 call 和 apply, 因為他們可以實現(xiàn) bind 的功能:

Function.prototype.bind = function(context){
  var _this = this;
  var args = [].slice.call(arguments, 1);

  return function (){
    innerArgs = [].slice.call(arguments);
    if(innerArgs && innerArgs.length > 0)
      args.push.apply(args, innerArgs);
    return _this.apply(context, args);
  }
}
add(3, 4);   //7
add.bind(null, 3)(4);   //7
var newAdd = add.bind(null, 5);
newAdd(8);   //13
var add2000 = add.bind(null, 2000);
add2000(100); //2100

但是,如果看到了這個題:

實現(xiàn)一個函數(shù)sum,運算結(jié)果可以滿足如下預(yù)期結(jié)果:
sum(1,2,3);       //6
sum(2,3)(2);      //7
sum(1)(2)(3)(4);  //10
sum(2)(4,1)(2);   //9

還覺得簡單么?我們理一下思路。首先試想一下這個 sum 函數(shù)的結(jié)構(gòu):

function sum(){
  return function(){
    return function(){
      //...
    }
  }
}

這個函數(shù)返回的一定是個函數(shù),但貌似需要寫無限個,這個不合理,我們修改一下:

function sum(){
  function innerSum(){
    //...
    return innerSum();
  }
  return innerSum();
}

這樣一來每次調(diào)用就不需要定義無限個函數(shù)了。我們完善里面的代碼:

//sum(1,2,3);       //6
//sum(2,3)(2);      //7
//sum(1)(2)(3)(4);  //10
//sum(2)(4,1)(2);   //9
function sum(){
  var cur = [].slice.call(arguments).reduce(function(a,b){return a+b;},0);
  function innerSum(){
    var next = [].slice.call(arguments).reduce(function(a,b){return a+b;},0);
    cur += next;
    return innerSum;
  }
  return innerSum;
}

這樣 sum 函數(shù)的柯里化過程就完成了,但是這個函數(shù)的返回的總是一個函數(shù),這樣我們?nèi)绾屋敵鰯?shù)值呢?我們可以借助隱式類型轉(zhuǎn)換需要的 toString 函數(shù)實現(xiàn):

function sum(){
  var cur = [].slice.call(arguments).reduce(function(a,b){return a+b;},0);
  function innerSum(){
    var next = [].slice.call(arguments).reduce(function(a,b){return a+b;},0);
    cur += next;
    return innerSum;
  }
  innerSum.toString = function(){
    return cur;
  }
  return innerSum;
}
console.log(sum(1,2,3));       //6
console.log(sum(2,3)(2));      //7
console.log(sum(1)(2)(3)(4));  //10
console.log(sum(2)(4,1)(2));   //9

計算結(jié)果沒錯,我們還可以換作 valueOf 實現(xiàn):

function sum(){
  var cur = [].slice.call(arguments).reduce(function(a,b){return a+b;},0);
  function innerSum(){
    var next = [].slice.call(arguments).reduce(function(a,b){return a+b;},0);
    cur += next;
    return innerSum;
  }
  innerSum.valueOf = function(){
    return cur;
  }
  return innerSum;
}
console.log(sum(1,2,3));       //6
console.log(sum(2,3)(2));      //7
console.log(sum(1)(2)(3)(4));  //10
console.log(sum(2)(4,1)(2));   //9

其實,如果同時存在 toString 和 valueOf 系統(tǒng)會先調(diào)用 toString, 然后調(diào)用valueOf,返回值自然是 valueOf 的返回值。這個很基礎(chǔ),這里就不提了。

通用柯里化方法

通用的柯里化寫法其實比之前的 sum 函數(shù)要簡單許多

var currying = function(fn) {
  // 主要還是收集所有需要的參數(shù)到一個數(shù)組中,便于統(tǒng)一計算
  var args = [].slice.call(arguments, 1);
  return function(){
      var _args = args.concat([].slice.call(arguments));
      return fn.apply(null, _args);
  }
}

var sum = function(){
  var args = [].slice.call(arguments);
  return args.reduce(function(a, b) {
      return a + b;
  });
};

var sum10 = currying(sum, 10);
console.log(sum10(20, 10));  // 40
console.log(sum10(10, 5));   // 25

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/107628.html

相關(guān)文章

  • 一道面試談?wù)?em>函數(shù)柯里(Currying)

    摘要:忍者秘籍一書中,對于柯里化的定義如下在一個函數(shù)中首先填充幾個參數(shù)然后再返回一個新函數(shù)的技術(shù)稱為柯里化?;氐轿覀兊念}目本身,其實根據(jù)測試用例我們可以發(fā)現(xiàn),函數(shù)的要求就是接受單一函數(shù),例如但是與柯里化不同之處在于,柯里化返回的一個新函數(shù)。   歡迎大家再一次來到我的文章專欄:從面試題中我們能學(xué)到什么,各位同行小伙伴是否已經(jīng)開始了悠閑的春節(jié)假期呢?在這里提前祝大家雞年大吉吧~哈哈,之前有人說...

    cppprimer 評論0 收藏0
  • 一道面試認(rèn)識函數(shù)柯里

    摘要:函數(shù)柯里化在函數(shù)式編程中,函數(shù)是一等公民。函數(shù)柯里化的主要作用和特點就是參數(shù)復(fù)用提前返回和延遲執(zhí)行??赡茉趯嶋H應(yīng)用場景中,很少使用函數(shù)柯里化的解決方案,但是了解認(rèn)識函數(shù)柯里化對自身的提升還是有幫助的。 最近在整理面試資源的時候,發(fā)現(xiàn)一道有意思的題目,所以就記錄下來。 題目 如何實現(xiàn) multi(2)(3)(4)=24? 首先來分析下這道題,實現(xiàn)一個 multi 函數(shù)并依次傳入?yún)?shù)執(zhí)行,...

    13651657101 評論0 收藏0
  • 一道柯里面試

    摘要:這是一道朋友在群里發(fā)的一道題,我之前不是很懂柯里化,就自己試著寫了一下,不知道算不算柯里化,望指教下面是題目寫好之后一下代碼可以正常運行輸入正確我自己的代碼我用到了以下知識點擴(kuò)展運算符傳參和擴(kuò)展運算符相關(guān)的數(shù)組操作。 這是一道朋友在群里發(fā)的一道題,我之前不是很懂柯里化,就自己試著寫了一下,不知道算不算柯里化,望指教~ 下面是題目: function curry() { ...

    andycall 評論0 收藏0
  • 關(guān)于JavaScript函數(shù)柯里探索

    摘要:函數(shù)柯里化關(guān)于函數(shù)柯里化的問題最初是在忍者秘籍中講閉包的部分中看到的,相信很多同學(xué)見過這樣一道和柯里化有關(guān)的面試題實現(xiàn)一個函數(shù),使得如下斷言能夠能夠通過簡單說就是實現(xiàn)一個求值函數(shù),能夠?qū)⑺袇?shù)相加得出結(jié)果。方法返回一個表示該對象的字符串。 函數(shù)柯里化 ??關(guān)于函數(shù)柯里化的問題最初是在《JavaScript忍者秘籍》中講閉包的部分中看到的,相信很多同學(xué)見過這樣一道和柯里化有關(guān)的面試題:...

    vboy1010 評論0 收藏0
  • 「前端面試系列6」理解函數(shù)柯里

    摘要:原題如下寫一個方法,當(dāng)使用下面的語法調(diào)用時,能正常工作這道題要考察的,就是對函數(shù)柯里化的理解。當(dāng)參數(shù)只有一個的時候,進(jìn)行柯里化的處理。這其實就是函數(shù)柯里化的簡單應(yīng)用。 showImg(https://segmentfault.com/img/bVbopGm?w=620&h=350); 前言 這是前端面試題系列的第 6 篇,你可能錯過了前面的篇章,可以在這里找到: ES6 中箭頭函數(shù)的...

    liaorio 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<