前端开发中,咱们的一些事件的响应比较慢或者须要请求接口完成的,咱们不但愿这些事件频繁执行,好比说须要对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
若文中有错误的地方望多多指正接口