前端開發中,咱們的一些事件的響應比較慢或者須要請求接口完成的,咱們不但願這些事件頻繁執行,好比說須要對input輸入的數據保存,監聽keyup事件,若是每次鍵盤輸入就執行保存請求,那樣可能會產生不少頻繁的請求,針對這種連續觸發的高頻率事件,函數防抖和函數節流給出了兩種解決方法前端
去抖動,方法是在函數觸發時,設定一個週期延遲執行函數,若在週期內函數再次執行、則刷新延遲時間,直到最後執行函數,這裏函數收集到的結果是最後一次操做的結果bash
var timer; // 定時器
function change (e) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(function () {
console.log(e.target.value);
timer = void 0;
}, 1000)
}
document.querySelector("#test").addEventListener('keyup', change);
複製代碼
這裏監聽input的keyup事件,change方法執行的時候會首先判判定時器是否存在、若是存在則clear掉,若是不則新建一個定時器延遲1s執行app
上面這樣實現沒毛病,可是卻有一個問題,沒有複用性,如今我來把他封裝成一個公共的方法函數
function keyup (e) {
console.log(e.target.value);
}
function debounce (method, delay) {
var timer = void 0;
return function () {
var self = this;
var args = arguments;
timer && clearTimeout(timer);
timer = setTimeout(function () {
method.apply(self, args)
timer = void 0;
}, delay)
}
}
document.querySelector("#test").addEventListener('keyup', debounce(keyup, 1000));
複製代碼
節流的概念是設定一個週期,週期內只執行一次,如有新的事件觸發則不執行,週期結束後又有新的事件觸發開始新的週期ui
好比說咱們監聽onscroll判斷獲取當前的scrollTop、能夠用到節流this
var start, timer, wait = 200
function scroll() {
var self = this;
var args = arguments;
if (!start) {
//第一次觸發,設置start時間
start = Date.now()
}
// 當前時間減去開始時間大於等於設定的週期則執行而且初始化start、timer
if (Date.now() - start >= wait) {
console.log('觸發了')
start = timer = void 0;
} else {
timer && clearTimeout(timer)
timer = setTimeout(function () {
scroll.apply(self, arguments)
},wait)
}
}
document.addEventListener('scroll', scroll)
複製代碼
function throttling (method, wait) {
var start, timer
return function run () {
var self = this;
var args = arguments;
if (!start) {
start = Date.now();
}
if (Date.now() - start >= wait) {
method.apply(self, args)
start = timer = void 0
} else {
timer && clearTimeout(timer)
timer = setTimeout(function () {
run.apply(self, args)
}, wait)
}
}
}
function scroll() {
console.log('觸發了')
}
document.addEventListener('scroll', throttling(scroll, 200))
複製代碼
這裏須要注意的就是參數和this指向的問題spa
節流和防抖各有特色,若是是須要一連串頻繁的事件只執行最後一次選擇防抖、其它能夠選擇節流,具體業務具體分析code
若文中有錯誤的地方望多多指正接口