JavaScript 防抖和節(jié)流
一潮孽、防抖
1-1 防抖基本概念
防抖具體指的是某個(gè)函數(shù)在某段時(shí)間內(nèi)揪荣,無(wú)論觸發(fā)了多少次回調(diào),都只執(zhí)行最后一次往史。假如我們?cè)O(shè)置了一個(gè)等待時(shí)間 3 秒的函數(shù)仗颈,在這 3 秒內(nèi)如果遇到函數(shù)調(diào)用請(qǐng)求就重新計(jì)時(shí) 3 秒,直至新的 3 秒內(nèi)沒(méi)有函數(shù)調(diào)用請(qǐng)求椎例,此時(shí)執(zhí)行函數(shù)挨决,不然就以此類推重新計(jì)時(shí)
1-2 防抖實(shí)現(xiàn)原理
防抖實(shí)現(xiàn)原理就是利用定時(shí)器,函數(shù)第一次執(zhí)行時(shí)設(shè)定一個(gè)定時(shí)器粟矿,并且通過(guò)閉包緩存起來(lái)凰棉,之后調(diào)用時(shí)發(fā)現(xiàn)已經(jīng)設(shè)定過(guò)定時(shí)器就清空之前的定時(shí)器,并重新設(shè)定一個(gè)新的定時(shí)器陌粹,如果存在沒(méi)有被清空的定時(shí)器撒犀,當(dāng)定時(shí)器計(jì)時(shí)結(jié)束后觸發(fā)函數(shù)執(zhí)行。
/*
* 防抖函數(shù)
* @param fn 事件觸發(fā)的操作
* @param delay 多少毫秒內(nèi)連續(xù)觸發(fā)事件,不會(huì)執(zhí)行
* @returns {Function}
*/
function debounce(fn,delay) {
let timer = null; //通過(guò)閉包緩存了一個(gè)定時(shí)器
return function () {
const args = [...arguments];
const that = this
timer && clearTimeout(timer);
timer = setTimeout(function () {
fn.apply(that,args);
},delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滾動(dòng)條位置:' + scrollTop);
},200)
二或舞、節(jié)流
2-1 節(jié)流基本概念
函數(shù)節(jié)流指的是某個(gè)函數(shù)在一定時(shí)間間隔內(nèi)(例如 3 秒)只執(zhí)行一次荆姆,在這 3 秒內(nèi) 無(wú)視后來(lái)產(chǎn)生的函數(shù)調(diào)用請(qǐng)求,也不會(huì)延長(zhǎng)時(shí)間間隔映凳。3 秒間隔結(jié)束后第一次遇到新的函數(shù)調(diào)用會(huì)觸發(fā)執(zhí)行胆筒,然后在這新的 3 秒內(nèi)依舊無(wú)視后來(lái)產(chǎn)生的函數(shù)調(diào)用請(qǐng)求,以此類推诈豌。函數(shù)節(jié)流非常適用于函數(shù)被頻繁調(diào)用的場(chǎng)景仆救,例如:window.onresize() 事件、mousemove 事件矫渔、上傳進(jìn)度等情況彤蔽。
2-2 節(jié)流實(shí)現(xiàn)原理
實(shí)現(xiàn)原理就是通過(guò)一個(gè)布爾類型變量來(lái)判斷是否可執(zhí)行回調(diào),當(dāng)變量為true時(shí)庙洼,生成一個(gè)定時(shí)器顿痪,同時(shí)將變量取反通過(guò)閉包保存起來(lái),當(dāng)定時(shí)器執(zhí)行完回調(diào)后油够,再將變量變?yōu)閠rue蚁袭,在變量為期false間,調(diào)用節(jié)流函數(shù)不會(huì)生成定時(shí)器石咬。
/**
* 節(jié)流函數(shù)
* @param fn 事件觸發(fā)的操作
* @param delay 間隔多少毫秒需要觸發(fā)一次事件
* @returns {Function}
*/
function throttle(fn, delay) {
let flag = true;
return function () {
if (!flag) {
return;
}
const that = this
const args = [...arguments];
flag = false;
setTimeout(() => {
fn.apply(that, args);
flag = true;
}, delay);
}
}
window.onscroll = debounce(function () {
let scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滾動(dòng)條位置:' + scrollTop);
},200)
三揩悄、使用場(chǎng)景
在一些高頻率事件觸發(fā)的場(chǎng)景下我們不希望對(duì)應(yīng)的事件處理函數(shù)多次執(zhí)行的時(shí)候,可以使用防抖和節(jié)流碌补,比如:
- 滾動(dòng)事件
- 輸入的模糊搜索
- 輪播圖切換
- 點(diǎn)擊操作......
瀏覽器默認(rèn)情況下都會(huì)有自己的監(jiān)聽時(shí)間間隔(以谷歌瀏覽器為例虏束,大概在4-6毫秒,就會(huì)去監(jiān)聽一下事件是否有發(fā)生)厦章,如果檢測(cè)到多次事件的監(jiān)聽執(zhí)行镇匀,那么就會(huì)造成不必要的資源浪費(fèi))