美文网首页
惰性函数和函数柯里化

惰性函数和函数柯里化

作者: lwz4070 | 来源:发表于2018-08-08 09:35 被阅读0次
    惰性函数

    惰性载入表示函数执行的分支只会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支了。
    例如:为了兼容各浏览器,对事件监听的支持:

    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;
        }
    }
    

    上面是注册函数缉拿提供的个浏览器兼容函数。由于各浏览器之间的差异,不得不在用的时候做能力检测。显然,单从功能上讲,已经做到了兼容各浏览器。但是每次监听,都会做一次能力检测,这就没必要了,真正的应用中,这显然是多余的,对同一个应用环境中,只需做一次检测即可。
    于是做如下改变:

     <!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>
    

    可以看出,第一次调用addEvent会对浏览器做能力检测,然后重写了addEvent。下次函数被重写,不会再做能力检测了。
    类似的经典例子还有: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 
     }
    

    代码中,我们让函数在第一次运行之后,则判断除了浏览器的环境,就被重新赋值了。赋值后的函数是直接return对应的方法。所以这个函数需要第二次调用的时候才真正的被调用。
    正式因为它第二次调用的饿时候,没有去走第一次调用那样复杂的判断的路,才显得“懒惰”。因此我们叫惰性函数。

    惰性函数应用场景

    1、应用频繁,如果只用一次,是体现不出来它的优点的,用的次数越多,越能体现这种模式的优势所在;
    2、固定不变,一次判定,在固定的应用环境中不会发生改变;

    函数柯里化

    函数柯里化又称部分求值,一个柯里化的函数首先会接受一些参数,接受了这些参数之后,该函数并不会立即求值,而是继续返回另外一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。

     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); // 转化成 currying 函数
      cost(100)(200); // 未真正求值 
      cost(200); // 未真正求值 
      cost(300);   // 未真正求值
      console.log(cost());  // 求值并输出:800
    

    以上代码中,完成了一个currying函数的编写。当调用cost()时,如果明确地带上了一些参数,表示此时并不进行真正的求值计算,而是把这些参数保存下来,此时让cost函数返回另外一个函数。只有以不带参数的而形式执行cost()时,才利用前面保存的所有参数,真正开始进行求值计算。

    相关文章

      网友评论

          本文标题:惰性函数和函数柯里化

          本文链接:https://www.haomeiwen.com/subject/iauavftx.html