網頁中JavaScript最基本的功能是監聽或響應用戶的動作,這非常的有用。用戶的動作有些頻率非常高,有的十分罕見。有些監聽器函數的執行如閃電般完成,而有些繁重的會把浏覽器拖死。拿浏覽器窗口的resize事件來說,這種事件會在浏覽器窗口大小的每一尺度變化都觸發一次,如果監聽器體量很大,你的浏覽器很快就會被拖垮。
很顯然,我們不能允許浏覽器被拖垮,但我們又不能刪除刪除監聽器。然而,我們可以限制函數調用的頻度,弱化事件函數運行帶來的影響。相對於讓窗口的每一步size的變化都觸發一次監聽器函數,我們可以現在監聽函數的觸發的最小間隔必須大於多少毫秒,讓它保持著合理的調用頻道,確保不毀壞用戶體驗。有一個很好的js工具庫叫做Underscore.js,它裡面有一個簡單的方法能讓你輕松的創建降低事件函數觸發頻度的監聽器。
JavaScript代碼
降頻監聽器的代碼很簡單:
復制代碼 代碼如下:
// 創建監聽器
var updateLayout = _.debounce(function(e) {
// Does all the layout updating here
}, 500); // 最低500毫秒運行一次
// Add the event listener
window.addEventListener("resize", updateLayout, false);
…這段Underscore.js代碼底層實際上是用interval檢查事件函數調用的頻度:
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// N milliseconds. If `immediate` is passed, trigger the function on the
// leading edge, instead of the trailing.
_.debounce = function(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
};
代碼並不是特別復雜,但用不著自己寫也是一種幸福。這個debounce函數並沒有依賴其他的Underscore.js函數,所以,你可以把這個方法添加到你喜歡的js工具庫中,例如jQuery或MooTools,很容易:
復制代碼 代碼如下:
// MooTools
Function.implement({
debounce: function(wait, immediate) {
var timeout,
func = this;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);
};
}
});
// Use it!
window.addEvent("resize", myFn.debounce(500));
正如上面說的,窗口的resize事件是最常見的使用降頻操作的地方,還有一個常用的地方是,根據用戶的按鍵輸入給出自動補全提示。我非常喜歡收集這樣的代碼片段,它們能輕松的讓你的網站更高效。同時也推薦大家研究一下Underscore.js,裡面提供了大量非常有用的函數。