一、what?
防抖 debounce 和節流 throttle 的概念並不是 JS 所特有的。它們是在對函數持續調用時進行不同控制的兩個概念。
1、防抖是爲了避免用戶無意間執行函數多次。比如有些用戶喜歡在點擊的時候使用 double click 雙擊,或者就是手抖連續點了兩下,這就可能會導致一些意想不到的問題。
2、節流就是連續觸發事件但是在n面中只執行一次函數。
二、why?
1、防抖-----優化用戶體驗:適時反饋,避免UI渲染阻塞,瀏覽器卡頓,提升頁面性能:避免頁面渲染卡頓,減少服務器壓力,防止惡意觸發
2、節流:節流會稀釋函數的執行頻率。
三、how?
1、防抖可以通過計時器來實現,通過setTimeout來指定一定時間後執行處理函數,如果在這之前事件再次觸發,則清空計時器,重新計時。
代碼:
簡單實現:
function debounce(){
let timerId=null;
return function(...args){
if(timerId)clearTimeout(timerId);
timerId=setTimeout(()=>{
fn.call(this,args);
},wait)
}
}
優化:
function debounce(fn,wait) {
let timerId=null;
let leadingTimerId=null;
return function(...args){
if(timerId){
clearTimeout(timerId);
clearTimeout(leadingTimerId);
timerId=setTimeout(()=>{
fn.call(this,false,args);
leadingTimerId=setTimeout(()=>{
timerId=null;
},wait)
},wait)
}else{
fn.call(this,true,args)
// 爲了解決只觸發一次,會同時觸發首次觸發和延時觸發的問題引入的特殊值
timerId=-1;
}
}
}
2、節流代碼實現:
時間戳:
function throttle(fn,wait){
let pre=0;
return function(){
let now=Date.now();
let _this=this
let args = arguments;
if(now-pre>wait){
fn.apply(_this,args)
pre=now
}
}
}
調用:
content.οnmοusemοve=throttle(count,1000);
定時器:
function throttle(func, wait) {
let timeout;
return function() {
let context = this;
let args = arguments;
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
調用:
content.οnmοusemοve=throttle(count,1000);