一个使用场景:
某些浏览器事件可能会在短期内高频触发,好比:整窗口大小或滚动页面。
若是给窗口滚动事件添加一个事件监听器,而后用户不停地快速滚动页面,那你的事件可能在短短数秒以内被触发数千次。这会致使很是严重的性能问题。
因此若是功能涉及滚动事件,窗口调整事件,或者键盘事件鼠标事件等,你可能须要警觉起来,是否有必要使用 debouncing 或者 throttling 来提升页面速度与性能。git
debouncing(防抖动)是解决上述问题的一个方案,它的作法是 限制下次函数调用以前必须等待的时间间隔,也就是说:强制一个函数在某个连续时间段内只执行一次,哪怕它原本会被调用屡次。正确实现 debouncing 的方法是:将若干个函数调用合并为一次,只有在空闲时间大于或等于给定值的时候,才执行调用方法。github
简单的实现一个 debounce
方法,接收两个参数,一个是须要防抖动的函数 fn
,另外一个是延迟时间delay
浏览器
funciton debouncing(fn, delay) { let timer; //定时器 return function() { // 保存函数调用时的上下文和参数,传递给 fn const context = this; const args = arguments; clearTimeout(timer); timer = setTimeout(function(){ fn.apply(context, args); }, delay); } }
该 debounce
的使用方法以下:app
$(document).on('keyup', debounce(function(e) { // 代码 }, 250))
throttling(节流阀)则是另外一种解决问题的方案,它的作法是固定一段时间内函数调用的频率,它与 debouncing 最大的不一样之处在于,throttling 会保证至少调用一次。函数
与 debounce
相似,接收两个参数,一个是须要截流的函数 fn
, 另外一个是函数执行间隔阈值 threshhold
。性能
function throttle(fn, threshhold) { let timer; //定时器 let last; //记录上次时间 threshhold || (threshhold = 250); //默认间隔为250ms return function() { // 保存函数调用时的上下文和参数,传递给 fn var context = this; var args = arguments; let now = +new Date(); // 若是上次调用距本次调用的时间间隔不够,则不执行 fn,并从新计时 if(last && now < last + threshhold){ clearTimeout(timer); // 保证在当前时间区间结束后,再执行一次 fn timer = setTimeout({ last = now; fn.apply(context, args); }, threshhold); } else { //若是时间间隔够了,则马上执行 fn last = now; fn.apply(context, args); } }
throttle
使用方法以下:this
$(document).on('mouvemove', throttle(function(e) { // 代码 }, 250))
debouncing 和 throttling 的区别仍是很明显的:前者把一段时间的屡次调用合并成一次,后者把一段时间的屡次调用减小为数次。下图的展现十分便于理解。spa
相关文章:
实例解析防抖动(Debouncing)和节流阀(Throttling)code