1. 程式人生 > 其它 >JS函式防抖、節流

JS函式防抖、節流

一 、什麼是函式防抖

  對於短時間內連續觸發的事件(onresizescrollmousemove,mousehover),觸發事件後 n 秒內函式只能執行一次,如果觸發事件後 n 秒內又觸發了事件,則重新計算函式延執行時間

二、如何解決

  setTimeout輔助實現,延遲執行需要執行的程式碼;

三、具體程式碼

  

 1 // 防抖 短時間內多次觸發同一事件,只執行最後一次,或者只執行最開始的一次,中間的不執行。
 2 /**
 3  * @desc 函式防抖
 4  * @param fn目標函式
 5  * @param delay 延遲執行
 6  * @param {Object} immediate
7 */ 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))
認真做事兒,踏實做人