《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);
    });
原文地址:https://www.cnblogs.com/GallopingSnail/p/5879120.html