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

Posted SmarTom

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《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/getUserInfo?"+userId,function(data){
       callback(data); 
    });
}
getUserInfo(14157,function(data){
    alert(data.userName);
});

 

2.Array.prorotype.sort

var array = [1,2,4];
array.sort(function(a,b){
    return b-a;
});

console.log(array);

 


2.函数作为返回值输出

1.判断数据的类型

场景

var isString = function(obj){
    return Object.prototype.toString.call(obj) == ‘[object string]‘;
}
var isArray = function(obj){
    return Object.prototype.toString.call(obj) ==‘[object Array]‘;
}
var isNumber = function(obj){
    return Object.prototype.toString.call(obj) == ‘[Object Number]‘
};
以上代码可写成:
var isType = function(type){
    return function(obj){   //函数作为返回值进行返回
        return Object.prototype.toString.call(obj) === ‘[object ‘+type+‘]‘;
    }
}
var isString = isType(‘String‘);
var isArray = isType(‘Array‘);
var isNumber = isType(‘Number‘);
console.log(isString([1,2,3,4]));
3.高级函数的实现AOP

Function.prototype.before=function(beforefn){
    var _self = this;           //这里的this实际上是func的this
    return function(){
        //这个this是before 的this
        beforefn.apply(this,arguments);         //这个是函数
        return _self.apply(this,arguments);    //func函数
    }
}
Function.prototype.after=function(afterfn){
    var _self = this;           //这里的this实际上是func的this
    return function(){
        var ret = _self.apply(this,arguments);  //func函数  实际上func可以包含before函数函数
        //这个this是after 的this
        afterfn.apply(this,arguments);         //这个是函数
        return ret;
    }
}
var func = function(){
    console.log(‘2‘);
}
var asdf = func.before(function(){
    console.log(‘1‘);
}).after(function(){
    console.log(‘3‘);
});

asdf();

 

流程图 技术分享

3.高阶函数其他应用

1.函数柯里化 currying函数

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

var currying = function(fn){
    var args = [];
    return function(){
        if(arguments.length == 0){
            var Mynameisbalabala;
            return fn.apply(this,args); //不要被这个this迷惑,实际是将argus传递给cost进行计算
            //return fn.apply(Mynameisbalabala,args);
        }else{
            [].push.apply(args,arguments);
            return arguments.callee;    //返回该函数
        }
    }
};
var ASF2FASD = (function(){
    var money = 0;
    return function(){
        for(var i=0;i<arguments.length;i++){
            money +=arguments[i];
        }
        return money;
    }
})();
var ASDFA = currying(ASF2FASD);
console.log(ASDFA(100).toString());
/* ASDF(100) 返回 ==(return fn.apply(this,args))
function (){
        if(arguments.length == 0){
            var Mynameisbalaba;
            return fn.apply(this,args); //不要被这个this迷惑,实际是将argus传递给cost进行计算
            //return fn.apply(Mynameisbalaba,args);
        }else{
            [].push.apply(args,arguments);
            return arguments.callee;    //返回该函数
        }
    }
*/
ASDFA(100);//
ASDFA(100);//
ASDFA(300);//
console.log(ASDFA());   //600

 

2.uncurrying函数

javascript,当我们调用对象的某个方法时,其实不用关心该对象原本是否设计为拥有这个方法,这是动态类型语言的特点,也是常说的鸭子类型的意思。


我们常用call和apply可以把任意对向当做this传入某个方法,这样一来,方法中用到this的地方就不在局限与原来规定的对象,而是加以泛化并得到更广的适用性。那么有没有把泛化this的过程提取出来呢....

仔细看一下代码还是很简单的不注解了.....

Function.prototype.uncurrying = function(){
    var self = this;//此时是Array.prototype.push
    return function() {
        var obj = Array.prototype.shift.call(arguments);
        //obj是{
        //‘length‘:1,
        //‘0‘:1
        //}
        //arguments 对象的第一个元素被截取
        return self.apply(obj,arguments);
        //相当于 Array.prototype.push.apply(obj,2);
    }
}
var push = Array.prototype.push.uncurrying();
var obj = {
    "length":1,
    "0":1
}
push(obj,2);
console.log(obj);

 

除了这样方法下面代码也是uncurrying的另一个实现方式:【】

Function.prototype.uncurrying = function(){
    var self = this;
    return function(){
        // Function.prototype.call  { ‘0‘: 1, length: 1 }
        return Function.prototype.call.apply(self,arguments);       //self =>asdfasdfasdfasdf对象  这里的this的话应该是push
    }
}

var push = Array.prototype.push.uncurrying();
var asdfasdfasdfasdf = {
    "length":1,
    "0":1
}
push(asdfasdfasdfasdf,2);
console.log(asdfasdfasdfasdf);

 

3.函数节流

函数调用频率过高,非常消耗性能的情况下使用函数节流比如监视窗口浏览器大小,比如监视鼠标的移动效果

实现节流:

var throttle = function (fn,interval){
    var _self = fn, //保存需要执行的函数引用
        timer,      //定时器
        firstTime = true;   //是否是第一次执行调用
        
    return function(){
        var args =arguments,
        __me = this;  //要执行的函数
        if(firstTime){              //如果是第一次调用,不需要延迟执行
            _self.apply(__me,args);
            return firstTime = false;
        }
        if(timer){      //如果定时器还在,说明前一次延迟执行还没有完成
            return false;
        }
        timer = setTimeout(function(){
            clearTimeout(timer);
            timer = null;
            _self.apply(__me,args);
        },interval || 500);
    }
}


window.onresize = throttle(function(){
    console.log(‘1‘);
},1000);

 

4.分时函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
</body>
<script>
    var timeout = function(ary,fn,count){
        console.log(‘5‘);
        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(){
            console.log(‘1‘);
            t = setInterval(function(){
                if(ary.length === 0){
                    return clearInterval(t);
                }
                start();
            },1000);
        };
    };
    var ary = [];
    for(var i=1;i<=1000;i++){
        ary.push(i);
    };
    var renderFriendList = timeout(ary,function(n){
        var div = document.createElement("div");
        div.innerHTML = n;
        document.body.appendChild(div);
    },8);
    renderFriendList();
</script>
</html>

 

5.惰性加载函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="div1">点击我绑定事件</div>
</body>
<script>
    var addEvent = function(elem,type,handler){
        if(window.addEventListener){
            addEvent = function(elem,type,handler){
                elem.addEventListener(type,handler,false);
            }
        }else if(window.attachEvent){
            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‘);
    })
</script>
</html>

 

以上是关于《JavaScript设计模式与开发》笔记 6.高阶函数的主要内容,如果未能解决你的问题,请参考以下文章

javascript设计模式与开发实践阅读笔记(10)—— 组合模式

JavaScript设计模式与开发实践---读书笔记 策略模式

《JavaScript设计模式与开发》笔记 1.面向对象的JavaScript

《JavaScript设计模式与开发》笔记 4.闭包

JavaScript设计模式与开发实践---读书笔记 迭代器模式

《JavaScript设计模式与开发》笔记 5.关于正确写一个闭包