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 相关文章推荐
node.js实现多图片上传实例
Jun 03 Javascript
JavaScript中的函数声明和函数表达式区别浅析
Mar 27 Javascript
Javascript的表单验证-提交表单
Mar 18 Javascript
表单元素值获取方式js及java方式的简单实例
Oct 15 Javascript
node.js报错:Cannot find module 'ejs'的解决办法
Dec 14 Javascript
详解Angularjs在控制器(controller.js)中使用过滤器($filter)格式化日期/时间实例
Feb 17 Javascript
Vue.js实现按钮的动态绑定效果及实现代码
Aug 21 Javascript
webpack中的热刷新与热加载的区别
Apr 09 Javascript
使用JS代码实现俄罗斯方块游戏
Aug 03 Javascript
使用layui实现的左侧菜单栏以及动态操作tab项方法
Sep 10 Javascript
Vue发布订阅模式实现过程图解
Apr 30 Javascript
jQuery实现动态向上滚动
Dec 21 jQuery
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 array_map()数组函数使用说明
2011/07/12 PHP
ThinkPHP简单使用memcache缓存的方法
2016/11/15 PHP
php 与 nginx 的处理方式及nginx与php-fpm通信的两种方式
2018/09/28 PHP
javascript CSS画图之基础篇
2009/07/29 Javascript
js+html+css实现鼠标移动div实例
2013/01/30 Javascript
JavaScript实现带标题的图片轮播特效
2015/05/20 Javascript
jQuery ajax分页插件实例代码
2016/01/27 Javascript
JS控制页面跳转时未请求要跳转的地址怎么回事
2016/10/14 Javascript
BootStrap框架个人总结(bootstrap框架、导航条、下拉菜单、轮播广告carousel、栅格系统布局、标签页tabs、模态框、菜单定位)
2016/12/01 Javascript
JS基于面向对象实现的选项卡效果示例
2016/12/20 Javascript
Angular在一个页面中使用两个ng-app的方法(二)
2017/02/20 Javascript
js前端日历控件(悬浮、拖拽、自由变形)
2017/03/02 Javascript
JS去掉字符串前后空格或去掉所有空格的用法
2017/03/25 Javascript
详解如何在Vue2中实现组件props双向绑定
2017/03/29 Javascript
JavaScript实现的贝塞尔曲线算法简单示例
2018/01/30 Javascript
vue2.0 + ele的循环表单及验证字段方法
2018/09/18 Javascript
关于ES6尾调用优化的使用
2020/09/11 Javascript
[01:36:17]DOTA2-DPC中国联赛 正赛 Ehome vs iG BO3 第一场 1月31日
2021/03/11 DOTA
Python编程对列表中字典元素进行排序的方法详解
2017/05/26 Python
Python 使用PIL numpy 实现拼接图片的示例
2018/05/08 Python
python实现多层感知器
2019/01/18 Python
Python实现打印实心和空心菱形
2019/11/23 Python
Python %r和%s区别代码实例解析
2020/04/03 Python
利用OpenCV中对图像数据进行64F和8U转换的方式
2020/06/03 Python
Python 通过正则表达式快速获取电影的下载地址
2020/08/17 Python
使用postMessage让 iframe自适应高度的方法示例
2019/10/08 HTML / CSS
Expedia泰国:预订机票、酒店和旅游包(航班+酒店)
2016/09/27 全球购物
friso美素佳儿官方海外旗舰店:荷兰原产原罐
2017/07/03 全球购物
加拿大高尔夫超市:Golf Town
2018/01/12 全球购物
一句话工作感言
2014/03/01 职场文书
机关党建工作汇报材料
2014/08/20 职场文书
教师批评与自我批评材料
2014/10/16 职场文书
投诉信回复范文
2015/07/03 职场文书
Android基础入门之dataBinding的简单使用教程
2022/06/21 Java/Android
Nginx代理Redis哨兵主从配置的实现
2022/07/15 Servers
Python 操作pdf pdfplumber读取PDF写入Exce
2022/08/14 Python