防抖和节流的区别和实现详解(中高级前端面试必备知识)

前言 什么是防抖?什么是节流?它们之间有什么区别?你能举例说明一下吗?
上面这些问题在面试的时候你有被问到过吗?网络上也有很多文章已有说明,但是大部分由于篇幅过长或者描述不清晰,导致难以理解。因此,自己结合了实际的案例和大家分享一下。篇幅很短,花几分钟就可读完,如果有不明白的地方,欢迎在下方留言讨论。
简介 在网页运行的某些场景中,有些事件会不间断的被触发。如scroll事件并不是我们想象中的,滚动一次触发一次。而是会多次被触发,由于过于频繁地DOM操作和资源加载,严重影响了网页性能,甚至会造成浏览器崩溃。
常见的应用场景

  1. 最常见的场景 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
链接:https://juejin.cn/post/7020955167419793444
说明:稀土掘金同步更新
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    推荐阅读