在前端开发中,有一部分的用户行为会频繁地触发事件执行,从而对DOM操作,资源加载等耗费性能的处理很可能导致页面卡顿甚至浏览器崩溃。
函数节流(throttle)和函数防抖(debounce)就是为了解决类似需求应运而生的。
节流:预定一个函数只有在大于等于执行周期时才执行,周期内调用不执行。
场景:
- 窗口调整(resize)
- 页面滚动(scroll)
- 抢购疯狂点击(mousedown)
例子:
// 显示数字的div
var oDiv = document.getElementById('show');
// 按钮
var oBtn = document.getElementById('btn');
function throttle(handler, wait) {
// 最近的一次点击时间
var lastTime = 0;
// onclick 的事件执行函数(这里形成了一个闭包)
return function(e) {
// 当前时间
var nowTime = new Date().getTime();
if(nowTime - lastTime > wait) {
// 修正this指向和事件对象参数
handler.apply(this, arguments);
lastTime = nowTime;
}
}
}
function buy(e) {
console.log(this, e);
oDiv.innerHTML = parseInt(oDiv.innerHTML) + 1;
}
oBtn.onclick = throttle(buy, 1000);
防抖:在函数需要频繁触发时,只有足够空闲的时间才执行一次。
场景:
- 实时搜索(keyup)
- 拖拽(mousemove)
例子:
var oInp = document.getElementById('inp');
function debounce(handler, delay) {
var timer = null;
// 事件处理函数(闭包)
return function() {
var _self = this;
var _arg = arguments;
clearTimeout(timer);
timer = setTimeout(function() {
// 修正this指向和事件对象参数
handler.apply(_self, _arg);
}, delay);
}
}
function ajax(e) {
console.log(e, this.value);
}
oInp.oninput = debounce(ajax, 1000);
总结
- 相同点
- 事件连续出发,在执行周期内控制事件执行次数
- 不同点
- 节流:事件在执行周期内连续触发,只执行一次
- 防抖:事件在执行周期内连续触发,不执行,间隔大于执行周期才触发一次