前言
什么是防抖?什么是节流?它们之间有什么区别?你能举例说明一下吗?
上面这些问题在面试的时候你有被问到过吗?网络上也有很多文章已有说明,但是大部分由于篇幅过长或者描述不清晰,导致难以理解。因此,自己结合了实际的案例和大家分享一下。篇幅很短,花几分钟就可读完,如果有不明白的地方,欢迎在下方留言讨论。
简介
在网页运行的某些场景中,有些事件会不间断的被触发。如scroll
事件并不是我们想象中的,滚动一次触发一次。而是会多次被触发,由于过于频繁地DOM
操作和资源加载,严重影响了网页性能,甚至会造成浏览器崩溃。
常见的应用场景
- 最常见的场景
scroll
事件。
如下。当我们对窗口增加滚动事件监听,然后每次滚动时,触发监听的回调函数。
function printScroll () {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条当前位置:' + scrollTop);
}
window.addEventListener('scroll', printScroll)
但是,在运行时我们发现滚动一下会触发多次回调函数,打印结果如下:
然而实际开发中我们并不需要如此高频的回调,毕竟浏览器的性能是有限的,不应该浪费在这里。那么如何优化这种情况了。
防抖(debounce)
含义:事件被触发后延迟n秒再执行回调,如果在这n秒内又被触发,则重新计时。
具体实现:原理就是利用闭包。
// 防抖函数(简洁版)
function debounce(fn,delay){
let timer = null //借助闭包
return function() {
// 每次执行前先清除定时器,以确保在delay时间内fn函数不被执行。
timer && clearTimeout(timer)
timer = setTimeout(fn, delay)
}
}
// 原始函数
const handlerScroll = function() {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条当前位置:' + scrollTop);
}
// 两函数结合,实现滚动防抖
const scrollHandler = debounce(handlerScroll, 1000)
window.addEventListener('scroll', scrollHandler)
// 注:以上代码可copy到控制台直接测试
此时会发现,必须在停止滚动1秒以后,才会打印出滚动条位置。
注:实际开发中需要通过apply来获取函数的作用域和变量fn.apply(context, args)
。
实际开发中需要防抖处理的场景还是非常多的,如resize事件
、scroll事件
、input事件
、拖拽事件
等。除了这些,还有很多情况需要我们结合实际开发处理。
节流(throttle)
顾名思义就是每过n秒仅执行一次回调函数。如单位时间内多次触发函数,也只有一次生效。
// 节流函数
function throttle(fn, delay) {
let timer = null; //定义一个定时器
return function() {
let context = this;
let args = arguments;
if(!timer) {
timer = setTimeout(function() {
fn.apply(context, args);
timer = null;
}, delay);
}
}
}
// 原始函数
const scrollEvent = function() {
console.log('当前时间戳:' + new Date().getTime());
}
// 两函数结合,实现节流防抖
const scrollHandler = throttle(scrollEvent, 1000)
// 滚动事件
window.addEventListener('scroll', scrollHandler);
// 注:以上代码可copy到控制台直接测试
连续滚动5s的实际效果:
由于setTimeout
函数的时间参数存在误差(或者说执行函数本身所需要的时间),所以打印的结果后三位不一定是我们期望的数值。节流函数除了利用定时器的方式,也可以利用时间戳的方式。当前时间与上一个时间进行比对,这里就不赘述了。
总结
综上所述,防抖是事件停止触发且过了某指定时间后执行一次,而函数节流是间隔某指定的单位时间执行一次。
防抖和节流能有效减少浏览器引擎的损耗,防止出现页面堵塞卡顿现象,作为大前端开发人员是应该熟练掌握的技能。
面试过程中你有被问倒过哪些问题?欢迎在下方留言讨论。如果发现文章中有误的地方欢迎指出。如果觉得有帮助,不妨点赞、关注
支持一下,非常感谢!
作者:tager