《javascript設計模式與開放實踐》學習(三)高階函數的應用

1、AOP(面向切面編程)編程

 Function.prototype.before=function (beforefn) {
        var _self=this;//保持原函數的引用
        return function () {//返回包含原函數和新函數的「代理」函數
            beforefn.apply(this,arguments);//執行新函數,修正this
            return _self.apply(this,arguments);//執行原函數
        }
    }

    Function.prototype.after=function (afterfn) {
        var _self=this;
        return function () {
            var ret=_self.apply(this,arguments);
            afterfn.apply(this,arguments);
            return ret;
        }
    }
    var func=function () {
        console.log(2);
    }
    func=func.before(function () {
        console.log(1);
    }).after(function () {
        console.log(3)
    });

    func();

2、currying 函數柯里化數組

currying又稱部分求值。過程當中不進行求值進行數值的保持,在最後一步進行求值。app

如:函數

 var curring=function (fn) {
        var args=[];
        return function () {
            if(arguments.length==0){
                return fn.apply(this,args);
            }else{
                [].push.apply(args,arguments);
                return arguments.callee //返回正被執行的 Function 對象
            }
        }
    }
    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=curring(cost);//轉換成curring函數
    cost(100);
    cost(200);
    cost(300);
    console.log(cost())

輸出結果600,在前3個函數調用的時候把值保持進數組,在最後一步進行數組求和。this

3、uncurringspa

一個對象借用領另外一個對象的方法或屬性prototype

將Array.prototype.push uncurring化代理

Function.prototype.uncurrying=function () {
        var self=this;
        return function () {
            var obj=Array.prototype.shift.call(arguments);//取出arguments第一個值,並將第一個值從arguments中移除
            return self.apply(obj,arguments);
        };
    };

    var push=Array.prototype.push.uncurrying();
    (function () {
        push(arguments,4);
        console.log(arguments);//輸出[1,2,3,4]
    })(1,2,3)

以此類推,其餘Array的方法也能夠uncurringcode

Function.prototype.uncurrying=function () {
        var self=this;
        return function () {
            var obj=Array.prototype.shift.call(arguments);//取出arguments第一個值,並將第一個值從arguments中移除
            return self.apply(obj,arguments);
        };
    };
    for(var i=0,fn,ary=['push','shift','forEach'];fn=ary[i++];){
        Array[fn]=Array.prototype[fn].uncurrying();
    };
    var obj={
        "length":3,
        "0":1,
        "1":2,
        "2":3
    };
    Array.push(obj,4);
    console.log(obj.length);//輸出4
    var fist=Array.shift(obj);
    console.log(fist);//輸出1
    console.log(obj);//輸出{0:2.1:3,2:4,length:3}

    Array.forEach(obj,function (i,n) {
        console.log(n);//分別輸出0,1,2
    })

 

4、函數節流對象

解決頻繁調用問題

var throttle=function (fn,interval) {
        var _self=fn,//保存須要被延遲執行的函數引用
                timer,//定時器
                fisrtTime=true;//是否第一次調用
        return function () {
            var args=arguments,
                    _me=this;
            if(fisrtTime){//若是是第一加載,不須要延時
                _self.apply(_me,args);
                return fisrtTime=false;
            }

            if(timer){//若是定時器還在,說明前一次延時執行尚未完成
                return false;
            }
            timer=setTimeout(function () {
                clearTimeout(timer);
                timer=null;
                _self.apply(_me,args);
            },interval||500);//||判斷interval是否已定,若是沒有給初始值500
        };
    };
    window.onresize=throttle(function () {
        console.log(1);
    },500);

5、分時函數

防止一次性加載過多,進行分時調用。

 var timeChunk=function (ary,fn,count) {
        var obj,t;
        var len=ary.length;
        var start=function () {
            for(var i=0;i<Math.min(count||1,ary.length);i++){
                var obj=ary.shift();
                fn(obj);
            }
        };
        return function () {
            t=setInterval(function () {
                if(ary.length===0){//若是所有節點都已經建立好
                    return clearInterval(t);
                }
                start();
            },200)//分批執行的時間間隔
        }
    }
    var ary=[];
    for(var i=1;i<=1000;i++){
        ary.push(i);//假設ary裝載了1000個好友
    }
    var renderFriendList=timeChunk(ary,function (n) {
        var div=document.createElement('div');
        div.innerHTML=n;
        document.body.appendChild(div);
    },8);
    renderFriendList();

6、惰性加載函數

第一次進入分支後重寫函數,第二次不在進行分支判斷

 var addEvent=function (elem,type,handler) {
        if(window.addEventListener){//非IE
            addEvent=function (elem,type,handler) {
                elem.addEventListener(type,handler,false);
            }
        }
        else if(window.attachEvent){//非W3C標準,只支持IE
            addEvent=function (elem,type,handler) {
                elem.attachEvent('on'+type,handler);
            }
        }
        addEvent(elem,type,handler);
    };
    var div=document.getElementById('div1');
    addEvent(div,'click',function () {
        alert(1);
    });
    addEvent(div,'click',function () {
        alert(2);
    });
相關文章
相關標籤/搜索