防抖和節流的區別是什么? 防抖和節流的實現。
防抖和節流的作用都是防止函數多次調用。區別在於,假設一個用戶一直觸發這個函數,且每次觸發函數的間隔小於設置的時間,防抖的情況下只會調用一次,
且節流的情況會每隔一定時間調用一次函數。
防抖(debounce):n秒內函數只會執行一次,如果n秒內高頻事件再次被觸發,則重新計算時間。
function debounce(func, wait, immediate=true) { let timeout, context, args; // 延遲執行函數 const later = () => setTimeout(() => { // 延遲函數執行完畢,清空定時器 timeout = null // 延遲執行的情況下,函數會在延遲函數中執行 // 使用到之前緩存的參數和上下文 if (!immediate) { func.apply(context, args); context = args = null; } }, wait); let debounced = function (...params) { if (!timeout) { timeout = later(); if (immediate) { //立即執行 func.apply(this, params); } else { //閉包 context = this; args = params; } } else { clearTimeout(timeout); timeout = later(); } } debounced.cancel = function () { clearTimeout(timeout); timeout = null; }; return debounced; };
防抖的應用場景:
1) 每次 resize / scroll 觸發統計事件
2) 文本輸入的驗證 (連續輸入文字后發送AJAX請求進行驗證,驗證一次就好)
節流 (throttle): 高頻事件在規定時間內只會執行一次,執行一次后,只有大於設定的執行周期后才會執行第二次。
//underscore.js function throttle(func, wait, options) { var timeout, context, args, result; var previous = 0; if (!options) options = {}; var later = function () { previous = options.leading === false ? 0 : Date.now() || new Date().getTime(); timeout = null; result = func.apply(context, args); if (!timeout) context = args = null; }; var throttled = function () { var now = Date.now() || new Date().getTime(); if (!previous && options.leading === false) previous = now; var remaining = wait - (now - previous); context = this; args = arguments; if (remaining <= 0 || remaining > wait) { if (timeout) { clearTimeout(timeout); timeout = null; } previous = now; result = func.apply(context, args); if (!timeout) context = args = null; } else if (!timeout && options.trailing !== false) { // 判斷是否設置了定時器和 trailing timeout = setTimeout(later, remaining); } return result; }; throttled.cancel = function () { clearTimeout(timeout); previous = 0; timeout = context = args = null; }; return throttled; };
函數節流的應用場景有:
1) DOM元素的拖拽功能實現(mousemove)
2) 射擊游戲的 mousedown / keydown 事件 (單位時間只能發射一顆子彈)
3) 計算鼠標移動的距離 (mousemove)
4) Canvas模擬畫板功能 (mousemove)
5) 搜索聯想(keyup)
6) 監聽滾動事件判斷是否到頁面底部自動加載更多:給scroll加了debounce后,
只有用戶停止滾動后,才會判斷是否到了頁面底部;如果是 throttle 的話,只要頁面滾動就會間隔一段時間判斷一次。
