js 什么是分时函数、惰性加载函数?带你一块了解下

1,085 阅读5分钟

这是我参与8月更文挑战的第12天,活动详情查看:8月更文挑战

前言

前几天看到一本书叫做《javascript设计模式与开发实践》,翻了几篇发现写的非常不错,个人觉得挺对我的胃口。然后当我推荐给身边朋友的时候,他们说这个很早就看过了,一本比较经典的书了,好吧!!!!!! 我翻了几篇看到了几个新名词:分时函数惰性加载函数。 但愿我不是最后知道的😂,接下来就总结一篇我看到的、学到的东西。

开始

分时函数

什么是分时函数呢?我觉得你可能在项目种也是用到过的,就是比如你需要新增1000个div到body, 这个时候直接绘制1000个div到body,其实浏览器是非常有压力的。 但是如果把这个1000个div用50m分批绘制,一批200个(10m), 那这个时候浏览器的压力就小了。 这个就是分时,那分时函数当然就是咱们把逻辑封装成函数了

代码实践:

//第一步先确定参数
//参数一  应该是数组(1000) Array
//参数二 应该是分批绘制的动作也就是个回调函数 Function
//参数三 应该是每次分批的绘制的量 Number
//参数四 应该是没批次绘制的时间(ms) Date
//结论函数应该是这个样的  timeChunk([], function() {}, 10, 1000)


/**
 * @params { Array } ary
 * @params { Function } fn
 * @params { Number } count
 * @params { Number } interval
*/

//第一步 先写分批绘制的函数start()

//condition 是咱们的count分批数量多少比如(100), Math.min(count || 1, ary.length)这个主要是兼容吧 怕ary的长度小了
//循环调用fn()回调, ary一直截取前一个
function timeChunk(ary, fn, count, interval) {
   const start = function() {
        let i = 0;
        const condition = Math.min(count || 1, ary.length)
        while (i < condition) {
            let a = ary.shift();
            fn(a);
            i++;
        }
    }
}


//第二步:首次立刻调用
function timeChunk(ary, fn, count, interval) {
   const start = function() {
        let i = 0;
        const condition = Math.min(count || 1, ary.length)
        while (i < condition) {
            let a = ary.shift();
            fn(a);
            i++;
        }
    }

    //第一次立刻调用(第一批)
    let firstTime = true;
    return function() {
        if(firstTime) {
            start();
            firstTime = false;
        }
    }
}


//第三步 然后再定时器分批次绘制(有点节流的感觉哈)我也是这个么觉得的
function timeChunk(ary, fn, count, interval) {
   const start = function() {
        let i = 0;
        const condition = Math.min(count || 1, ary.length)
        while (i < condition) {
            let a = ary.shift();
            fn(a);
            i++;
        }
    }

    //第一次立刻调用(第一批)
    let firstTime = true, time;
    return function() {
        if(firstTime) {
            start();
            firstTime = false;
        }

        //写个定时器执行咱们的分批任务
       time = setInterval(() => {
         if(ary.length === 0) {
            clearInterval(time);
          }
          start();
        }, interval || 500)
    }
}



//使用起来
let ary = new Array(100).fill(0);
const renderList = timeChunk(ary, function() {
  console.log('我是timeChunk分批绘制函数平均每2秒绘制10次')
}, 10, 2000);

renderList();

防抖函数

什么是防抖函数呢? 就是在我多次触发的时候就执行我最后触发一次。这个样能大大减少不必要的性能,联动问题。 例如:我一个保存按钮用户一直再用鼠标点,这个时候在没做任何处理的情况下会多次触发保存事件。俩个解决方案:1、按钮loading,确定再第一次点了保存成功后才允许下次点击。2、添加防抖动事件,让用户随意点,程序就触发用户最后一次的动作。在选择2的时候就用到了咱们今天的防抖函数了。

代码实践:

//第一不从封装函数的角度出发,save就是咱们的按钮触发的事件:
let time;
function save() {
  if(time) { clearTimeout(time) }

  time = setTimeout(() => {
      clearTimeout(time);
      time = null;
      console.log('我是保存按钮的事件')
  }, 1000)
}


//上面就是一个简单的防抖的事件函数了。 大致就是在我一直点击save得时候一直清除定时器,最后一次才保留


//封装成一个通用的防抖函数
function debounce(fn, interval) {
    let time;
    return function() {
        let args = arguments;
        if(time) { clearTimeout(time) }

        time = setTimeout(() => {
                fn.apply(this, args)
                clearTimeout(time)
                time = null;
        }, interval || 500)
    }
}

//save按钮使用方式
const save = debounce(function() {
    console.log('我是save函数添加了防抖事件')
    //就可以再下面添加自己的逻辑了
}, 1000)

节流函数

节流函数跟防抖函数有区别嘛? 有!!!! 单从名称上就有区别。说一下节流函数:1、首次先调用一次;2、再多次触发的时间内比如30秒, 尼定义的节流函数是1秒 那么再尼连续点击的时间内会触发30次。这就是节流函数

代码实践:

//还是以保存按钮为例,给保存按钮添加节流事件

let time, firstTime = true;
function save() {
    if(fistTime) {
        console.log('我是save的节流事件,我首次触发立刻调用')
        return firstTime = false;
    }
    if(time) return
    time = setTimeout(() => {
        clearTimeout(time);
        time = null;
        console.log('我是save的节流事件')
    },1000)
}

//上面就是直接再save里面写的节流事件了


//那咱们封装下这个节流函数 搞成通用的

function throttle(fn, interval) {
    let time, firstTime = true;

    return function() {
        const args = arguments;
        const _m = this;
        if(firstTime) {
          fn.apply(_m, args)
          return firstTime = false;
        }


        if(time) return
        time = setTimeout(() => {
            fn.apply(_m, args)
            clearTimeout(time);
             time = null;
        }, interval || 500)

    }
}

//给save 添加节流事件
const save = throttle(() => {
    console.log('我是save的节流函数')
}, 1000)

惰性加载函数

什么是惰性加载函数呢? 就是优化咱们的经常调用的函数。但是为什么叫惰性加载呢?不理解!!!!!!(可能就是把一些不用加载或没必要做的判断抽象成不做,或者少做的)

代码实践:

//以书上的例子总结吧(没有想到更好的方案)浏览器的兼容

//未优化前
let addEvent = function(elem, type, handler) {
  if(window.addEventListener) {
      return elem.addEventListener(type, handler, false)
  }

  if(window.attachEvent) {
      return elem.attachEvent(`on${type}`, handler)
  }
}

//缺点:每次加载都需要进行判断进入里面的if条件



//第一次优化:

let addEvent = (function() {
   if(window.addEventListener) {
      return function() {
          elem.addEventListener(type, handler, false)
      }
   }

   if(window.attachEvent) {
      return function() {
          elem.attachEvent(`on${type}`, handler)
      }
   }
})();
//优化后的缺点是 平白无故先调用了下addEvent



//第二次优化就是咱们的惰性加载函数看看是什么样的
let addEvent = function(ele, type, handler) {
      if(window.addEventListener) {
          addEvent = function(ele, type, handler) {
            ele.addEventListener(type, handler, false);
          }
      }else if(window.attachEvent) {
         addEvent = function(ele, type, handler) {
            ele.attachEvent(`on${type}`, handler)
         }
      }

    
      addEvent(ele, type, handler);
  }

//咱们大致分析下这个函数
//1、在使用的第一次判断了下 
//2、直接更改了addEvent(这个时候的addEvent已经是判断后的了,在下次就不会在进行判断了)
//3、为什么在底部执行了一遍  addEvent(ele, type, handler)? 其实就是更改后的函数调用下,不能就返回一个函数。第一次没出发吧

总结

以上就是我对几种函数的理解

结束语

  • 大家好 我是三原,多谢您的观看,我会更加努力(๑•̀ㅂ•́)و✧多多总结。
  • 每个方法都是敲出来验证过通过的,有需要可以放心复制。
  • 如果您给帮点个赞👍就更好了 谢谢您~~~~~
  • 期待您的关注