節流實質上是:如果你持續觸發事件,每隔一段時間,只執行一次事件。
根據這個需求我們可以通過時間戳實現節流:
//第一個實現方式function throttle(func, wait) {
var context, args;
var previous = 0;
return function() {
var now = +new Date();
context = this;
args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}}//另外補充一下獲取時間戳的方式吧// new Date().getTime()// Date.parse(new Date())// +new Date()// Date.now()// 通過判斷再次點擊時間與上次點擊時間的時間戳是否大於傳入的時間,來判斷函數是否被執行
另一種實現方式通過定時器,通過判斷定時器的存在來決定函數是否被執行
// 第二種實現方式function throttle(func, wait) {
var timeout;
var previous = 0;
return function() {
context = this;
args = arguments;
if (!timeout) {
timeout = setTimeout(function(){
timeout = null;
func.apply(context, args)
}, wait)
}
}}//
看上面兩種實現方式的代碼,比較可以發現:
- 方式一的事件會立刻執行,因爲獲取當前時間戳肯定會大於wait傳入的時間,方式二事件會在 n 秒後第一次執行,因爲設置了定時器,所以會在wait秒之後執行。
- 如果我們連續執行了幾次,第一種方式會在事件結束之後不會再執行函數,第二種會在結束之後wait秒之後再執行一次。
怎麼中和實現一下兩種方式呢?
// 第三種方式function throttle(func, wait, options) {
var timeout, context, args, result;
var previous = 0;
if (!options) options = {};
var later = function() {
previous = options.leading === false ? 0 : new Date().getTime();
timeout = null;
func.apply(context, args);
if (!timeout) context = args = null;
};
var throttled = function() {
var now = new Date().getTime();
if (!previous && options.leading === false) previous = now;
var remaining = wait - (now - previous);
context = this;
args = arguments;
if (remaining <= 0 || remaining > wait) {
if (timeout) {
clearTimeout(timeout);
timeout = null;
}
previous = now;
func.apply(context, args);
if (!timeout) context = args = null;
} else if (!timeout && options.trailing !== false) {
timeout = setTimeout(later, remaining);
}
};
return throttled;}
//leading:false 表示禁用第一次執行
//trailing: false 表示禁用停止觸發的回調
//那就是 leading:false 和 trailing: false 不能同時設置。