函數(shù)節(jié)流和防抖在前端開發(fā)中應(yīng)用廣泛赊时,例如:函數(shù)防抖可以用于對用戶輸入的自動補(bǔ)全操作、函數(shù)節(jié)流可以用于對用戶瀏覽行為的捕捉莺匠。
防抖
函數(shù)在事件觸發(fā) n 秒后才執(zhí)行,如果一個(gè)事件觸發(fā)的 n 秒內(nèi)又觸發(fā)了這個(gè)事件漩怎,那就以新的事件的觸發(fā)時(shí)間為準(zhǔn)
基本版
function denounce(func, wait) {
var timeout;
return function (){
clearTimeout(timeout);
setTimeout(func, wait);
}
}
解決 setTimeout 執(zhí)行過程中 this 指向問題
function debounce (func, wait){
var timeout
return function (){
var that = this
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(that)
}, wait)
}
}
解決 event 參數(shù)傳遞
function debounce (func, wait){
var timeout
return function (){
var args = arguments
var that = this
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(that, args)
}, wait)
}
}
加上可立即執(zhí)行判斷
function debounce (func, wait, immediate){
var timeout
return function (){
var args = arguments
var that = this
clearTimeout(timeout)
if (immediate){
if (!timeout){
func.apply(that, args)
}
timeout = setTimeout(function(){
timeout = null
}, wait)
} else {
timeout = setTimeout(function(){
func.apply(that, args)
}, wait)
}
}
}
加上返回值
function debounce (func, wait, immediate){
var timeout, result
return function (){
var args = arguments
var that = this
clearTimeout(timeout)
if (immediate){
if (timeout){
result = func.apply(that, args)
}
timeout = setTimeout(function(){
timeout = null
}, wait)
} else {
timeout = setTimeout(function(){
func.apply(that, args)
}, wait)
}
return result
}
}
增加取消上次防抖等待
function debounce (func, wait, immediate){
var timeout, result
var debounced = function (){
var args = arguments
var that = this
clearTimeout(timeout)
if (immediate){
if (!timeout){
result = func.apply(that, args)
}
timeout = setTimeout(function(){
timeout = null
}, wait)
} else {
timeout = setTimeout(function(){
func.apply(that, args)
}, wait)
}
return result
}
debounced.cancel = function(){
clearTimeout(timeout)
timeout = null
}
return debounced
}
節(jié)流
函數(shù)在每個(gè)規(guī)定時(shí)間間隔內(nèi)只會被觸發(fā)一次
兩種基本方式
時(shí)間戳版(效果:第一次觸發(fā)馬上執(zhí)行,最后一次觸發(fā)不會有效果)
function throttle(func, wait) {
var pre = 0
return function(){
var now = Date.now()
var that = this
var args = arguments
if (now - pre > wait) {
func.apply(that, args)
pre = now
}
}
}
定時(shí)器版(效果:第一次觸發(fā)延遲執(zhí)行嗦嗡,最后一次觸發(fā)有效果)
function throttle(func, wait){
var timeout
return function(){
var that = this
var args = arguments
if (!timeout) {
timeout = setTimeout(function (){
timeout = null;
func.apply(that, args)
}, wait)
}
}
}
結(jié)合可配置版
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;
}