js: 高阶函数

函数视作高阶函数的条件
函数可作为参数被传递 或 函数可做为返回值输出
1.函数作为参数被传递:回调函数
回调函数应用:异步处理(ajax)、调用函数的内部数据“委托”回调函数处理(Array.prototype.sort)

2.函数做为返回值输出

    var pointSingle = function(fn){
      var single;
      return function(){
        // 返回已创建对象 或 返回创建对象的函数
        return single || (single = fn.apply(this, arguments))
      };
    }
    // 根据参数 生成点
    var point = function(x,y){ return { left: x, top: y}; };
    // 生成唯一点
    var getPoint = pointSingle( point );

    var point01 = getPoint(0,0);
    var point02 = getPoint(10,10);

    // point01 point02指向同一个 { left: 0, top: 0}为第一次创建的 point01 = getPoint(0,0);
    console.log(point01 === point02); 
    console.log(point01); //{ left: 0, top: 0}
    console.log(point02); //{ left: 0, top: 0}

其他应用:
实现AOP
(面向切片编程:把与核心业务逻辑模块无关的功能分离,动态加入业务逻辑,以保持业务模块的纯净和高内聚,且实现无关模块的复用。),如 日志功能等。

    Function.prototype.setLog = function(before, after){
      var _self = this;
      return function(){
        before.apply(this, arguments);
        var ret = _self.apply(this, arguments);
        after.apply(this, arguments);
        return ret;
      }
    }
    // 业务代码
    var func = function(){
      console.log("run func.");
    }
    // 给业务代码增加日志
    func = func.setLog(
      function(){ console.log("before ");},
      function(){ console.log("after ");}
    );
    func();
    // 顺序输出:
    // before 
    // run func.
    // after

实现函数节流

    // 函数节流
    var throttle = function(fn, interval){
      var targFunc = fn, // 保存目标函数
          timer,  // 声明定时器
          firstTime = true; // 是否第一次调用

      return function(){
        var args = arguments,
            _this = this;

        if (firstTime){ // 第一次调用,不检查定时器
          targFunc.apply(_this, args);
          return firstTime = false;
        }

        if(timer){ // 定时器未结束
          return false;
        }

        timer = setTimeout(function(){
          clearTimeout(timer);
          timer = null; // 结束时置 null
          targFunc.apply(_this, args);
        }, interval || 500); // 未设置则默认为 500 ms
      };
    };

    window.onresize = throttle(function(){
      console.log(window.document.body.clientWidth);
    }, 500);

实现分时函数(数据分批加载)
例:循环打印 有 1000 个元素的数组的各元素值
普通情况为一次打印完 1000 个数据;
分时则 可做 每隔一段时间 打印一部分;
实现:每1s 打印 10 个数据,共500个

    // 分时函数
    var timeChunk = function(arr, fn, interval, count){
      var timer,
        count;
      count = count || 1; // 默认每次数量为1

      // 每个间隔调用执行
      var start = function(){
        for(var i=0, len=arr.length; i < Math.min(count, len); i++){
          var obj = arr.shift();
          fn(obj);
        }
      };

      return function(){
        timer = setInterval(function(){
          if (arr.length === 0) {
            return clearInterval(timer);
          }
          start();
        }, interval);
      };
    };

    var arr01 = [];
    for (var i =0; i<500; i++){
      arr01.push(i + "-point");
    }

    var testTimeChunk = timeChunk(arr01, function(txt){console.log(txt);}, 1000, 10);
    testTimeChunk();

惰性加载
实现浏览器相同功能不同封装的兼容封装
例:事件监听的封装对比.

    // 事件监听的封装对比
    // 1. 每次调用执行原函数,都会进行判断
    var addEvent01 = function(ele, type, handler){
      if(window.addEventListener){
        return ele.addEventListener(type, handler, false);
      }
      if(window.attachEvent){
        return ele.attachEvent("on"+type, handler );
      }
      throw new Error("not found addEventListener & attachEvent.");
    };
    // 2. 立即执行函数,一定会执行一次判断,返回后addEvent02 不会进行判断
    var addEvent02 = (function(win){
      if(win.addEventListener){
        return function(ele, type, handler){ ele.addEventListener(type, handler, false); };
      }
      if(win.attachEvent){
        return function(ele, type, handler){ ele.attachEvent("on"+type, handler ); };
      }
      throw new Error("not found addEventListener & attachEvent.");
    })(window);
    // 3. 当被调用时,内部进行判断,更改函数定义,之后调用均为更改后的函数
    var addEvent03 = function(ele, type, handler){
      if(window.addEventListener){
        addEvent03 = function(ele, type, handler){
          ele.addEventListener(type, handler, false);
        };
      }else if(window.attachEvent){
        addEvent03 = function(ele, type, handler){
          ele.attachEvent("on"+type, handler );
        };
      }else{
        throw new Error("not found addEventListener & attachEvent.");
      }

      addEvent03(ele, type, handler);
    };

部分代码引用和修改:《JavaScript 设计模式与实践》by曾探,

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值