防抖和节流
处理频繁触发的事件时,如果没有进行限制,每次触发都调用处理函数进行处理不仅会浪费资源,还会降低用户体验,所以需要限制处理函数的调用频率,这便是用到防抖和节流的地方。
函数防抖
当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时。
函数防抖的一个典型应用场景是根据 input 的输入内容搜索相关信息,如果 input 内容每次改变都发起搜索请求,则会在短时间内发次多个请求,这种情况下,对事件处理函数进行防抖处理,在给定的时间段 T 内,input 内容没有改变,才发起搜索请求。
1 2 3 4 5 6 7 8 9 10
| function debounce(fn, wait) { let timeout = null; return function() { if (timeout !== null) { clearTimeOut(timeout); } timeout = setTimeOut(fn, wait); }; }
|
函数节流
当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
函数节流适合的处理的情况是更高频次的触发事件处理函数的情况,比如 resize、mousemove 、scroll 等,强制事件处理函数以固定频率执行。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| function throttle(fn, delay) { let prev = Date.now(); return function() { let context = this; let args = arguments; let now = Data.now(); if (now - prev >= delay) { fn.apply(context, args); prev = Date.now(); } }; }
function handler() {}
window.addEventListener('scroll', throttle(handler, 500))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function throttle(fn, delay) { let timer = null; return function() { let context = this; let args = arguments; if (!timer) { timer = setTimeOut(function() { fn.apply(context, args); timer = null; }, delay) } }; }
function handler() {}
window.addEventListener('scroll', throttle(handler, 500))
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function throttleFun(fun, duration) { let timer = null; let startT = Date.now(); return function() { const context = this; const args = arguments; const remaining = duration - ( startT - Date.now()); clearTimeout(timer); if (remaining <= 0) { fun.apply(context, args); startT = Date.now(); } else { timer = setTimeout(fun, remaining); } } }
|
防抖和节流的区别
防抖将几次操作合并为一次操作,节流则保证一段时间内只触发一次函数。
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。