淺談JavaScript中的防抖和節(jié)流
什么是防抖和節(jié)流?
在 JavaScript 中,防抖(debounce)和節(jié)流(throttle)是用來限制函數(shù)執(zhí)行頻率的兩種常見技術(shù)。
防抖(debounce) 是指在某個時間段內(nèi),只執(zhí)行最后一次觸發(fā)的函數(shù)調(diào)用。如果在這個時間段內(nèi)再次觸發(fā)該函數(shù),會重新計時,直到等待時間結(jié)束才會執(zhí)行函數(shù)。 這個技術(shù)通常用于處理頻繁觸發(fā)的事件,比如窗口大小調(diào)整、搜索框輸入等。防抖可以避免函數(shù)執(zhí)行過多次,以減少網(wǎng)絡(luò)開銷和性能負擔。
節(jié)流(throttle) 是指在一段時間內(nèi)限制函數(shù)的執(zhí)行頻率,保證一定時間內(nèi)只執(zhí)行一次函數(shù)調(diào)用。無論觸發(fā)頻率多高,都會在指定時間間隔內(nèi)執(zhí)行一次函數(shù)。 這個技術(shù)通常用于處理連續(xù)觸發(fā)的事件,比如滾動事件、鼠標移動事件等。節(jié)流可以控制函數(shù)的執(zhí)行頻率,以減少資源消耗和提高性能。
手寫一個防抖的工具函數(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ù)說明
- 這個防抖函數(shù)接受兩個參數(shù):
func
表示需要進行防抖的函數(shù),delay
表示延遲的時間間隔(以毫秒為單位) - 函數(shù)內(nèi)部使用了一個
timeoutId
變量來保存定時器的標識。當調(diào)用防抖函數(shù)返回的新函數(shù)時,會清除之前的定時器,并設(shè)置一個新的定時器。只有在延遲時間內(nèi)沒有再次調(diào)用該新函數(shù)時,才會觸發(fā)最終的函數(shù)執(zhí)行
使用示例
該示例表示在全局滾動事件中使用防抖函數(shù),每200毫秒內(nèi)如果觸發(fā)滾動事件,那么不會執(zhí)行handleScroll()
函數(shù)。 然后重新計時200毫秒,再次判斷,直到最后一個200毫秒內(nèi)沒有觸發(fā)滾動事件,才會執(zhí)行handleScroll()
函數(shù)
function handleScroll() { console.log('Scrolled'); } const debouncedScroll = debounce(handleScroll, 200); window.addEventListener('scroll', debouncedScroll);
手寫一個節(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ù)說明
- 這個節(jié)流函數(shù)接受兩個參數(shù):
func
是要執(zhí)行的函數(shù),delay
是延遲時間(以毫秒為單位) - 它返回一個新的函數(shù),該函數(shù)在調(diào)用時會根據(jù)指定的延遲時間來限制原始函數(shù)的執(zhí)行頻率
使用示例
在全局滾動事件中使用節(jié)流函數(shù),無論在滾動事件的監(jiān)聽過程中,觸發(fā)了幾次handleScroll()
函數(shù),都只會在每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)聽、按鈕點擊事件監(jiān)聽、滾動事件監(jiān)聽、鼠標移動事件監(jiān)聽等等場景。
工作中哪些場景可以使用防抖函數(shù)?
- 用戶輸入: 當用戶在表單輸入框中頻繁輸入時,可以使用防抖函數(shù)來延遲處理用戶輸入,避免頻繁的請求或操作,提高性能和用戶體驗。
- 搜索框: 在搜索框中,當用戶連續(xù)輸入關(guān)鍵字時,可以使用防抖函數(shù)來延遲發(fā)送搜索請求,以避免請求過多。
- 窗口調(diào)整: 當窗口大小調(diào)整時,會觸發(fā)resize事件,可以使用防抖函數(shù)來限制resize事件的觸發(fā)次數(shù),避免頻繁執(zhí)行調(diào)整相關(guān)的代碼。
- 按鈕頻繁點擊: 當按鈕被頻繁點擊時,可以使用防抖函數(shù)來限制按鈕點擊的觸發(fā)次數(shù)。
工作中哪些場景可以使用節(jié)流函數(shù)?
- 用戶輸入: 當用戶在文本框中輸入時,觸發(fā)搜索功能。使用節(jié)流函數(shù)可以限制搜索請求的頻率,以避免頻繁的網(wǎng)絡(luò)請求。例如,可以設(shè)置一個定時器,在用戶輸入后的一小段時間內(nèi)不觸發(fā)搜索請求,只在定時器結(jié)束后才進行搜索。
- 無限加載: 當用戶滾動頁面時,觸發(fā)加載更多數(shù)據(jù)的操作。使用節(jié)流函數(shù)可以限制加載操作的頻率,以提高頁面的響應(yīng)性能。例如,可以設(shè)置一個定時器,在用戶滾動過程中只觸發(fā)加載操作的最后一次滾動事件。
- 按鈕頻繁點擊: 當用戶頻繁點擊某個按鈕時,觸發(fā)某個操作。使用節(jié)流函數(shù)可以限制點擊操作的頻率,以避免重復(fù)操作或者混亂的界面狀態(tài)。例如,可以設(shè)置一個定時器,在用戶點擊后的一小段時間內(nèi)不觸發(fā)重復(fù)操作。
如何使用loadsh.js工具庫中的防抖和節(jié)流函數(shù)
實際開發(fā)過程中,我們的項目中可能會直接使用loadsh.js
工具庫,來避免重復(fù)造輪子,所以這里也特地說明一下如何使用loadsh.js
工具庫中的防抖和節(jié)流函數(shù)
- 安裝
loadsh.js
工具庫
npm install lodash
- 在項目中引入
loadsh.js
工具庫,不同前端項目引入方式不同,請自行鑒別
import { debounce, throttle } from 'loadsh';
- 使用防抖函數(shù),該示例中,
submitData()
函數(shù)被限制為每1秒只會執(zhí)行最后一次,如果在等待時間內(nèi)多次調(diào)用該函數(shù),則會重置1秒的等待時間
// 定義要延遲執(zhí)行的函數(shù) function submitData(data) { console.log('保存數(shù)據(jù):', data); } // 使用debounce函數(shù)創(chuàng)建一個延遲執(zhí)行的函數(shù) const debouncedFn = _.debounce(submitData, 1000); // 模擬連續(xù)觸發(fā)保存數(shù)據(jù)的操作 // 等待1秒后,只會執(zhí)行最后一次保存數(shù)據(jù)的操作 debouncedFn('數(shù)據(jù)1'); // 不會輸出 debouncedFn('數(shù)據(jù)2'); // 不會輸出 debouncedFn('數(shù)據(jù)3'); // 輸出 —— 保存數(shù)據(jù):數(shù)據(jù)3
- 使用節(jié)流函數(shù),該示例中,
throttledFn()
函數(shù)被限制為每秒只能執(zhí)行一次,如果在等待時間內(nèi)多次調(diào)用該函數(shù),則不會執(zhí)行
// 定義要減少調(diào)用次數(shù)的函數(shù) function fetchData(data) { console.log('拉取數(shù)據(jù):', data); } // 使用throttle函數(shù)創(chuàng)建一個定時執(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'); // 不會輸出 // 2秒后再次調(diào)用throttledFn函數(shù) setTimeout(() => { throttledFn('數(shù)據(jù)3'); // 輸出 —— 拉取數(shù)據(jù): 數(shù)據(jù)3 }, 1000);
以上就是淺談JavaScript中的防抖和節(jié)流的詳細內(nèi)容,更多關(guān)于JavaScript防抖節(jié)流的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JavaScript加入收藏夾功能(兼容IE、firefox、chrome)
這篇文章主要介紹了JavaScript加入收藏夾功能,兼容IE、firefox、chrome,并解決了window.sidebar.addPanel is not a function問題,需要的朋友可以參考下2014-05-05JS圖片延遲加載插件LazyImgv1.0用法分析【附demo源碼下載】
這篇文章主要介紹了JS圖片延遲加載插件LazyImgv1.0用法,結(jié)合實例形式分析了使用圖片延遲加載插件LazyImgv1.0的注意事項與核心操作技巧,并附帶demo源碼供讀者下載參考,需要的朋友可以參考下2017-09-09js實現(xiàn)select二級聯(lián)動下拉菜單
這個是簡單也是最基本的下拉框聯(lián)動的示例,這個示例主要針對那些只有二級聯(lián)動,且第一級是固定的選項,第二級的內(nèi)容也比較簡單,不刷新的聯(lián)動,感興趣的小伙伴們可以參考一下2016-04-04JavaScript數(shù)據(jù)結(jié)構(gòu)與算法之檢索算法實例分析【順序查找、最大最小值、自組織查詢】
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)與算法之檢索算法,結(jié)合實例形式分析了順序查找、最大最小值、自組織查詢算法相關(guān)原理與實現(xiàn)技巧,需要的朋友可以參考下2019-02-02