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 相关文章推荐
jquery 倒计时效果实现秒杀思路
Sep 11 Javascript
js 页面元素的几个用法总结
Nov 18 Javascript
javascript实现详细时间提醒信息效果的方法
Mar 11 Javascript
js如何实现淡入淡出效果
Nov 18 Javascript
javascript仿百度输入框提示自动下拉补全
Jan 07 Javascript
HTML5+jQuery插件Quicksand实现超酷的星际争霸2兵种分类展示效果(附demo源码下载)
May 25 Javascript
Angular 2.x学习教程之结构指令详解
May 25 Javascript
vue将对象新增的属性添加到检测序列的方法
Feb 24 Javascript
基于Vue-Cli 打包自动生成/抽离相关配置文件的实现方法
Dec 09 Javascript
JavaScript实现答题评分功能页面
Jun 24 Javascript
js+css3实现简单时钟特效
Sep 13 Javascript
详解node.js创建一个web服务器(Server)的详细步骤
Jan 15 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控制器调度使用示例
2014/02/24 PHP
PHP正则提取不包含指定网址的图片地址的例子
2014/04/21 PHP
php实现的mongodb操作类实例
2015/04/03 PHP
php实现用已经过去多长时间的方式显示时间
2015/06/05 PHP
php中smarty模板条件判断用法实例
2015/06/11 PHP
PHP register_shutdown_function()函数的使用示例
2015/06/23 PHP
laravel-admin 实现在指定的相册下添加照片
2019/10/21 PHP
js中string转int把String类型转化成int类型
2014/08/13 Javascript
js图片翻书效果代码分享
2015/08/20 Javascript
关于vue.js弹窗组件的知识点总结
2016/09/11 Javascript
两种简单的跨域方法(jsonp、php)
2017/01/02 Javascript
JavaScript寄生组合式继承实例详解
2018/01/06 Javascript
关于Mac下安装nodejs、npm和cnpm的教程
2018/04/11 NodeJs
node puppeteer(headless chrome)实现网站登录
2018/05/09 Javascript
浅谈Angular6的服务和依赖注入
2018/06/27 Javascript
如何获取vue单文件自身源码路径
2019/05/06 Javascript
vue 实现input表单元素的disabled示例
2019/10/28 Javascript
JavaScript实现简单计算器功能
2019/12/19 Javascript
微信小程序订阅消息(java后端实现)开发
2020/06/01 Javascript
html5以及jQuery实现本地图片上传前的预览代码实例讲解
2021/03/01 jQuery
[48:37]EG vs OG 2018国际邀请赛小组赛BO2 第一场 8.17
2018/08/18 DOTA
python队列queue模块详解
2018/04/27 Python
儿童编程python入门
2018/05/08 Python
DataFrame.groupby()所见的各种用法详解
2020/06/14 Python
超市端午节活动方案
2014/01/23 职场文书
校园文化建设方案
2014/02/03 职场文书
考生诚信考试承诺书
2014/05/23 职场文书
公司演讲稿开场白
2014/08/25 职场文书
党员四风自我剖析材料思想汇报
2014/09/13 职场文书
总经理助理岗位职责范本
2015/03/31 职场文书
成品仓管员岗位职责
2015/04/01 职场文书
师德师风主题教育活动总结
2015/05/07 职场文书
感恩教育观后感
2015/06/17 职场文书
婚庆开业庆典主持词
2015/06/30 职场文书
2015年征兵工作总结
2015/07/23 职场文书
2016春季幼儿园开学寄语
2015/12/03 职场文书