JavaScript函数节流和函数去抖知识点学习


Posted in Javascript onJuly 31, 2018

概念

节流 (throttle) 让一个函数不要执行的太频繁,减少执行过快的调用,叫节流

去抖 (debounce) 去抖就是对于一定时间段的连续的函数调用,只让其执行一次

throttle 应用场景

  • DOM 元素的拖拽功能实现(mousemove)
  • 射击游戏的 mousedown/keydown 事件(单位时间只能发射一颗子弹)
  • 计算鼠标移动的距离(mousemove)
  • Canvas 模拟画板功能(mousemove
  • 搜索联想(keyup
  • 监听滚动事件判断是否到页面底部自动加载更多:给 scroll 加了 debounce 后,只有用户停止滚动后,才会判断是否到了页面底部;如果是 throttle 的话,只要页面滚动就会间隔一段时间判断一次

debounce 应用场景

每次 resize/scroll 触发统计事件

文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)

函数去抖的实现

我们以scroll事件为例,探究如何是实现滚动一次窗口打印一个hello world 字符串。 如果不对其节流或者去抖:

window.onscroll = function () {
 console.log('hello world');
}

这样每滚动一次,实际上会打印多个 hello world。 函数去抖背后的思路是指,某些代码不可能在没有间断的情况下连续执行。创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个。如果前一个定时器已经执行过了,这个操作就没有任何意义。然而,如果前一个定时器尚未执行,其实就是将其替换为一个新的定时器。目的是只有在执行函数的请求停止了一段时间之后才执行。

《高程三》给出了最简洁最经典的去抖代码,如下:

function debounce(method, context) {
 clearTimeout(method.tId);
 method.tId = setTimeout(function() {
 method.call(context);
 }, 1000);
}

function print() {
 console.log('hello world');
}

window.onscroll = function() {
 debounce(print);
};

再做一些改动

function debounce(delay, action) {
 var tId;
 return function () {
  var context = this;
  var arg = arguments;
  if (tId) clearTimeout(tId);
  tId = setTimeout(function () {
   action.apply(context, arg);
  }, delay);
 }
}

window.onscroll = debounce(1000, print);

函数节流的实现

函数节流就是让连续执行的函数,变为固定时间段间断地执行。 大概有两种方式实现。

其一使用时间戳来判断是否已经到回调执行时间,记录上次执行的时间戳,然后每次触发事件时执行回调,回调中判断当前时间戳距离上次执行时间戳的时间间隔是否有*s,如果是,则执行,并更新上次执行的时间戳,如此循环。

var throttle = function(delay, action) {
 var last = 0;
 return function() {
  var curr = new Date();
  if (curr - last > delay) {
   action.apply(this, arguments);
   last = curr;
  }
 }
}

第二种方法是使用定时器,比如,当scroll事件刚触发时,打印一个hello world ,然后设置一个1000ms的定时器,此后每次触发scroll事件,触发回调,如果已经存在定时器,则回调不执行方法,知道定时器出发,handler被清除,然后重新设置定时器。

var throttle = function(delay, action) {
 var timeout;
 var later = function () {
  timeout = setTimeout(function(){
   clearTimeout(timeout);
   // 解除引用
   timeout = null;
  }, delay);
 };
 later();
 if (!timeout) {
  action.apply(this, arguments);
  later();
 }
}

更新方法:

function throttlePro(delay, action) {
 var tId;
 return function () {
  var context = this;
  var arg = arguments;
  if (tId) return;
  tId = setTimeout(function () {
   action.apply(context, arg);
   clearTimeout(tId);
   // setTimeout 返回一个整数,clearTimeout 之后,tId还是那个整数,setInterval同样如此
   tId = null;
  }, delay);
 }
}
Javascript 相关文章推荐
(转载)JavaScript中匿名函数,函数直接量和闭包
May 08 Javascript
jquery 跨域访问问题解决方法(笔记)
Jun 08 Javascript
JavaScript获得页面base标签中url的方法
Apr 03 Javascript
基于jquery实现鼠标左右拖动滑块滑动附源码下载
Dec 23 Javascript
当jquery ajax遇上401请求的解决方法
May 19 Javascript
js中class的点击事件没有效果的解决方法
Oct 13 Javascript
JavaScript制作弹出层效果
Dec 02 Javascript
走进javascript——不起眼的基础,值和分号
Feb 24 Javascript
vue 解决addRoutes动态添加路由后刷新失效问题
Jul 02 Javascript
优雅的在React项目中使用Redux的方法
Nov 10 Javascript
vue里的data要用return返回的原因浅析
May 28 Javascript
如何优雅地取消 JavaScript 异步任务
Mar 22 Javascript
JS使用遮罩实现点击某区域以外时弹窗的弹出与关闭功能示例
Jul 31 #Javascript
微信网页授权并获取用户信息的方法
Jul 30 #Javascript
axios简单实现小程序延时loading指示
Jul 30 #Javascript
JS实现HTML页面中动态显示当前时间完整示例
Jul 30 #Javascript
JS实现DOM节点插入操作之子节点与兄弟节点插入操作示例
Jul 30 #Javascript
js+html5实现手机九宫格密码解锁功能
Jul 30 #Javascript
vscode中vue-cli项目es-lint的配置方法
Jul 30 #Javascript
You might like
基于preg_match_all采集后数据处理的一点心得笔记(编码转换和正则匹配)
2014/01/31 PHP
PHP程序员不应该忽略的3点
2015/10/09 PHP
深入讲解PHP的对象注入(Object Injection)
2017/03/01 PHP
微信公众平台开发-微信服务器IP接口实例(含源码)
2017/03/05 PHP
利用PHP判断是手机移动端还是PC端访问的函数示例
2017/12/14 PHP
thinkphp5 URL和路由的功能详解与实例
2017/12/26 PHP
php设计模式之观察者模式实例详解【星际争霸游戏案例】
2020/03/30 PHP
javascript 带有滚动条的表格,标题固定,带排序功能.
2009/11/13 Javascript
JavaScript 常见对象类创建代码与优缺点分析
2009/12/07 Javascript
javascript算法题 求任意一个1-9位不重复的N位数在该组合中的大小排列序号
2012/07/21 Javascript
缓动函数requestAnimationFrame 更好的实现浏览器经动画
2012/12/07 Javascript
多种方法实现360浏览器下禁止自动填写用户名密码
2014/06/16 Javascript
js怎么判断flash swf文件是否加载完毕
2014/08/14 Javascript
Node.js 文件夹目录结构创建实例代码
2016/07/08 Javascript
全面接触神奇的Bootstrap导航条实战篇
2016/08/01 Javascript
jQuery使用方法
2017/02/04 Javascript
Angular中innerHTML标签的样式不起作用的原因解析
2019/06/18 Javascript
JS数组方法reduce的用法实例分析
2020/03/03 Javascript
只有 20 行的 JavaScript 模板引擎实例详解
2020/05/11 Javascript
Python和Ruby中each循环引用变量问题(一个隐秘BUG?)
2014/06/04 Python
Python模拟百度登录实例详解
2016/01/20 Python
轻松掌握python设计模式之访问者模式
2016/11/18 Python
Python中datetime模块参考手册
2017/01/13 Python
Python3 把一个列表按指定数目分成多个列表的方式
2019/12/25 Python
如何更改 pandas dataframe 中两列的位置
2019/12/27 Python
将labelme格式数据转化为标准的coco数据集格式方式
2020/02/17 Python
StubHub智利:购买和出售您的门票
2016/11/23 全球购物
美国体育用品商店:Academy Sports + Outdoors
2020/01/04 全球购物
旅游项目开发策划书
2014/01/18 职场文书
本科毕业生求职自荐信
2014/04/09 职场文书
工会优秀工作者事迹
2014/08/17 职场文书
银行授权委托书范本
2014/10/04 职场文书
思想作风整顿个人剖析材料
2014/10/06 职场文书
2014年保密工作总结
2014/11/22 职场文书
工作年限证明模板
2015/06/15 职场文书
Python常遇到的错误和异常
2021/11/02 Python