函数节流之debounce
Posted llcdxh
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了函数节流之debounce相关的知识,希望对你有一定的参考价值。
浏览器中某些计算和处理要比其他的昂贵很多。例如, DOM 操作比起非 DOM 交互需要更多的内存和 CPU 时间。连续尝试进行过多的 DOM 相关操作可能会导致浏览器挂起,有时候甚至会崩溃。尤其在 IE 中使用 onresize 事件处理程序的时候容易发生,当调整浏览器大小的时候,该事件会连续触发。在 onresize 事件处理程序内部如果尝试进行 DOM 操作,其高频率的更改可能会让浏览器崩溃。为了绕开这个问题,你可以使用定时器对该函数进行节流。
函数节流背后的基本思想是指,某些代码不可以在没有间断的情况连续重复执行。第一次调用函数,创建一个定时器,在指定的时间间隔之后运行代码。当第二次调用该函数时,它会清除前一次的定时器并设置另一个 (摘录至javascript高级程序设计的函数节流)。
适用的应用场景:
1、window对象的resize、scroll事件
2、拖拽时的mousemove事件
3、射击游戏中的mousedown、keydown事件
4、文字输入、自动完成的keyup事件
1 /** 2 * 函数去抖,保证在一段时间内,被调用函数只是执行一次 3 * @param {*} func 调用用的函数,function 4 * @param {*} wait 等待的时间,单位ms 5 * @param {*} immediate 当immediate为true时,第一次调用该函数的时候,就调用func函数;false表示超时之后再调用 6 */ 7 export function debounce (func, wait, immediate = false) { 8 let timeout, args, context, timestamp, result 9 10 const later = function () { 11 // 记录上一次触发时间间隔 12 const last = +new Date() - timestamp 13 14 // 上次被包装函数被调用时间间隔last小于设定时间间隔wait 15 // 调用的时间比较频繁,重新计算下次执行的时间 16 if (last < wait && last > 0) { 17 timeout = setTimeout(later, wait - last) 18 } else { 19 timeout = null 20 // 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用 21 if (!immediate) { 22 result = func.apply(context, args) 23 if (!timeout) context = args = null 24 } 25 } 26 } 27 28 // ...args:使用es6的rest运算符,把逗号隔开的值序列组合成一个数组:如test(1,2,3,4) ==> args:[1,2,3,4] 29 // 符合apply(obj,[]) 30 return function (...args) { 31 // 把上下文的this对象保存下来,因为下面的apply要使用 32 context = this 33 // 记录当前的时间戳,也可以使用Date.now() 34 timestamp = +new Date() 35 // 第一次调用该方法时,且immediate为true,则调用func函数 36 const callNow = immediate && !timeout 37 // 如果延时不存在,重新设定延时,首次的时候 38 if (!timeout) { 39 timeout = setTimeout(later, wait) 40 } 41 // 如果immediate为true,那么立马调用该函数 42 if (callNow) { 43 result = func.apply(context, args) 44 context = args = null 45 } 46 47 return result 48 } 49 }
以上是关于函数节流之debounce的主要内容,如果未能解决你的问题,请参考以下文章
JavaScript函数节流(throttle)与函数去抖(debounce)
43.Vue中使用Lodash 节流(throttle)和防抖(debounce)函数