区别:
防抖debounce是最后一次事件执行。当规定时间内再次触发事件的时候,定时器会重新进行计时,只有当触发 事件 后规定时间内不再次触发执行事件。
节流throttle是指定时间间隔内只会执行一次任务。多次触发事件的时候,规定时间内只会触发一次。
相同点:
1、其实本质上都是为了节省程序的性能(防止高频函数调用)
2、借助了闭包的特性来缓存变量(状态)
3、都可以使用setTimeout实现
不同点
1、使用防抖,可能N个delay时间间隔之后fn也没执行,但是使用节流触发的delay间隔内有且只执行一次
2、同样一段时间间隔内快速连续触发,防抖只执行一次,而节流会执行多次,只是在不同的delay周期内
3、侧重点不同,防抖侧重于稳定只能执行一次,而节流强调限周期内次数,即执行频率,不限制所有时间内的总次数
使用场景
防抖
1、一些表单元素的校验,如手机号,邮箱,用户名等
2、有个输入框,输入之后会调用接口,获取联想词。只有在用户输入完毕的一段时间后,才会调用接口,出现联想词。
节流
1、一些鼠标的跟随动画实现
2、懒加载要监听计算滚动条的位置也就是scroll,使用节流按一定时间的频率获取。
3、scroll,resize, touchmove, mousemove等极易持续性促发事件的相关动画问题,降低频率
4、用户点击提交按钮,假设我们知道接口大致的返回时间的情况下,我们使用节流,只允许一定时间内点击一次。
手撕代码
1、防抖
function debounce(fn,delay) {
let timer = null;
return function() {
if (timer) clearTimeout(timer);
timer = setTimeout(()=>{
fn.call(this,...arguments)// 用apply指向调用debounce的对象,相当于this.fn(args);
//fun.apply(this,arguments)
}, delay);
}
}
写个键盘keyup的时候触发请求
function ajax(content) {//模拟ajax请求
console.log('ajax request ' + content)
}
function debounce(fun, delay) {
let timer=null
return function () {
if (timer) clearTimeout(timer);
timer = setTimeout(() =>{
fun.call(this, ...arguments)
//fun.apply(this,arguments)
}, delay)
}
}
let inputb = document.getElementById('debounce')
let debounceAjax = debounce(ajax, 500)// 防抖函数
inputb.addEventListener('keyup', function (e) {
debounceAjax(e.target.value)// 给防抖函数传参
})
2、节流
function throttle(fn, delay) {
let valid = true;
return function () {
if (!valid) return;
valid = false;
setTimeout(() => {
fn.call(this,...arguments);// 用call指向调用debounce的对象,相当于this.fn(args);
//fun.apply(this,arguments)
valid = true;
},delay)
}
}
写个scroll的时候触发请求
function ajax(content) {//模拟ajax请求
console.log('ajax request ' + content)
}
function throttle(fn, delay) {
let valid = true;
return function () {
if (!valid) return;
valid = false;
setTimeout(() => {
fn.call(this,...arguments);// 用call指向调用throttle的对象,相当于this.fn(args);
//fun.apply(this,arguments)
valid = true;
},delay)
}
}
let throttleAjax = throttle(ajax, 1000)// 节流函数
window.addEventListener("scroll",function(){
throttleAjax(document.documentElement.scrollTop||document.body.scrollTop)//传入的参数
})
这样,在某些特定的工作场景,我们就可以使用防抖与节流来减少不必要的损耗。
那么问题来了,假设面试官听到你这句话,是不是会接着问一句:“为什么说上面的场景不节制会造成过多损耗呢?”
OK,这就涉及到浏览器渲染页面的机制了……重绘和回流