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 相关文章推荐
分别用marquee和div+js实现首尾相连循环滚动效果,仅3行代码
Sep 21 Javascript
jquery选择器之属性过滤选择器详解
Jan 27 Javascript
javascript验证身份证号
Mar 03 Javascript
jQuery实现鼠标双击Table单元格变成文本框及输入内容后更新到数据库的方法
Nov 25 Javascript
jQuery Validate表单验证插件 添加class属性形式的校验
Jan 18 Javascript
JS中input表单隐藏域及其使用方法
Feb 13 Javascript
JS实现快速比较两个字符串中包含有相同数字的方法
Sep 11 Javascript
js实现简单数字变动效果
Nov 06 Javascript
原生JS实现 MUI导航栏透明渐变效果
Nov 07 Javascript
Vue请求JSON Server服务器数据的实现方法
Nov 02 Javascript
vue接入腾讯防水墙代码
May 07 Javascript
一篇文章带你从零快速上手Rollup
Sep 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
php无序树实现方法
2015/07/28 PHP
PHP实现移除数组中为空或为某值元素的方法
2017/01/07 PHP
Laravel 5.2 文档 数据库 ―― 起步介绍
2019/10/21 PHP
IE6下CSS图片缓存问题解决方法
2010/12/09 Javascript
JQuery页面图片切换和新闻列表滚动效果的具体实现
2013/09/26 Javascript
js使用正则实现ReplaceAll全部替换的方法
2014/08/22 Javascript
javascript实现漂亮的拖动层,窗口拖拽特效
2015/04/24 Javascript
js 声明数组和向数组中添加对象变量的简单实例
2016/07/28 Javascript
PHP抓取HTTPS内容和错误处理的方法
2016/09/30 Javascript
JS中实现函数return多个返回值的实例
2017/02/21 Javascript
微信小程序实现点击按钮修改view标签背景颜色功能示例【附demo源码下载】
2017/12/06 Javascript
vue动态绑定组件子父组件多表单验证功能的实现代码
2018/05/14 Javascript
jQuery基于Ajax实现读取XML数据功能示例
2018/05/31 jQuery
jQuery实现表格隔行换色
2018/09/01 jQuery
如何实现一个webpack模块解析器
2018/10/24 Javascript
详解vue挂载到dom上会发生什么
2019/01/20 Javascript
基于elementUI实现图片预览组件的示例代码
2019/03/31 Javascript
轻松解决JavaScript定时器越走越快的问题
2019/05/13 Javascript
关于ligerui子页面关闭后,父页面刷新,重新加载的方法
2019/09/27 Javascript
微信小程序利用button控制条件标签的变量问题
2020/03/15 Javascript
Python完全新手教程
2007/02/08 Python
linux系统使用python监测系统负载脚本分享
2014/01/15 Python
解决在pycharm中显示额外的 figure 窗口问题
2019/01/15 Python
python itchat给指定联系人发消息的方法
2019/06/11 Python
如何使用Python自动控制windows桌面
2019/07/11 Python
python 类的继承 实例方法.静态方法.类方法的代码解析
2019/08/23 Python
Python全局锁中如何合理运用多线程(多进程)
2019/11/06 Python
python中自带的三个装饰器的实现
2019/11/08 Python
Python爬虫解析网页的4种方式实例及原理解析
2019/12/30 Python
分享8款纯CSS3实现的搜索框功能
2017/09/14 HTML / CSS
css3气泡 css3关键帧动画创建的动态通知气泡
2013/02/26 HTML / CSS
莱德杯高尔夫欧洲官方商店:Ryder Cup Shop
2019/08/14 全球购物
自荐书范文
2013/12/08 职场文书
《雪地里的小画家》教学反思
2014/02/22 职场文书
财务管理职业生涯规划书
2014/02/26 职场文书
Java基础之详解HashSet的使用方法
2021/06/30 Java/Android