函數柯里化~

今天接觸到了一個以前沒據說過的東東,感受很好玩~分享給你們~爲了完全的瞭解一下相關概念,特地拜讀了一下張鑫旭大神的相關文章連接以下~:數組

http://www.zhangxinxu.com/wor...

感謝大神分享,本文將截取大神分享的部分及加上本身的小小理解~
先發一波定義~(源自百度百科)瀏覽器

在計算機科學中,柯里化(Currying)是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,而且返回接受餘下的參數且返回結果的新函數的技術。這個技術由 Christopher Strachey 以邏輯學家 Haskell Curry 命名的,儘管它是 Moses Schnfinkel 和 Gottlob Frege 發明的。

大神用於函數柯里化用的比喻至關的形象很是有助於理解~
「柯里化」就像某些官員的把戲,官員要弄7個老婆,礙於國策(一夫一妻)以及年老弟衰,表面上就1個老婆,實際上剩下的6個暗地裏消化,代碼表示以下:app

var curring = function(fn){
    // fn 指官員消化老婆的手段
    var args = [].slice.call(arguments,1); // 截取arguments中的第一個生成一個數組,也就是當前語境下的明面上的合法老婆
    return function(){
        // 將已有的參數和新傳進來的參數合併爲一個數組,對應已有的合法老婆和新搞定的老婆
        var newArgs = args.concat([].slice.call(arguments));
        // 將全部的參數newArgs綁定給fn~ 
        return fn.apply(null,newArgs);
    }
}

// 下面爲官員如何搞定7個老婆作測試
// 得到合法老婆
var getWife = currying(function(){
    var allWife = [].slice.call(arguments);
    console.log(allWife.join(';'))
},"合法老婆");
// 得到其餘6個老婆
getWife("小老婆1","小老婆2","小老婆3","小老婆4","小老婆5","小老婆6");
// 換一批老婆 
getWife("大老婆","小老婆","俏老婆","刁蠻老婆","乖老婆","送上門老婆");
// 再換一批老婆
getWife("超越韋小寶的老婆");

效果是這樣的~
圖片描述wordpress

不管輸入多少個參數,都會打印輸出,且都會帶着第一個參數~
上文代碼fn.apply(null,newArgs)中的null本是應該制定fn中this的指向的對象,沒有因此就用null啦,算是一個小技巧~函數

理解理解以後再想一想,這個東西有什麼用啊~~
柯里化有三個常見的應用:測試

  • 參數複用(上文代碼中的合法老婆)
  • 提早返回

這裏舉個很實用的例子,兼容現代瀏覽器以及IE瀏覽器的事件添加方法:this

var addEvent = function(el, type, fn, capture) {
    if (window.addEventListener) {
        el.addEventListener(type, function(e) {
            fn.call(el, e);
        }, capture);
    } else if (window.attachEvent) {
        el.attachEvent("on" + type, function(e) {
            fn.call(el, e);
        });
    } 
};

上面的方法有什麼問題呢?很顯然,咱們每次使用addEvent爲元素添加事件的時候,(eg. IE6/IE7)都會走一遍if...else if ...,其實只要一次斷定就能夠了,怎麼作?–柯里化。改成下面這樣子的代碼:spa

var addEvent = (function(){
    if (window.addEventListener) {
        return function(el, sType, fn, capture) {
            el.addEventListener(sType, function(e) {
                fn.call(el, e);
            }, (capture));
        };
    } else if (window.attachEvent) {
        return function(el, sType, fn, capture) {
            el.attachEvent("on" + sType, function(e) {
                fn.call(el, e);
            });
        };
    }
})();

初始addEvent的執行其實只實現了部分的應用(只有一次的if...else if...斷定),而剩餘的參數應用都是其返回函數實現的,典型的柯里化。code

  • 第三個常見應用: 延遲計算
var curryWeight = function(fn) {
    var _weight = [];
    return function() {
        if (arguments.length === 0) {
            return fn.apply(null, _weight);
        } else {
            _weight = _weight.concat([].slice.call(arguments));
        }
    }
};
var weight = 0;
var addWeight = curryWeight(function() {
    var i=0; len = arguments.length;
    for (i; i<len; i+=1) {
        weight += arguments[i];
    }
});

addWeight(2.3);
addWeight(6.5);
addWeight(1.2);
addWeight(2.5);
addWeight();    //  這裏才計算

console.log(weight);    // 12.5

先傳入參數,直到調用的時候才執行計算~對象

今天的分享就先到這裏了~願與各位共勉~

相關文章
相關標籤/搜索