高阶函数——基础+AOP+惰性加载函数

本文详细探讨了高阶函数的概念,包括函数作为参数传递和返回值输出的应用场景,如回调函数、排序函数、类型判断函数等。同时介绍了如何利用高阶函数实现AOP和惰性加载,提高代码的复用性和性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

高阶函数是指至少满足下列条件之一的函数:

  • 函数可以作为参数被传递
  • 函数可以作为返回值输出。

一、函数作为参数传递

  1. 回调函数

例:ajax异步请求中的回调函数

var getUser=function(userId,callback){
    &.ajax("http://xxx.com/getUser?"+userId,function(){
        if(typeof callback==='function'){
            callback(data);
        }
    })
};
getUser(0802,function(data){
    console.log(data.userName);
});
  • 当我们想在ajax请求返回之后做一些事情,但又不知道请求返回的确切时间时,最常见的方案就是把callback函数当作参数传入ajax请求的方法中,待请求完成之后执行callback函数

例:在页面创建100个节点,将节点均设置为隐藏

var appendDiv= function () {
    for(var i=0;i<100;i++){
        var div=document.getElementsByTagName("div");
        div.innerHTML=i;
        document.appendChild(div);
        div.style.display="none";
    }
};
appendDiv();
  • 这样做不合理,会使其成为一个难以复用的函数,并不是每个人创建了节点之后就希望它们立刻隐藏

更改:将div.style.display="none";这行代码抽出来,用回调函数的形式传入appendDiv方法:

var appendDiv=function(callback){
    for(var i=0;i<100;i++){
        var div=document.getElementsByTagName("div");
        div.innerHTML=i;
        document.appendChild(div);
        if(typeof callback=="function"){
            callback(div);
        }
    }
};
appendDiv(function(node){
    node.style.display="none";
});
  1. Array.prototype.sort

把可变的部分封装在函数参数里,动态传入Array.prototype.sort

//从小到大
[1,4,3].sort(function(a,b){
    return a-b;
})
//从大到小
[1,4,3].sort(function(a,b){
    return b-a;
})

二、函数作为返回值输出

  1. 判断数据的类型
console.log(Object.prototype.toString.call([1, 2, 3]));  //[object Array]
console.log(Object.prototype.toString.call("str"));  //[object String]
console.log(Object.prototype.toString.call(123));  //[object Number]

例:将这些字符串作为参数提前植入isType函数,代码如下

var isType=function(){
    return function(obj){
        return Object.prototype.toString.call(obj);
    }
};
var isString=isType('String');
var isArray=isType('Array');
var isNumber=isType('Number');
console.log(isArray([1, 2, 3]));  //[object Array]
  1. getSingle

既把函数当作参数传递,又让函数执行后返回了另外一个函数

var getSingle=function(fn){
    var ret;
    return function(){
        return ret || (ret=fn.apply(this,arguments));
    }
};
var getScript=getSingle(function(){
        return document.createElement("script");
});
var script1=getScript();
var script2=getScript();
console.log(script1 === script2);  //true

三、高阶函数实现AOP

把一个函数“动态织入”到另一个函数中

Function.prototype.before=function(beforefn){  //beforefn为新添加的函数,装载了新添加的功能代码
    var self=this;  //保存原函数func的引用
    return function(){  //返回包含了原函数和新函数的“代理”函数
        beforefn.apply(this,arguments);  //执行新函数,且保证this不被劫持
        // 新函数接受的参数会被原封不动地传入原函数,新函数在原函数之前执行
        return self.apply(this,arguments);  //执行原函数并返回原函数的执行结果,并保证this不被劫持
    }
};
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();

四、惰性加载函数

attachEvent——兼容:IE7、IE8;不兼容firefox、chrome、IE9、IE10、IE11、safari、opera
addEventListener——兼容:firefox、chrome、IE、safari、opera;不兼容IE7、IE8

例1:缺点:当它每次被调用时都会执行里面的if条件语句,增加了开销(虽然不大)

var addEvent=function(elem,type,handler){
    if(window.addEventListener){
        return elem.addEventListener(type,handler,false);
    }
    if(window.attachEvent()){
        return elem.attachEvent("on"+type,handler);
    }
}

例2:在代码加载时就立刻进行一次判断

var addEvent = (function(){
    if (window.addEventListener) {
        return elem.addEventListener(type, handler, false);
    }
    if (window.attachEvent()) {
        return elem.attachEvent("on" + type, handler);
    }
})();
  • 可能我们从头到尾都没有使用过addEvent函数,这样会稍稍延长页面ready的时间

例3:惰性加载函数

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);
        }
    }
};
var div1=document.getElementById("div1");
addEvent(div1,"click",function(){
    console.log(1);
});
addEvent(div1,"click",function(){
    console.log(2);
});
  • 在第一次进入条件分支后,在函数内部会重写这个函数,重写之后的函数就是我们期望的addEvent函数,在下一次进入addEvent函数时,addEvent函数就不再存在条件分支
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值