《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);
    });
时间: 2024-08-05 07:06:21

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

《JavaScript设计模式与开发》笔记 6.高阶函数

1.函数作为参数传递 1.回调函数 2.Array.prototype.sort 2.函数作为返回值输出 1.判断数据的类型 3.高级函数的实现AOP 4.高阶函数的其他应用 1.currying 函数柯里化 2.uncurring 3.函数节流 4.分时函数 5.惰性加载函数 1.函数作为参数传递 1.回调函数 最经常用的或许就是异步Ajax了 var getUserInfo = function(userId,callback){ $.ajax("http://xxx.com/getUser

Python学习笔记——高阶函数

变量可以指向函数: >>> abs(-8) 8 >>> abs <built-in function abs>    可以看出abs(-8)是函数调用,而abs是函数本身 如果我们要获得函数调用结果,我们可以把结果赋值给变量: >>> x = abs(-8) >>> x 8 如果把函数本身赋值给变量: >>> f = abs >>> f <built-in function abs

python学习笔记——高阶函数map()

满足以下两点中任意一点,即为高阶函数: 1.函数接收一个或多个函数作为参数 2.函数返回一个函数 1 描述 用函数和可迭代对象中每一个元素作为参数,计算出新的迭代对象 map() 会根据提供的函数对指定序列做映射. 第一个参数 function 以参数序列中的每一个元素调用 function 函数,返回包含每次 function 函数返回值的新列表. 2 语法 map(function, sequence[, sequence, ...]) function:函数 sequence:一个或多个序

《javascript设计模式与开放实践》学习(三)函数的闭包1

假设也没有上有5个div节点,通过循环给每个div绑定onclick实现弹出对应的编号.代码如下: <div>1</div> <div>2</div> <div>3</div> <div>4</div> <div>5</div> <script> var nodes=document.getElementsByTagName('div'); for (var i=0,len=

《javascript设计模式与开放实践》学习(五)惰性单例模式

在JS中可以使用代理来实现单例模式.如创建唯一DIV的场景: var CreateDiv=function (html) { this.html=html; this.init(); } CreateDiv.prototype.init=function () { var div=document.createElement('div'); div.innerHTML=this.html; document.body.appendChild(div); } var ProxySingleCrea

《javascript设计模式与开放实践》学习(二)对象方法的借用

1.借用构造函数 var A=function (name) { this.name=name; } var B=function () { A.apply(this,arguments);//借用A的函数构造器 } B.prototype.getName=function () { return this.name; }; var b=new B('Seven'); console.log(b.getName());//输出Seven 2.arguments增删元素 arguments虽然有“

《javascript设计模式与开放实践》学习(一)Function.prototype.bind

使用Function.prototype.bind来包装func函数 1.简化版的bind Function.prototype.bind=function (context) { var self=this; //保存原函数 return function () { return self.apply(context,arguments); } }; var obj={name:'seven'}; var func=function(){ alert(this.name); }.bind(ob

《javascript设计模式与开放实践》学习(四)私有变量

为了避免全局变量被污染,可采用加命名空间和闭包封装方式进行私有化. 一.使用命名空间 将某个变量变成某个命名空间下私有变量 var MyApp={}; MyApp.namespace=function (name) { var parts=name.split('.'); var current=MyApp; for(var i in parts){ if(!current[parts[i]]){ current[parts[i]]={}; } current=current[parts[i]]

《javascript设计模式与开放实践》学习(一)javascript实现多态

还是以鸭子唱歌为例 1.prototype 给对象添加方法或属性 <script> var makeSound=function (animal) { animal.sound(); } var Duck=function () { } Duck.prototype.sound=function () { console.log("嘎嘎嘎"); } var Chichen=function () { } Chichen.prototype.sound=function ()