JS中的节流和防抖
在看别人的代码时在注释中发现了没听过的词汇,防抖,然后就去查了一下,总结自己的理解。
防抖(debounce):
效果:短时间内大量触发同一事件,最后只会执行一次函数。
用现实中的场景举例,在电梯外部按下按钮,电梯会在当前楼层停留一段时候后才往下走,如果在外部重复按下按钮,电梯就会一直停留在当前楼层。
可能需要用上的场景:scroll、mousemove、keydown等高频触发的事件,如果频繁触发事件绑定的函数,可能会造成页面卡顿等问题。
常见应用场景:(1)window的 resize 和 scroll 事件; 如:滚动到页面底部加载更多,稍微滚动一下就会触发n多次scroll事件,如果每次触发scroll事件的时候都去判断一次是否已经滚动到了页面底部,无疑会造成资源的浪费。此时若使用js节流,每隔一定的时间(如500ms)进行一次判断,间隔期间只能有一次触发判断,既节省了资源,也不会影响用户体验。(2)文字输入时的 keyup 事件; 如:输入搜索关键词的时候,进行自动完成或者自动联想。同理,这种情况下用户每敲击一次键盘就会触发一次keyup事件,此时用户可能连一个字都没有输入完成==,此时可以使用js防抖,在用户停止输入的一段时间后(如500ms)触发判断,进行自动联想或者自动搜索;也可以使用js节流,每隔一段时间,进行一次判断的执行,既可以实现实时的自动联想,也不会出现过于频繁的请求。(3)元素拖拽、移动时的 mousemove 事件;
实现原理:使用闭包在内部封装一个定时器(setTimeout),然后延迟执行,当重复调用时清除定时器,重新计时。
实现代码:
/**
* @description 防抖
* @param {Function} fn 需要执行的函数
* @param {Number} delay 延迟时间
* @returns Function
*/
function debounce(fn,delay){
let timer = null
return function() {
if(timer){
clearTimeout(timer)
}
timer = setTimeout(fn,delay)
}
}缺点:如果连续的调用间隔一直小于delay, 会造成长时间不触发.
节流(throttle)
效果:在规定时间内,只能触发一次函数。如果这个时间内触发多次函数,只有一次生效。
实现原理:使用闭包在内部定义定时器,定时器计时未完成时不执行函数。
使用setTimeou实现:
/**
* @description 节流
* @param {Function} fn 需要执行的函数
* @param {Number} delay 延迟时间
* @returns Function
*/
function throttle(fn,delay){
let timer = null
return function() {
if(!timer){
timer = setTimeout(()=>{
timer = null;
fn()
},delay)
}
}
}使用时间戳实现:
/**
* @description 节流
* @param {Function} fn 需要执行的函数
* @param {Number} delay 延迟时间
* @returns Function
*/
function throttle(fn, wait) {
let previous = 0;
return function() {
let now = Date.now();
if (now - previous > wait) {
fn()
previous = now;
}
}
}总结:
防抖和节流只是减少了事件回调函数的执行次数,并不会减少事件的触发频率。防抖和节流并没有从本质上解决性能问题,我们还应该注意优化我们事件回调函数的逻辑功能,避免在回调中执行比较复杂的DOM操作,减少浏览器reflow和repaint。
参考文章:
https://segmentfault.com/a/1190000018428170
https://blog.csdn.net/xiaomajia029/article/details/82657319
https://www.yht7.com/news/30003
# JavaScript
评论
后参与评论
还没有评论,来说点什么吧~