惰性函數(shù)和函數(shù)柯里化

惰性函數(shù)

惰性載入表示函數(shù)執(zhí)行的分支只會在函數(shù)第一次調(diào)用的時(shí)候執(zhí)行,在第一次調(diào)用過程中,該函數(shù)會被覆蓋為另一個(gè)按照合適方式執(zhí)行的函數(shù),這樣任何對原函數(shù)的調(diào)用就不用再經(jīng)過執(zhí)行的分支了。
例如:為了兼容各瀏覽器,對事件監(jiān)聽的支持:

function addEvent (type, element, fun) {
    if (element.addEventListener) {
        element.addEventListener(type, fun, false);
    }
    else if(element.attachEvent){
        element.attachEvent('on' + type, fun);
    }
    else{
        element['on' + type] = fun;
    }
}

上面是注冊函數(shù)緝拿提供的個(gè)瀏覽器兼容函數(shù)。由于各瀏覽器之間的差異,不得不在用的時(shí)候做能力檢測。顯然,單從功能上講,已經(jīng)做到了兼容各瀏覽器。但是每次監(jiān)聽,都會做一次能力檢測,這就沒必要了,真正的應(yīng)用中,這顯然是多余的,對同一個(gè)應(yīng)用環(huán)境中,只需做一次檢測即可。
于是做如下改變:

 <!DOCTYPE html>
<html>
<head>
    <title></title>
    <style type="text/css">
      #app{
        width: 50px;
        height: 50px;
        background-color: skyblue;
      }
    </style>
</head>
<body>
  <div id="app"></div>
   <script type="text/javascript"> 
  
 function addEvent(element,type,fun) {
    if(element.addEventListener){
        addEvent = function(element,type,fun){
            console.log('chrome addEvent');
            element.addEventListener(type,fun,false);
        }
    }else if(element.attachEvent){
        addEvent = function(element,type,fun){
            element.attachEvent('on'+type,fun);
        }
    }else{
        addEvent = function(element,type,fun){
            element['on'+type] = fun;
        }
    }
     return addEvent(element,type,fun);
  }

 var app = document.getElementById("app");
   addEvent(app,'click',function(){
    alert(1);
   })
 addEvent(app,'click',function(){
    alert(2);
   })
   </script>

</body>
</html>

可以看出,第一次調(diào)用addEvent會對瀏覽器做能力檢測,然后重寫了addEvent。下次函數(shù)被重寫,不會再做能力檢測了。
類似的經(jīng)典例子還有:XMLHttpRequest

function createXHR() {
      var xhr;
      if(typeof XMLHttpRequest != 'undefined') {
          xhr = new XMLHttpRequest();
        createXHR = function() {
             return new XMLHttpRequest();
         }
     }else {
        try {
            xhr = new ActiveXObject("Msxml2.XMLHTTP");
            createXHR = function() {
                 return new ActiveXObject("Msxml2.XMLHTTP");
             }
         }catch(e) {
            try {
                 xhr = new ActiveXObject("Microsoft.XMLHTTP");
                 createXHR = function() {
                     return new ActiveXObject("Microsoft.XMLHTTP"); 
                 }
            }catch(e) {
                 createXHR = function () {
                     return null;
                 }
            }
       }
     }
    return xhr 
 }

代碼中,我們讓函數(shù)在第一次運(yùn)行之后,則判斷除了瀏覽器的環(huán)境,就被重新賦值了。賦值后的函數(shù)是直接return對應(yīng)的方法。所以這個(gè)函數(shù)需要第二次調(diào)用的時(shí)候才真正的被調(diào)用。
正式因?yàn)樗诙握{(diào)用的餓時(shí)候,沒有去走第一次調(diào)用那樣復(fù)雜的判斷的路,才顯得“懶惰”。因此我們叫惰性函數(shù)。

惰性函數(shù)應(yīng)用場景

1、應(yīng)用頻繁,如果只用一次,是體現(xiàn)不出來它的優(yōu)點(diǎn)的,用的次數(shù)越多,越能體現(xiàn)這種模式的優(yōu)勢所在;
2、固定不變,一次判定,在固定的應(yīng)用環(huán)境中不會發(fā)生改變;

函數(shù)柯里化

函數(shù)柯里化又稱部分求值,一個(gè)柯里化的函數(shù)首先會接受一些參數(shù),接受了這些參數(shù)之后,該函數(shù)并不會立即求值,而是繼續(xù)返回另外一個(gè)函數(shù),剛才傳入的參數(shù)在函數(shù)形成的閉包中被保存起來。待到函數(shù)被真正需要求值的時(shí)候,之前傳入的所有參數(shù)都會被一次性用于求值。

 var currying = function(fn){
        var args = [];
        return function(){
           if(arguments.length === 0){
             return fn.apply(this,args);
          }else{
            [].push.apply(args,arguments);
            return arguments.callee;
          }
        }
     }
    var cost = (function(){
        var money = 0;
        return function(){
          for(var i = 0 ,l = arguments.length; i<l; i++){
            money += arguments[i];
          }
          return money;
        }
    })()
  var cost = currying(cost); // 轉(zhuǎn)化成 currying 函數(shù)
  cost(100)(200); // 未真正求值 
  cost(200); // 未真正求值 
  cost(300);   // 未真正求值
  console.log(cost());  // 求值并輸出:800

以上代碼中,完成了一個(gè)currying函數(shù)的編寫。當(dāng)調(diào)用cost()時(shí),如果明確地帶上了一些參數(shù),表示此時(shí)并不進(jìn)行真正的求值計(jì)算,而是把這些參數(shù)保存下來,此時(shí)讓cost函數(shù)返回另外一個(gè)函數(shù)。只有以不帶參數(shù)的而形式執(zhí)行cost()時(shí),才利用前面保存的所有參數(shù),真正開始進(jìn)行求值計(jì)算。

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

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

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