带着问题去尝试

首先我们要知道为什么要用到函数节流和函数去抖?我们带着以下的疑问来进行分析!

1.比如搜索框,你会用到什么事件(change、blur、keyup等)?去做什么效果?
2.再比如scroll滚动事件,怎么去触发?是滚一段距离触发一次?还是滚一圈触发一次?还是滚一次触发一次?
3.还包括mouseover事件是怎么触发呢?
......

场景实例

函数节流和去抖的出现场景,一般都伴随着客户端 DOM 的事件监听。举个例子,实现一个原生的拖拽功能(不能用 H5 Drag&Drop API),需要一路监听 mousemove 事件,在回调中获取元素当前位置,然后重置 dom 的位置(样式改变)。如果我们不加以控制,每移动一定像素而触发的回调数量是会非常惊人的,回调中又伴随着 DOM 操作,继而引发浏览器的重排与重绘,性能差的浏览器可能就会直接假死,这样的用户体验是非常糟糕的。我们需要做的是降低触发回调的频率,比如让它 500ms 触发一次,或者 200ms,甚至 100ms,这个阈值不能太大,太大了拖拽就会失真,也不能太小,太小了低版本浏览器可能就会假死,这样的解决方案就是函数节流,英文名字叫「throttle」。函数节流的核心是,让一个函数不要执行得太频繁,减少一些过快的调用来节流。

说完函数节流,再看它的好基友函数去抖(debounce)。思考这样一个场景,对于浏览器窗口,每做一次 resize 操作,发送一个请求,很显然,我们需要监听 resize 事件,但是和 mousemove 一样,每缩小(或者放大)一次浏览器,实际上会触发 N 多次的 resize 事件,用节流?节流只能保证定时触发,我们一次就好,这就要用去抖。简单的说,函数去抖就是对于一定时间段的连续的函数调用,只让其执行一次。

实例了解

下面就让我们来了解throttle(节流) 和 debounce(去抖)

1.throttle节流,scroll和mouseover亦或者其他方式,每次移动都会触发代码效果,但是这些效果太密集了,占用了系统资源,计算机的计算能力是有限的,我们写的代码应该尽可能的优雅。
2.debounce去抖,本意是从按键去抖过来的,让我们的用户正确的操作之后才去执行代码,且只会执行一次,比如当我们做文本输入的时候,如果用keyup我们不是去节流,而是去判断用户停止了输入。
3.节流保证在一定时间内,只能触发一次。如果我们只要触发一次,这就是去抖。代码上来看差距不是很大。

直接试一下:

//先来个有问题的代码
window.onscroll=function(){
console.log(new Date());
}

控制台会打印:

VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
VM109:2 Sun Mar 12 2017 18:05:50 GMT+0800 (中国标准时间)
...

控制台会一直这样输入,那问题来了,这获取并不是我们想要的,我们并不想让他一直触发下去。

我们要解决这些问题,所以直接看代码:

//我们先来个节流,每秒输出一次
window.onscroll=function(){
if(window.onScrollTag == undefined){
window.onScrollTag=true;
console.log(new Date());
setTimeout(function(){
window.onScrollTag=undefined;
},1000);
}
}//先触发
window.onscroll=function(){
if(window.onScrollTag == undefined){
window.onScrollTag=setTimeout(function(){
window.onScrollTag=undefined;
console.log(new Date());
},1000); }
}//后触发
//从上面的代码可以看出来,我们在一个事件执行的时候就把标记改成不可用。一秒后才可以再次触发操作。
//我们在尝试一下去抖
window.onscroll=function(){
if(window.onScrollTag != undefined){
clearTimeout(window.onScrollTag);
}
window.onScrollTag=setTimeout(function(){
console.log(new Date());
},1000);
}//消抖,消除抖动,感觉这个更好听
//节流
funtion throttle(func, wait) {  
var lastTime = 0,
timeout;  
return funtion() {    
var context = this,
args = arguments,
delay = wait || 100,
now = new Date().getTime();    
if (now - lastTime <= delay) {      
return;    
}    
lastTime = now;
clearTimeout(timeout);  
timeout = setTimeout(function() {
timeout = null;
func.apply(context, args);
}, delay)  
}
}
// 去抖
function debounce(func, wait) {
var timeout;
return function() {
var context = this,
args = arguments,
delay = wait || 250;
clearTimeout(timeout);
timeout = setTimeout(function() {
timeout = null;
func.apply(context, args);
}, delay);
};
}

throttle 应用场景

函数节流有哪些应用场景?哪些时候我们需要间隔一定时间触发回调来控制函数调用频率?

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

debounce 应用场景

函数去抖有哪些应用场景?哪些时候对于连续的事件响应我们只需要执行一次回调?

  • 每次 resize/scroll 触发统计事件
  • 文本输入的验证(连续输入文字后发送 AJAX 请求进行验证,验证一次就好)

小结

函数节流和函数去抖的核心其实就是限制某一个方法被频繁触发,而一个方法之所以会被频繁触发,大多数情况下是因为 DOM 事件的监听回调,而这也是函数节流以及去抖多数情况下的应用场景

如果大家感兴趣,可以参考下:http://underscorejs.org/

javascript中的函数节流和函数去抖的更多相关文章

  1. JavaScript 中函数节流和函数去抖的讲解

    JavaScript 中函数节流和函数去抖的讲解 我们都知道频繁触发执行一段js逻辑代码对性能会有很大的影响,尤其是在做一些效果实现方面,或者逻辑中需要进行后端请求,更是会导致卡顿,效果失效等结果,所 ...

  2. JavaScript 函数节流和函数去抖应用场景辨析

    概述 也是好久没更新 源码解读,看着房价蹭蹭暴涨,心里也是五味杂陈,对未来充满恐惧和迷茫 ...(敢问一句你们上岸了吗) 言归正传,今天要介绍的是 underscore 中两个重要的方法,函数节流和函 ...

  3. 【javascript】js中的函数节流和函数防抖

    一.概念解释  函数节流和函数防抖,两者都是优化高频率执行js代码的一种手段.  大家大概都知道旧款电视机的工作原理,就是一行行得扫描出色彩到屏幕上,然后组成一张张图片.由于肉眼只能分辨出一定频率的变 ...

  4. 深入理解javascript函数进阶系列第三篇——函数节流和函数防抖

    前面的话 javascript中的函数大多数情况下都是由用户主动调用触发的,除非是函数本身的实现不合理,否则一般不会遇到跟性能相关的问题.但在一些少数情况下,函数的触发不是由用户直接控制的.在这些场景 ...

  5. javaScript函数节流与函数防抖

    javaScript函数节流与防抖之区别 函数防抖(debounce)与函数节流(throttle)都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,出现延迟.假死或卡顿 ...

  6. JavaScript中常见的数组操作函数及用法

    JavaScript中常见的数组操作函数及用法 昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下 ...

  7. JavaScript中常见的字符串操作函数及用法

    JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...

  8. js 函数节流throttle 函数去抖debounce

    1.函数节流throttle 通俗解释: 假设你正在乘电梯上楼,当电梯门关闭之前发现有人也要乘电梯,礼貌起见,你会按下开门开关,然后等他进电梯: 但是,你是个没耐心的人,你最多只会等待电梯停留一分钟: ...

  9. 一篇文章把你带入到JavaScript中的闭包与高级函数

    在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. funct ...

随机推荐

  1. 如何做一个项目.ppt

    链接:https://pan.baidu.com/s/1q8Ogj0xYQV_vk-HGcszxqw 提取码:0a82 复制这段内容后打开百度网盘手机App,操作更方便哦

  2. TestNg框架基础入门

    TestNg框架简介: TestNG,即Testing, Next Generation,下一代测试技术,是一套根据JUnit 和NUnit思想而构建的利用注释来强化测试功能的一个测试框架.TestN ...

  3. C# 断言 Assert

    重构-断言 现象:某一段代码需要对程序状态做出某种假设 做法:以断言明确表现这种假设 动机: 常常有这种一段代码:只有某个条件为真是,该改名才能正常运行. 通常假设这样的假设并没有代码中明确表现出来, ...

  4. 导出insert语句

    --by zhuyj 显示&select ‘\&s’ from dual; --注意必须要加引号 --by zhuyjcreate or replace function fun_ex ...

  5. 高可用Redis(五):瑞士军刀之慢查询,Pipeline和发布订阅

    1.慢查询 1.1 慢查询的生命周期 步骤一:client通过网络向Redis发送一条命令 步骤二:由于Redis是单线程应用,可以把Redis想像成一个队列,client执行的所有命令都在排队等着s ...

  6. 如何在Django中配置MySQL数据库

    直接上图 在项目中直接找到settings 文件 第一步       原始Django自带数据库 第二步将配置改成MySQL的数据 第三步  在__init__文件中告知Django使用MySQL数据 ...

  7. python-shutil学习

    shutil:高级的 文件.文件夹.压缩包 处理模块 1. shutil.copyfileobj(fsrc, fdst[, length])(copyfileobj方法只会拷贝文件内容)将文件内容拷贝 ...

  8. Nginx配置详解(转)

    转自:Nginx简介及配置文件详解 一 Nginx简介 Nginx是一款开源代码的高性能HTTP服务器和反向代理服务器,同时支持IMAP/POP3/SMTP代理服务 1.Nginx工作原理 Nginx ...

  9. 设置SecureCRT的背景色和文字颜色方案

    一.对于临时设置,可以如下操作: 首先options -- session - appearance 此处可以设置临时的窗口背景,字体颜色,大小等等,为什么说是临时,是因为只要你关闭连接后,又会恢复. ...

  10. Jenkins Vue项目自动构建以及构建后续操作

    Jenkins在linux上的安装教程:http://www.ityouknow.com/springboot/2017/11/11/springboot-jenkins.html 另外,关于在win ...