防抖(Debounce)和節流(Throttle)是兩種常用的最佳化技術,主要用於控制高頻率的事件觸發,如滾動、輸入、視窗調整大小等。本文將深入探討防抖與節流的原理、實現方法及其應用場景。
簡單場景就是:輸入框防抖,滾動節流
1. 防抖(Debounce)
防抖是一種在事件頻繁觸發時,透過延遲執行來減少事件觸發次數的技術。防抖的核心思想是:當事件被觸發時,不立即執行處理函式,而是設定一個定時器,如果在定時器未結束前再次觸發事件,則重新開始計時。這樣可以確保在一定時間內只執行一次事件處理函式。
實現原理:
function debounce(func, wait) { let timeout; return function(...args) { const context = this; clearTimeout(timeout); timeout = setTimeout(() => func.apply(context, args), wait); }; }
示例應用:
在搜尋框輸入時,實時傳送請求獲取搜尋建議。如果不進行防抖處理,每次輸入都會傳送請求,造成伺服器壓力和資源浪費。透過防抖可以最佳化這種場景:
const searchInput = document.getElementById('search'); const handleSearch = debounce((event) => { console.log('Fetching search results for:', event.target.value); // 傳送搜尋請求 }, 300); searchInput.addEventListener('input', handleSearch);
2. 節流(Throttle)
節流是一種在事件頻繁觸發時,透過限制函式執行頻率來減少事件處理次數的技術。節流的核心思想是:在規定的時間間隔內只執行一次事件處理函式,不論期間事件觸發了多少次。
實現原理:
function throttle(func, limit) { let inThrottle; return function(...args) { const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; }
示例應用:
在頁面滾動時,實時計算滾動位置以顯示回到頂部按鈕。如果不進行節流處理,滾動事件會頻繁觸發,導致效能問題。透過節流可以最佳化這種場景:
const handleScroll = throttle(() => { console.log('Scroll position:', window.scrollY); // 處理滾動事件 }, 200); window.addEventListener('scroll', handleScroll);
3. 防抖與節流的選擇
防抖和節流雖然都是用於控制高頻事件,但它們的應用場景有所不同:
- 防抖:適用於頻繁觸發但只需最後一次結果的場景,如搜尋輸入、視窗大小調整等。
- 節流:適用於持續觸發但需要定期執行的場景,如滾動事件、視窗滾動位置計算等。
4. 深入最佳化
立即執行版防抖:
有時我們希望在事件觸發時立即執行一次,然後再進行防抖控制,可以在防抖函式中新增一個立即執行選項:
function debounce(func, wait, immediate) { let timeout; return function(...args) { const context = this; const callNow = immediate && !timeout; clearTimeout(timeout); timeout = setTimeout(() => { timeout = null; if (!immediate) func.apply(context, args); }, wait); if (callNow) func.apply(context, args); }; }
帶有標識的節流:
有時我們希望在節流過程中能夠獲取到當前的狀態,可以在節流函式中新增一個標識:
function throttle(func, limit) { let inThrottle; return function(...args) { const context = this; if (!inThrottle) { func.apply(context, args); inThrottle = true; setTimeout(() => inThrottle = false, limit); } }; }
5. 綜合應用
在實際開發中,防抖與節流可以結合使用。例如在一個實時搜尋的頁面中,使用者輸入時進行防抖處理,而在結果展示時進行節流處理,以最佳化整體效能。
const searchInput = document.getElementById('search'); const resultsContainer = document.getElementById('results'); const fetchResults = debounce((query) => { console.log('Fetching results for:', query); // 模擬搜尋請求 setTimeout(() => { resultsContainer.innerHTML = `Results for: ${query}`; }, 500); }, 300); const handleScroll = throttle(() => { console.log('Scroll position:', window.scrollY); // 處理滾動事件 }, 200); searchInput.addEventListener('input', (event) => { fetchResults(event.target.value); }); window.addEventListener('scroll', handleScroll);
防抖與節流是前端效能最佳化中的兩項重要技術,透過合理地應用這兩種技術,可以顯著減少高頻事件帶來的效能問題,提升使用者體驗。其他效能最佳化技術,如程式碼分割、非同步載入、懶載入等,後續介紹。