以下场景往往由于事件频繁被触发,因而频繁执行DOM操作、资源加载等重行为,导致UI停顿甚至浏览器崩溃。

1. window对象的resize、scroll事件

2. 拖拽时的mousemove事件

3. 射击游戏中的mousedown、keydown事件

4. 文字输入、自动完成的keyup/keypress事件

实际上对于window的resize事件,实际需求大多为停止改变大小n毫秒后执行后续处理;而其他事件大多的需求是以一定的频率执行后续处理。针对这两种需求就出现了debounce和throttle两种解决办法。

一、什么是debounce

1、定义:

如果用手指一直按住一个弹簧,它将不会弹起直到你松手为止。

也就是说当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。

接口定义:

/**
* 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 idle,fn 才会执行
* @param fn {function} 请求关联函数,实际应用需要调用的函数
* @param delay {number} 空闲时间,单位毫秒
* @return {function} 返回客户调用函数
*/
debounce(fn,delay)

2、简单实现:

/**
*
* @param fn {Function} 实际要执行的函数
* @param delay {Number} 延迟时间,也就是阈值,单位是毫秒(ms)
*
* @return {Function} 返回一个“去弹跳”了的函数
*/ function debounce(fn, delay) { // 定时器,用来 setTimeout
var timer // 返回一个函数,这个函数会在一个时间区间结束后的 delay 毫秒时执行 fn 函数
return function () { // 保存函数调用时的上下文和参数,传递给 fn
var context = this
var args = arguments // 每次这个返回的函数被调用,就清除定时器,以保证不执行 fn
clearTimeout(timer) // 当返回的函数被最后一次调用后(也就是用户停止了某个连续的操作),
// 再过 delay 毫秒就执行 fn
timer = setTimeout(function () {
fn.apply(context, args)
}, delay)
}
}

其实思路很简单,debounce 返回了一个闭包,这个闭包依然会被连续频繁地调用,但是在闭包内部,却限制了原始函数 fn 的执行,强制 fn 只在连续操作停止后只执行一次。

debounce 的使用方式如下:

$(document).on('mouvemove', debounce(function(e) {
// 代码
}, ))
$('input').on('keyup', debounce(function(e) {
// 发送 ajax 请求
}, ))

二、什么是throttle

1、定义

如果将水龙头拧紧直到水是以水滴的形式流出,那你会发现每隔一段时间,就会有一滴水流出。

  也就是说预先规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某个事件被触发多次,只有一次能生效。

接口定义:

/**
* 频率控制 返回函数连续调用时,action 执行频率限定为 次 / delay
* @param delay {number} 延迟时间,单位毫秒
* @param action {function} 请求关联函数,实际应用需要调用的函数
* @return {function} 返回客户调用函数
*/
throttle(delay,action)

2、简单实现

/**
*
* @param fn {Function} 实际要执行的函数
* @param delay {Number} 执行间隔,单位是毫秒(ms)
*
* @return {Function} 返回一个“节流”函数
*/
function throttle(fn, threshhold) { // 记录上次执行的时间
var last // 定时器
var timer // 默认间隔为 250ms
threshhold || (threshhold = ) // 返回的函数,每过 threshhold 毫秒就执行一次 fn 函数
return function () { // 保存函数调用时的上下文和参数,传递给 fn
var context = this
var args = arguments var now = +new Date() // 如果距离上次执行 fn 函数的时间小于 threshhold,那么就放弃
// 执行 fn,并重新计时
if (last && now < last + threshhold) {
clearTimeout(timer) // 保证在当前时间区间结束后,再执行一次 fn
timer = setTimeout(function () {
last = now
fn.apply(context, args)
}, threshhold)
// 在时间区间的最开始和到达指定间隔的时候执行一次 fn
} else {
last = now
fn.apply(context, args)
}
}
}

原理也不复杂,相比 debounce,无非是多了一个时间间隔的判断,其他的逻辑基本一致。throttle 的使用方式如下:

$(document).on('mouvemove', throttle(function(e) {
// 代码
}, ))

throttle 常用的场景是限制 resize 和 scroll 的触发频率

总结:

debounce 强制函数在某段时间内只执行一次,throttle 强制函数以固定的速率执行。在处理一些高频率触发的 DOM 事件的时候,它们都能极大提高用户体验。

函数去抖(debounce)与 函数节流(throttle)的更多相关文章

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

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

  2. “浅入浅出”函数防抖(debounce)与节流(throttle)

    函数防抖与节流是日常开发中经常用到的技巧,也是前端面试中的常客,但是发现自己工作一年多了,要么直接复用已有的代码或工具,要么抄袭<JS高级程序设计>书中所述"函数节流" ...

  3. (转)JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)

     JavaScript-性能优化之函数节流(throttle)与函数去抖(debounce)         函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过 ...

  4. JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)

    函数节流,简单地讲,就是让一个函数无法在很短的时间间隔内连续调用,只有当上一次函数执行后过了你规定的时间间隔,才能进行下一次该函数的调用. 函数节流的原理挺简单的,估计大家都想到了,那就是定时器.当我 ...

  5. JavaScript函数节流(throttle)与函数去抖(debounce)

    对于浏览器窗口大小改变的时候,来动态改变页面元素的大小,可以采用window的resize事件,实现代码: <script type="text/javascript"> ...

  6. JavaScript-性能优化,函数节流(throttle)与函数去抖(debounce)

    我在写一个类似百度搜索框的自动提示功能时候,使用了AJAX+keydown事件.调试时候我发现,当在搜索框中输入文字的时候,控制台在不停发送AJAX.这在本地服务器测试还好,如果我把它拿到运行环境,很 ...

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

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

  8. JavaScript函数节流与函数去抖

    介绍 首先解释一下这两个概念: 函数节流(throttle):是让一个函数无法在很短的时间间隔内连续调用,当上一次函数执行后过了规定的时间间隔,才能进行下一次该函数的调用. 函数去抖(debounce ...

  9. javascript中的函数节流和函数去抖

    带着问题去尝试 首先我们要知道为什么要用到函数节流和函数去抖?我们带着以下的疑问来进行分析! 1.比如搜索框,你会用到什么事件(change.blur.keyup等)?去做什么效果?2.再比如scro ...

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

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

随机推荐

  1. 【OpenCV】邻域滤波:方框、高斯、中值、双边滤波

    原文:http://blog.csdn.net/xiaowei_cqu/article/details/7785365 邻域滤波(卷积)   邻域算子值利用给定像素周围像素的值决定此像素的最终输出.如 ...

  2. Linq学习以及简单用法

    Linq学习 Linq(language Intergrated Query)即语言集成查询 LINQ是一组语言特性和API,使得你可以使用统一的方式编写各种查询.用于保存和检索来自不同数据源的数据, ...

  3. jQuery 表格中实现“删除线”的增进方法

    之前做了一个删除线的效果,就是类似这样的,在内容的中间加一条线. 但是又有点不同的是,这种删除线不是单纯的在文字之上,而是给一个Table中的一行加上这种删除线效果. 这里有两个方法,是在不同时期写的 ...

  4. 六、阻塞队列LinkedBlockQueue

    一.简介 Java提供了FIFO先进先出的阻塞队列实现,这其实是一种生产者消费者理念,可以通过阻塞队列将生产者和消费者进行解耦合. LinkedBlockQueue是一种无界队列,但事实上它只是队列可 ...

  5. poj 2417 Discrete Logging ---高次同余第一种类型。babystep_gaint_step

    Discrete Logging Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 2831   Accepted: 1391 ...

  6. BZOJ3193: [JLOI2013]地形生成

    传送门 Sol 第一问可以考虑按照山的高度从大到小放 但是这样如果遇到高度相同的就不好考虑,那么同时要求数量限制从小到大 这样每次放的时候后面的一定不会影响前面,并且高度相同的时候前面能放的位置后面的 ...

  7. 使用javascript调用android代码

    1.使用webview对象的addJavascriptInterface方法 2.addJavascriptInterface方法有两个参数,第一个参数就是我们一般会实现一个自己的类,类里面提供我们要 ...

  8. react打包开发文件的步骤(上传给线上环境)

    cd进入ReleaseProject目录,然后运行npm start,系统会自动在public目录下面完成打包工作,然后我再把  public文件下压缩位public.rar上传即可:(public文 ...

  9. Jquery插件 “IT小鲜肉 Tree”,猛烈完善中

    今天又给Jquery插件“IT小鲜肉 Tree”添加了自定义图标.自定义标签显示功能:目前“IT小鲜肉 Tree”已经具备有checkbox.drag and drop 等基本功能. 废话不说,直接上 ...

  10. CentOS配置multipath

    可以通过2种方式查看HBA的WWN信息: 1. 查看sys文件系统 查看HBA卡型号:[root@localhost ~]# lspci  | grep -i fibre13:00.0 Fibre C ...