首页 > 代码库 > 《javascript设计模式与开放实践》学习(三)高阶函数的应用

《javascript设计模式与开放实践》学习(三)高阶函数的应用

一、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();

二、currying 函数柯里化

currying又称部分求值。过程中不进行求值进行数值的保持,在最后一步进行求值。

如:

 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个函数调用的时候把值保持进数组,在最后一步进行数组求和。

三、uncurring

一个对象借用领另一个对象的方法或属性

将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的方法也可以uncurring

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

 

四、函数节流

解决频繁调用问题

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

五、分时函数

防止一次性加载过多,进行分时调用。

 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();

六、惰性加载函数

第一次进入分支后重写函数,第二次不在进行分支判断

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

 

《javascript设计模式与开放实践》学习(三)高阶函数的应用