節流防抖

/**
 *  * @param fn {Function} 實際要執行的函數  * @param delay {Number} 延遲時間,也就是閾值,單位是毫秒(ms)  *  * @return {Function} 返回一個「去彈跳」了的函數  */ function debounce(fn, delay) { // 定時器,用來 setTimeout let timer; // 返回一個函數,這個函數會在一個時間區間結束後的 delay 毫秒時執行 fn 函數 return function() { // 保存函數調用時的上下文和參數,傳遞給 fn let context = this; let args = arguments; // 每次這個返回的函數被調用,就清除定時器,以保證不執行 fn clearTimeout(timer); // 當返回的函數被最後一次調用後(也就是用戶中止了某個連續的操做), // 再過 delay 毫秒就執行 fn timer = setTimeout(function() { fn.apply(context, args); }, delay); }; }

其實思路很簡單,debounce 返回了一個閉包,這個閉包依然會被連續頻繁地調用,可是在閉包內部,卻限制了原始函數 fn 的執行,強制 fn 只在連續操做中止後只執行一次。debounce 的使用方式以下:git

$(document).on( 'mouvemove', debounce(function(e) { // 代碼 }, 250) );

Throttle

throttle 的概念理解起來更容易,就是固定函數執行的速率,即所謂的「節流」。正常狀況下,mousemove 的監聽函數可能會每 20ms(假設)執行一次,若是設置 200ms 的「節流」,那麼它就會每 200ms 執行一次。好比在 1s 的時間段內,正常的監聽函數可能會執行 50(1000/20) 次,「節流」 200ms 後則會執行 5(1000/200) 次。github

與 debounce 相似,咱們這個 throttle 也接收兩個參數,一個實際要執行的函數 fn,一個執行間隔閾值 threshhold。一樣的,throttle 的更完整實現能夠參看 underscore 的 _.throttle閉包

/**
 *  * @param fn {Function} 實際要執行的函數  * @param delay {Number} 執行間隔,單位是毫秒(ms)  *  * @return {Function} 返回一個「節流」函數  */ function throttle(fn, threshhold) { // 記錄上次執行的時間 let last; // 定時器 let timer; // 默認間隔爲 250ms threshhold || (threshhold = 250); // 返回的函數,每過 threshhold 毫秒就執行一次 fn 函數 return function() { // 保存函數調用時的上下文和參數,傳遞給 fn let context = this; let args = arguments; let now = +new Date(); // 若是距離上次執行 fn 函數的時間小於 threshhold,那麼就放棄 // 執行 fn,並從新計時 if (last && now < last + threshhold) { clearTimeout(timer); // 保證在當前時間區間結束後,再執行一次 fn timer = setTimeout(function() { last = now; fn.apply(context, args); }, threshhold); // 在時間區間的最開始和到達指定間隔的時候執行一次 fn } else { last = now; fn.apply(context, args); } }; }

原理也不復雜,相比 debounce,無非是多了一個時間間隔的判斷,其餘的邏輯基本一致。throttle 的使用方式以下:app

$(document).on( 'mouvemove', throttle(function(e) { // 代碼 }, 250) );
相關文章
相關標籤/搜索