「~函数防抖与节流 ~」
每日一题,希望让爱学习、思考的前端技术伙伴在一起学习、复盘、成长。 基础知识要夯实,原理源码要深入,深度广度要扩展,坚持每天进步一点点,每天有所收获。进大厂是最终目标 ?
* 回答面试题的套路
1、先说这个点的明确定义,或者是特性;
2、再说具体的应用场景;
3、说说自己的看法、观点;
4、可以稍微举一反三,说说同类特性,或者类似的框架,更好的方案。
防抖和节流的产生
浏览器的resize、scroll、keypress、mousemove操作时会频繁触发,如果我们在回调中计算元素位置、做一些跟DOM相关的操作,引起浏览器回流和重绘,频繁触发回调,很可能会造成浏览器掉帧,甚至会使浏览器崩溃,影响用户体验。针对这种现象,目前有两种常用的解决方案:防抖和节流。
手写函数防抖与节流
1、函数的防抖(防止老年帕金森)
对于频繁触发某个操作,我们只识别一次(只触发执行一次函数)。
代码如下:
function debounce(func, wait = 300, immediate = false) {
let timer = null;
return function anonymous(...params) {
let now = immediate && !timer;
// 每次点击都把之前设置的定时器清除
clearTimeout(timer);
// 重新设置一个新的定时器监听wait时间内是否触发第二次
timer = setTimeout(() => {
// 手动让其回归到初始状态
timer = null;
// wait这么久的等待中,没有触发第二次
!immediate ? func.call(this, ...params) : null;
}, wait);
// 如果是立即执行
now ? func.call(this, ...params) : null;
};
}
参数
1)func[function]:最后要触发执行的函数;
2)wait[number]:“频繁”设定的界限;
3)immediate[boolean]:默认多次操作,我们识别的是最后一次,但是immediate=true,让其识别第一次;
主体思路:
在当前点击完成后,我们等wait这么长的时间,看是否还会触发第二次,如果没有触发第二次,属于非频繁操作,我们直接执行想要执行的函数func;如果触发了第二次,则以前的不算了,从当前这次再开始等待...
2、函数节流:
在一段频繁操作中,可以触发多次,但是触发的频率由自己指定。
代码如下:
function throttle(func, wait = 300) {
let timer = null,
previous = 0; // 记录上一次操作的时间
return function anonymous(...params) {
let now = new Date(),
remaining = wait - (now - previous); //记录还差多久达到我们一次触发的频率
if (remaining <= 0) {
// 两次操作的间隔时间已经超过wait了
window.clearTimeout(timer);
timer = null;
previous = now;
func.call(this, ...params);
} else if (!timer) {
// 两次操作的间隔时间还不符合触发的频率
timer = setTimeout(() => {
timer = null;
previous = new Date();
func.call(this, ...params);
}, remaining);
}
};
}
参数
func[function]:最后要触发执行的函数;
wait[number]:触发的频率;
应用场景
1、防抖(debounce)
1)每次 resize/scroll 触发统计事件 (调整窗口大小);
2)文本输入的验证,连续输入文字后发送 AJAX 请求进行验证,验证一次就好。(keyup 事件);
2、节流(throttle)
1)鼠标不断点击触发;
2)监听滚动事件;
自己的认识与理解:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行。
* 可以在留言区写下你的答案,一起成长进大厂。
推荐热门技术文章:
JS第一座大山:堆栈内存和闭包作用域 (想深入看这里)
JS基础进阶- 堆栈内存和闭包作用域
JS基础进阶- 闭包作用域和JS高阶编程技巧
觉得本文对你有帮助?请分享给更多人
关注「前端学苑」加星标,提升前端技能
如果觉得这篇文章还不错,来个【分享、点赞、在看】三连吧,让更多的人也看到~