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 innerHTML、outerHTML、innerText、outerText的区别
Nov 24 Javascript
select 控制网页内容隐藏于显示的实现代码
May 25 Javascript
javascript动态加载三
Aug 22 Javascript
javascript创建和存储cookie示例
Jan 07 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
Js实现简单的小球运动特效
Feb 18 Javascript
jQuery 获取跨域XML(RSS)数据的相关总结分析
May 18 Javascript
jQuery通过ajax请求php遍历json数组到table中的代码(推荐)
Jun 12 Javascript
高效的jQuery代码编写技巧总结
Feb 22 Javascript
微信小程序 实现点击添加移除class
Jun 12 Javascript
web前端vue之vuex单独一文件使用方式实例详解
Jan 11 Javascript
如何使用Node.js爬取任意网页资源并输出PDF文件到本地
Jun 17 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
杏林同学录(九)
2006/10/09 PHP
php简单静态页生成过程
2008/03/27 PHP
PHP生成唯一的促销/优惠/折扣码(附源码)
2012/12/28 PHP
采用ThinkPHP中F方法实现快速缓存实例
2014/06/13 PHP
php实现mysql数据库分表分段备份
2015/06/18 PHP
Javascript remove 自定义数组删除方法
2009/10/20 Javascript
浅谈javascript中的闭包
2015/05/13 Javascript
jquery插件jquery.nicescroll实现图片无滚动条左右拖拽的方法
2015/08/10 Javascript
jquery实现适用于门户站的导航下拉菜单效果代码
2015/08/24 Javascript
jquery实现简易的移动端验证表单
2015/11/08 Javascript
javascript弹出带文字信息的提示框效果
2016/07/19 Javascript
jquery层级选择器的实现(匹配后代元素div)
2016/09/05 Javascript
canvas实现图像放大镜
2017/02/06 Javascript
详解Webstorm 新建.vue文件支持高亮vue语法和es6语法
2017/10/26 Javascript
vue基础之v-bind属性、class和style用法分析
2019/03/11 Javascript
读懂CommonJS的模块加载
2019/04/19 Javascript
对vue中的事件穿透与禁止穿透实例详解
2019/10/28 Javascript
[43:32]2014 DOTA2华西杯精英邀请赛 5 25 LGD VS NewBee第一场
2014/05/26 DOTA
Windows下Eclipse+PyDev配置Python+PyQt4开发环境
2016/05/17 Python
Python自动化运维_文件内容差异对比分析
2017/12/13 Python
Python中的并发处理之asyncio包使用的详解
2018/04/03 Python
Python使用min、max函数查找二维数据矩阵中最小、最大值的方法
2018/05/15 Python
如何理解Python中包的引入
2020/05/29 Python
python 识别登录验证码图片功能的实现代码(完整代码)
2020/07/03 Python
五分钟带你搞懂python 迭代器与生成器
2020/08/30 Python
python 邮件检测工具mmpi的使用
2021/01/04 Python
selenium设置浏览器为headless无头模式(Chrome和Firefox)
2021/01/08 Python
英国著名的药妆网站:Escentual
2016/07/29 全球购物
荷兰最大的儿童服装店:The Kids Republic
2019/04/13 全球购物
《挑山工》的教学反思
2014/02/16 职场文书
人力管理专业毕业生求职信
2014/02/27 职场文书
医德医风演讲稿
2014/05/20 职场文书
冬季安全检查方案
2014/05/23 职场文书
2014年政风行风自查自纠报告
2014/10/21 职场文书
研究生给导师的自荐信
2015/03/06 职场文书
JavaScript声明变量和数据类型的转换
2022/04/12 Javascript