1. 程式人生 > >Javascript函式防抖與節流

Javascript函式防抖與節流

為什麼要函式防抖和函式節流?

知乎上的回答有很經典的例子:

舉個栗子,我們知道目前的一種說法是當 1 秒內連續播放 24 張以上的圖片時,在人眼的視覺中就會形成一個連貫的動畫,所以在電影的播放(以前是,現在不知道)中基本是以每秒 24 張的速度播放的,為什麼不 100 張或更多是因為 24 張就可以滿足人類視覺需求的時候,100 張就會顯得很浪費資源。再舉個栗子,假設電梯一次只能載一人的話,10 個人要上樓的話電梯就得走 10 次,是一種浪費資源的行為;而實際生活正顯然不是這樣的,當電梯裡有人準備上樓的時候如果外面又有人按電梯的話,電梯會再次開啟直到滿載位置,從電梯的角度來說,這時一種節約資源的行為(相對於一次只能載一個人)。 —— 引自

大板慄函式節流與函式防抖

瀏覽器操作中我們經常會遇到短時間內頻繁觸發的事件,類似於:

  • window的scroll、resize事件等
  • input中change或input事件、keyup、keydown和keypress事件等

這種耗費效能的事情,很可能造成瀏覽器的卡頓,甚至崩潰。可通過函式防抖和節流來避免這種情況。

函式防抖(Debounce)

debounce: 事件觸發停止一定時間後才會執行響應的函式,期間如果重複呼叫動作,重新計算時間。類似於,按下一個彈簧,只有你鬆手的時候彈簧才會彈起。本質上是將多次操作合併為一次操作。可用一個定時器維護,事件觸發後wait時間內如果事件重複觸發,那麼取消當前定時器,重新設定一個時延為wait的定時器。

方法定義

/**
*@param fn {function} 事件觸發執行的函式
*@param wait {number} 固定時間(事件停止觸發多久之後執行函式)
*/
debounce(fn,wait)

方法實現

function debounce(fn,wait){
	var timer;
	return function(){
		var args = Array.prototype.slice.apply(arguments);
		if(timer){
			clearTimeout(timer);
		};
		timer = setTimeout(function
(){ fn.apply(this,args); },wait); } }

函式節流(Throttle)

防抖有一個問題,那就是如果事件一直在觸發,那麼執行函式永遠都得不到執行。這種情況下,函式節流此時是較好的方法。它與防抖最大的區別就是,無論事件觸發多麼頻繁,都可以保證在規定時間內可以執行一次執行函式。

throttle:事件觸發後執行函式執行期間內事件再次觸發,執行函式將不會執行,等規定時間之後事件觸發,執行函式方可再次執行。

方法定義

/**
*@param fn {function} 事件觸發執行的函式
*@param wait {number} 固定時間(函式執行當前時間與下一次執行時間的最小時間範圍)
*/
throttle(fn,wait)

方法實現一

function throttle(fn,wait){
	var isExecute = false;
	return function(){
		var args = Array.prototype.slice.apply(arguments);
		if(isExecute) {
			return;
		}
		isExecute = true;
		setTimeout(function(){
			fn.apply(this,args);
			isExecute = fale
		},wait)
	}
}

方法實現二

function throttle(fn,wait){
	var lastTime = new Date().getTime();
	return function(){
		var args = Array.prototype.slice.apply(arguments);
		var curTime = new Date().getTime();
		if((curTime - lastTime) < wait){return;};
		lastTime = curTime;
		fn.apply(this,args);
	}
}