淺談JavaScript中的防抖和節(jié)流
什么是防抖和節(jié)流?
在 JavaScript 中,防抖(debounce)和節(jié)流(throttle)是用來限制函數(shù)執(zhí)行頻率的兩種常見技術(shù)。
防抖(debounce) 是指在某個(gè)時(shí)間段內(nèi),只執(zhí)行最后一次觸發(fā)的函數(shù)調(diào)用。如果在這個(gè)時(shí)間段內(nèi)再次觸發(fā)該函數(shù),會(huì)重新計(jì)時(shí),直到等待時(shí)間結(jié)束才會(huì)執(zhí)行函數(shù)。 這個(gè)技術(shù)通常用于處理頻繁觸發(fā)的事件,比如窗口大小調(diào)整、搜索框輸入等。防抖可以避免函數(shù)執(zhí)行過多次,以減少網(wǎng)絡(luò)開銷和性能負(fù)擔(dān)。
節(jié)流(throttle) 是指在一段時(shí)間內(nèi)限制函數(shù)的執(zhí)行頻率,保證一定時(shí)間內(nèi)只執(zhí)行一次函數(shù)調(diào)用。無論觸發(fā)頻率多高,都會(huì)在指定時(shí)間間隔內(nèi)執(zhí)行一次函數(shù)。 這個(gè)技術(shù)通常用于處理連續(xù)觸發(fā)的事件,比如滾動(dòng)事件、鼠標(biāo)移動(dòng)事件等。節(jié)流可以控制函數(shù)的執(zhí)行頻率,以減少資源消耗和提高性能。
手寫一個(gè)防抖的工具函數(shù)
function debounce(func, delay) {
let timeoutId;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeoutId);
timeoutId = setTimeout(function() {
func.apply(context, args);
}, delay);
};
}函數(shù)說明
- 這個(gè)防抖函數(shù)接受兩個(gè)參數(shù):
func表示需要進(jìn)行防抖的函數(shù),delay表示延遲的時(shí)間間隔(以毫秒為單位) - 函數(shù)內(nèi)部使用了一個(gè)
timeoutId變量來保存定時(shí)器的標(biāo)識(shí)。當(dāng)調(diào)用防抖函數(shù)返回的新函數(shù)時(shí),會(huì)清除之前的定時(shí)器,并設(shè)置一個(gè)新的定時(shí)器。只有在延遲時(shí)間內(nèi)沒有再次調(diào)用該新函數(shù)時(shí),才會(huì)觸發(fā)最終的函數(shù)執(zhí)行
使用示例
該示例表示在全局滾動(dòng)事件中使用防抖函數(shù),每200毫秒內(nèi)如果觸發(fā)滾動(dòng)事件,那么不會(huì)執(zhí)行handleScroll()函數(shù)。 然后重新計(jì)時(shí)200毫秒,再次判斷,直到最后一個(gè)200毫秒內(nèi)沒有觸發(fā)滾動(dòng)事件,才會(huì)執(zhí)行handleScroll()函數(shù)
function handleScroll() {
console.log('Scrolled');
}
const debouncedScroll = debounce(handleScroll, 200);
window.addEventListener('scroll', debouncedScroll);手寫一個(gè)節(jié)流的工具函數(shù)
function throttle(func, delay) {
let timeoutId;
let lastExecTime = 0;
return function(...args) {
const currentTime = Date.now();
const remainingTime = delay - (currentTime - lastExecTime);
clearTimeout(timeoutId);
if (remainingTime <= 0) {
func.apply(this, args);
lastExecTime = currentTime;
} else {
timeoutId = setTimeout(() => {
func.apply(this, args);
lastExecTime = Date.now();
}, remainingTime);
}
};
}函數(shù)說明
- 這個(gè)節(jié)流函數(shù)接受兩個(gè)參數(shù):
func是要執(zhí)行的函數(shù),delay是延遲時(shí)間(以毫秒為單位) - 它返回一個(gè)新的函數(shù),該函數(shù)在調(diào)用時(shí)會(huì)根據(jù)指定的延遲時(shí)間來限制原始函數(shù)的執(zhí)行頻率
使用示例
在全局滾動(dòng)事件中使用節(jié)流函數(shù),無論在滾動(dòng)事件的監(jiān)聽過程中,觸發(fā)了幾次handleScroll()函數(shù),都只會(huì)在每200毫秒內(nèi)執(zhí)行一次handleScroll()函數(shù)。
function handleScroll() {
console.log('Scrolled');
}
const throttledScroll = throttle(handleScroll, 200);
window.addEventListener('scroll', throttledScroll);如何在工作中應(yīng)用防抖和節(jié)流
防抖和節(jié)流主要應(yīng)用于:搜索框輸入事件監(jiān)聽、窗口大小調(diào)整事件監(jiān)聽、按鈕點(diǎn)擊事件監(jiān)聽、滾動(dòng)事件監(jiān)聽、鼠標(biāo)移動(dòng)事件監(jiān)聽等等場(chǎng)景。
工作中哪些場(chǎng)景可以使用防抖函數(shù)?
- 用戶輸入: 當(dāng)用戶在表單輸入框中頻繁輸入時(shí),可以使用防抖函數(shù)來延遲處理用戶輸入,避免頻繁的請(qǐng)求或操作,提高性能和用戶體驗(yàn)。
- 搜索框: 在搜索框中,當(dāng)用戶連續(xù)輸入關(guān)鍵字時(shí),可以使用防抖函數(shù)來延遲發(fā)送搜索請(qǐng)求,以避免請(qǐng)求過多。
- 窗口調(diào)整: 當(dāng)窗口大小調(diào)整時(shí),會(huì)觸發(fā)resize事件,可以使用防抖函數(shù)來限制resize事件的觸發(fā)次數(shù),避免頻繁執(zhí)行調(diào)整相關(guān)的代碼。
- 按鈕頻繁點(diǎn)擊: 當(dāng)按鈕被頻繁點(diǎn)擊時(shí),可以使用防抖函數(shù)來限制按鈕點(diǎn)擊的觸發(fā)次數(shù)。
工作中哪些場(chǎng)景可以使用節(jié)流函數(shù)?
- 用戶輸入: 當(dāng)用戶在文本框中輸入時(shí),觸發(fā)搜索功能。使用節(jié)流函數(shù)可以限制搜索請(qǐng)求的頻率,以避免頻繁的網(wǎng)絡(luò)請(qǐng)求。例如,可以設(shè)置一個(gè)定時(shí)器,在用戶輸入后的一小段時(shí)間內(nèi)不觸發(fā)搜索請(qǐng)求,只在定時(shí)器結(jié)束后才進(jìn)行搜索。
- 無限加載: 當(dāng)用戶滾動(dòng)頁面時(shí),觸發(fā)加載更多數(shù)據(jù)的操作。使用節(jié)流函數(shù)可以限制加載操作的頻率,以提高頁面的響應(yīng)性能。例如,可以設(shè)置一個(gè)定時(shí)器,在用戶滾動(dòng)過程中只觸發(fā)加載操作的最后一次滾動(dòng)事件。
- 按鈕頻繁點(diǎn)擊: 當(dāng)用戶頻繁點(diǎn)擊某個(gè)按鈕時(shí),觸發(fā)某個(gè)操作。使用節(jié)流函數(shù)可以限制點(diǎn)擊操作的頻率,以避免重復(fù)操作或者混亂的界面狀態(tài)。例如,可以設(shè)置一個(gè)定時(shí)器,在用戶點(diǎn)擊后的一小段時(shí)間內(nèi)不觸發(fā)重復(fù)操作。
如何使用loadsh.js工具庫中的防抖和節(jié)流函數(shù)
實(shí)際開發(fā)過程中,我們的項(xiàng)目中可能會(huì)直接使用loadsh.js工具庫,來避免重復(fù)造輪子,所以這里也特地說明一下如何使用loadsh.js工具庫中的防抖和節(jié)流函數(shù)
- 安裝
loadsh.js工具庫
npm install lodash
- 在項(xiàng)目中引入
loadsh.js工具庫,不同前端項(xiàng)目引入方式不同,請(qǐng)自行鑒別
import { debounce, throttle } from 'loadsh';- 使用防抖函數(shù),該示例中,
submitData()函數(shù)被限制為每1秒只會(huì)執(zhí)行最后一次,如果在等待時(shí)間內(nèi)多次調(diào)用該函數(shù),則會(huì)重置1秒的等待時(shí)間
// 定義要延遲執(zhí)行的函數(shù)
function submitData(data) {
console.log('保存數(shù)據(jù):', data);
}
// 使用debounce函數(shù)創(chuàng)建一個(gè)延遲執(zhí)行的函數(shù)
const debouncedFn = _.debounce(submitData, 1000);
// 模擬連續(xù)觸發(fā)保存數(shù)據(jù)的操作
// 等待1秒后,只會(huì)執(zhí)行最后一次保存數(shù)據(jù)的操作
debouncedFn('數(shù)據(jù)1'); // 不會(huì)輸出
debouncedFn('數(shù)據(jù)2'); // 不會(huì)輸出
debouncedFn('數(shù)據(jù)3'); // 輸出 —— 保存數(shù)據(jù):數(shù)據(jù)3- 使用節(jié)流函數(shù),該示例中,
throttledFn()函數(shù)被限制為每秒只能執(zhí)行一次,如果在等待時(shí)間內(nèi)多次調(diào)用該函數(shù),則不會(huì)執(zhí)行
// 定義要減少調(diào)用次數(shù)的函數(shù)
function fetchData(data) {
console.log('拉取數(shù)據(jù):', data);
}
// 使用throttle函數(shù)創(chuàng)建一個(gè)定時(shí)執(zhí)行的函數(shù)
const throttledFn = _.throttle(fetchData, 2000);
// 調(diào)用throttledFn函數(shù)
throttledFn('數(shù)據(jù)1'); // 輸出 —— 拉取數(shù)據(jù): 數(shù)據(jù)1
// 在1秒內(nèi)多次調(diào)用throttledFn函數(shù)
throttledFn('數(shù)據(jù)2'); // 不會(huì)輸出
// 2秒后再次調(diào)用throttledFn函數(shù)
setTimeout(() => {
throttledFn('數(shù)據(jù)3'); // 輸出 —— 拉取數(shù)據(jù): 數(shù)據(jù)3
}, 1000);以上就是淺談JavaScript中的防抖和節(jié)流的詳細(xì)內(nèi)容,更多關(guān)于JavaScript防抖節(jié)流的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
- JS中的防抖與節(jié)流及作用詳解
- JS函數(shù)節(jié)流和函數(shù)防抖問題分析
- 關(guān)于JavaScript防抖與節(jié)流的區(qū)別與實(shí)現(xiàn)
- 如何解決js函數(shù)防抖、節(jié)流出現(xiàn)的問題
- js防抖和節(jié)流的深入講解
- 什么是JavaScript的防抖與節(jié)流
- JavaScript中防抖和節(jié)流的區(qū)別及適用場(chǎng)景
- JavaScript 防抖和節(jié)流遇見的奇怪問題及解決
- JS防抖和節(jié)流實(shí)例解析
- 通過代碼實(shí)驗(yàn)演示js的防抖與節(jié)流(超詳細(xì)解釋)
相關(guān)文章
琥珀無限級(jí)聯(lián)動(dòng)菜單-JavaScript版
琥珀無限級(jí)聯(lián)動(dòng)菜單-JavaScript版...2006-11-11
JavaScript 模塊化語法 import、export示例詳解
ES6 模塊化 (import / export) 是 JavaScript 官方推薦的模塊化方案,解決了 代碼復(fù)用、作用域管理、依賴管理 等問題,本文給大家介紹了JavaScript 模塊化語法 import、export示例代碼,感興趣的朋友一起看看吧2025-04-04
js小數(shù)運(yùn)算出現(xiàn)多位小數(shù)如何解決
關(guān)于JavaScript小數(shù)進(jìn)行加、減、乘、除出現(xiàn)多位小數(shù)問題,自己研究了一下,而且作了相關(guān)的測(cè)試,收獲不少知識(shí)點(diǎn),需要的朋友可以參考下2015-10-10
微信小程序使用radio顯示單選項(xiàng)功能【附源碼下載】
這篇文章主要介紹了微信小程序使用radio顯示單選項(xiàng)功能,涉及針對(duì)radio組件事件響應(yīng)相關(guān)操作技巧,并附帶源碼供讀者下載參考,需要的朋友可以參考下2017-12-12
js字符串轉(zhuǎn)json的三種簡(jiǎn)單方法舉例
在很多時(shí)候我們都需要將數(shù)據(jù)轉(zhuǎn)換為JSON的格式去進(jìn)行請(qǐng)求,下面這篇文章主要給大家介紹了關(guān)于js字符串轉(zhuǎn)json的三種簡(jiǎn)單方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-04-04
JS結(jié)合WebSocket實(shí)現(xiàn)實(shí)時(shí)雙向通信
WebSocket 是一種在 Web 應(yīng)用程序中實(shí)現(xiàn)實(shí)時(shí)、雙向通信的協(xié)議,在本文中,我們將深入介紹 WebSocket 的原理、用法以及一些實(shí)際應(yīng)用場(chǎng)景,x需要的可以參考下2023-11-11
JS中超越現(xiàn)實(shí)的匿名函數(shù)用法實(shí)例分析
這篇文章主要介紹了JS中超越現(xiàn)實(shí)的匿名函數(shù)用法,結(jié)合實(shí)例形式分析了javascript匿名函數(shù)定義、用法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2019-06-06

