JS防抖和节流实例解析


Posted in Javascript onSeptember 24, 2019

日常开发过程中,滚动事件做复杂计算频繁调用回调函数很可能会造成页面的卡顿,这时候我们更希望把多次计算合并成一次,只操作一个精确点,JS把这种方式称为debounce(防抖)和throttle(节流)

函数防抖

当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定时间到来之前,又触发了事件,就重新开始延时。也就是说当一个用户一直触发这个函数,且每次触发函数的间隔小于既定时间,那么防抖的情况下只会执行一次。

function debounce(fn, wait) {
  var timeout = null;   //定义一个定时器
  return function() {
    if(timeout !== null) 
        clearTimeout(timeout); //清除这个定时器
    timeout = setTimeout(fn, wait); 
  }
}
// 处理函数
function handle() {
  console.log(Math.random()); 
}
// 滚动事件
window.addEventListener('scroll', debounce(handle, 1000));

JS防抖和节流实例解析

如上所见,当持续触发scroll函数,handle函数只会在1秒时间内执行一次,在滚动过程中并没有持续执行,有效减少了性能的损耗

函数节流

当持续触发事件时,保证在一定时间内只调用一次事件处理函数,意思就是说,假设一个用户一直触发这个函数,且每次触发小于既定值,函数节流会每隔这个时间调用一次

用一句话总结防抖和节流的区别:防抖是将多次执行变为最后一次执行,节流是将多次执行变为每隔一段时间执行
实现函数节流我们主要有两种方法:时间戳和定时器

例如

var throttle = function(func, delay) {
  var prev = Date.now();
  return function() {
    var context = this;  //this指向window
    var args = arguments;
    var now = Date.now();
    if (now - prev >= delay) {
      func.apply(context, args);
      prev = Date.now();
    }
  }
}
function handle() {
  console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));

这个节流函数利用时间戳让第一次滚动事件执行一次回调函数,此后每隔1000ms执行一次,在小于1000ms这段时间内的滚动是不执行的
再举一个定时器的例子:

var throttle = function(func, delay) {
  var timer = null;
  return function() {
    var context = this;
    var args = arguments;
    if (!timer) {
      timer = setTimeout(function() {
        func.apply(context, args);
        timer = null;
      }, delay);
    }
  }
}
function handle() {
  console.log(Math.random());
}
window.addEventListener('scroll', throttle(handle, 1000));

当触发事件的时候,我们设置了一个定时器,在没到1000ms之前这个定时器为null,而到了规定时间执行这个函数并再次把定时器清除。也就是说当第一次触发事件,到达规定时间再执行这个函数,执行之后马上清除定时器,开始新的循环,那么我们看到的效果就是,滚动之后没有马上打印,而是等待1000ms打印,有一个延迟的效果,并且这段时间滚动事件不会执行函数。
单用时间戳或者定时器都有缺陷,我们更希望第一次触发马上执行函数,最后一次触发也可以执行一次事件处理函数

var throttle = function(func, delay) {
   var timer = null;
   var startTime = Date.now(); //设置开始时间
   return function() {
       var curTime = Date.now();
       var remaining = delay - (curTime - startTime); //剩余时间
       var context = this;
       var args = arguments;
       clearTimeout(timer);
       if (remaining <= 0) {   // 第一次触发立即执行
          func.apply(context, args);
          startTime = Date.now();
       } else {
          timer = setTimeout(func, remaining);  //取消当前计数器并计算新的remaining
       }
   }
}
function handle() {
   console.log(Math.random());
}
 window.addEventListener('scroll', throttle(handle, 1000));

JS防抖和节流实例解析

在节流函数内部使用开始时间startTime、当前时间curTime和剩余时间remaining,当剩余时间小于等于0意味着执行处理函数,这样保证第一次就能立即执行函数并且每隔delay时间执行一次;如果还没到时间,就会在remaining之后触发,保证最后一次触发事件也能执行函数,如果在remaining时间内又触发了滚动事件,那么会取消当前的计数器并计算出新的remaing时间。通过时间戳和定时器的方法,我们实现了第一次立即执行,最后一次也执行,规定时间间隔执行的效果,可以灵活运用在开发中

PS:防抖和节流能有效减少浏览器引擎的损耗,防止出现页面堵塞卡顿现象,应该熟练掌握。最后再次感谢原作者的总结,热心分享技术让我们的生活变得更好

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
ExtJs GridPanel简单的增删改实现代码
Aug 26 Javascript
浅析jquery ajax异步调用方法中不能给全局变量赋值的原因及解决方法
Jan 10 Javascript
js实现的map方法示例代码
Jan 13 Javascript
javascript window.open打开新窗口后无法再次打开该窗口问题的解决方法
Apr 12 Javascript
javascript中Number的方法小结
Nov 21 Javascript
Vue学习笔记进阶篇之vue-router安装及使用方法
Jul 19 Javascript
Vue-Cli中自定义过滤器的实现代码
Aug 12 Javascript
js中Object.defineProperty()方法的不详解
Jul 09 Javascript
jQuery滑动效果实现方法分析
Sep 05 jQuery
js获取对象,数组所有属性键值(key)和对应值(value)的方法示例
Jun 19 Javascript
深入浅出vue图片路径的实现
Sep 04 Javascript
解决Vue-Router升级导致的Uncaught (in promise)问题
Aug 07 Javascript
vue.js实现图书管理功能
Sep 24 #Javascript
layui table单元格事件修改值的方法
Sep 24 #Javascript
Javascript Dom元素获取和添加详解
Sep 24 #Javascript
微信小程序全局变量的设置、使用、修改过程解析
Sep 24 #Javascript
layui监听select变化,以及设置radio选中的方法
Sep 24 #Javascript
layui 监听select选择 获取当前select的ID名称方法
Sep 24 #Javascript
layui监听下拉选框选中值变化的方法(包含监听普通下拉选框)
Sep 24 #Javascript
You might like
ThinkPHP使用心得分享-上传类UploadFile的使用
2014/05/15 PHP
Javascript 刷新全集常用代码
2009/11/22 Javascript
jquery 层次选择器siblings与nextAll的区别介绍
2013/08/02 Javascript
JavaScript声明变量名的语法规则
2015/07/10 Javascript
JavaScript实现图片滑动切换的代码示例分享
2016/03/06 Javascript
Angular路由简单学习
2016/12/26 Javascript
10个最优秀的Node.js MVC框架
2017/08/24 Javascript
小程序测试后台服务的方法(ngrok)
2019/03/08 Javascript
ajax跨域访问遇到的问题及解决方案
2019/05/23 Javascript
NodeJS实现一个聊天室功能
2019/11/25 NodeJs
微信小程序云函数添加数据到数据库的方法
2020/03/04 Javascript
微信小程序实现购物车小功能
2020/12/30 Javascript
[01:30:15]DOTA2-DPC中国联赛 正赛 Ehome vs Aster BO3 第二场 2月2日
2021/03/11 DOTA
python使用装饰器和线程限制函数执行时间的方法
2015/04/18 Python
python选择排序算法实例总结
2015/07/01 Python
python使用pymysql实现操作mysql
2016/09/13 Python
Python 比较两个数组的元素的异同方法
2017/08/17 Python
Python基于回溯法子集树模板解决最佳作业调度问题示例
2017/09/08 Python
Python基于opencv调用摄像头获取个人图片的实现方法
2019/02/21 Python
使用 Python 快速实现 HTTP 和 FTP 服务器的方法
2019/07/22 Python
Django ORM 查询管理器源码解析
2019/08/05 Python
python中下标和切片的使用方法解析
2019/08/27 Python
简单了解python元组tuple相关原理
2019/12/02 Python
Python unittest单元测试openpyxl实现过程解析
2020/05/27 Python
史上最详细的Python打包成exe文件教程
2021/01/17 Python
pandas统计重复值次数的方法实现
2021/02/20 Python
网页切图的CSS和布局经验与要点
2015/04/09 HTML / CSS
eDreams澳大利亚:预订机票、酒店和度假产品
2017/04/19 全球购物
shell程序中如何注释
2012/02/17 面试题
六十大寿答谢词
2014/01/12 职场文书
校本教研工作制度
2014/01/22 职场文书
入党积极分子学习两会心得体会范文
2014/03/17 职场文书
学术会议邀请函
2015/01/30 职场文书
物业公司管理制度
2015/08/05 职场文书
python垃圾回收机制原理分析
2022/04/13 Python