JS函式防抖、節流
阿新 • • 發佈:2021-12-07
一 、什麼是函式防抖
對於短時間內連續觸發的事件(onresize,scroll,mousemove,mousehover),觸發事件後 n 秒內函式只能執行一次,如果觸發事件後 n 秒內又觸發了事件,則重新計算函式延執行時間
二、如何解決
setTimeout輔助實現,延遲執行需要執行的程式碼;
三、具體程式碼
1 // 防抖 短時間內多次觸發同一事件,只執行最後一次,或者只執行最開始的一次,中間的不執行。 2 /** 3 * @desc 函式防抖 4 * @param fn目標函式 5 * @param delay 延遲執行 6 * @param {Object} immediate7 */ 8 function debounce(fn, delay, immediate) { 9 if(typeof fn != "function") { 10 throw new TypeError("fn不是函式") 11 } 12 13 let timer; 14 return function() { 15 var _this = this // 取debounce執行作用域的this(原函式掛載到的物件) 16 var args = arguments 17 if(timer) {18 clearTimeout(timer) 19 } 20 21 if(immediate) { // 立即執行(立即執行的意思是觸發事件後函式會立即執行,然後 n 秒內不觸發事件才能繼續執行函式) 22 let callnow = !timer 23 timer = setTimeout(() => { 24 timer = null 25 }, delay) 26 if(callnow) fn.apply(_this, args)27 } else { // 延遲執行(非立即執行版意思是觸發事件後函式不會立即執行,而是在 n 秒後執行,如果在 n 秒內又觸發了事件,則會重新計算函式執行時間) 28 timer = setTimeout(function() { 29 fn.apply(_this, args); 30 }, delay) 31 } 32 } 33 } 34 35 input.addEventListener('keyUp', debounce(() => { 36 console.log(input.value) 37 }, 600))
四、什麼是節流
函式執行一次之後,該函式在指定的時間期限內不再工作,直到過了這段時間才重新生效
五、適用場景
搜尋框搜尋輸入、改變瀏覽器視窗大小
六、程式碼實現
1 // 節流 2 /** 3 * @param {Object} 函式節流 4 * @param {Object} delay 5 * @param {type} 1 表時間戳版,2 表定時器版 6 * 時間戳版和定時器版的節流函式的區別就是,時間戳版的函式觸發是在時間段內開始的時候,而定時器版的函式觸發是在時間段內結束的時候 7 */ 8 function throttle(fn, delay, type) { 9 if (type === 1) { 10 let previous = 0; 11 } else if (type === 2) { 12 let timer; 13 } 14 return function() { 15 var _this = this; 16 var args = arguments; 17 if(type === 1) { 18 let now = Date.now(); 19 if (now - previous > delay) { 20 fn.apply(_this, args) 21 previous = now 22 } 23 } else if(type === 2) { 24 if(timer) { 25 return 26 } 27 timer = setTimeout(function() { 28 fn.apply(fn, args) // 這裡args接收的是外邊返回的函式的引數,不能用arguments 29 // fn.apply(_this, arguments); 需要注意:Chrome 14 以及 Internet Explorer 9 仍然不接受類陣列物件。如果傳入類陣列物件,它們會丟擲異常 30 timer = null // 在delay後執行完fn之後清空timer,此時timer為假,throttle觸發可以進入計時器 31 }, delay) 32 } 33 } 34 } 35 36 diva.addEventListener('drgs', throttle((e) => { 37 console.log(e.offsetX, e.offsetY) 38 }, 100))認真做事兒,踏實做人