本质上是优化高频率执行代码的一种手段
如:浏览器的 resize、scroll、keypress、mousemove 等事件在触发时,会不断地调用绑定在事件上的回调函数,极大地浪费资源,降低前端性能
为了优化体验,需要对这类事件进行调用次数的限制,对此我们就可以采用 防抖(debounce) 和 节流(throttle) 的方式来减少调用频率
防抖
防抖(debounce):不管事件触发频率多高,一定在事件触发n秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,就以新的事件的时间为准,n秒后才执行,总之,触发完事件 n 秒内不再触发事件,n秒后再执行。
有时候我们需要让函数立即执行一次,再等后面事件触发后等待n秒执行,我们给debounce函数一个flag用于标示是否立即执行。
当定时器变量timer为空时,说明是第一次执行,我们立即执行它。
function debounce(event, time, flag) {
let timer = null;//初始化计时器变量
return function (...args) {
clearTimeout(timer);//清除上一个计时器
if (flag && !timer) {//如果传入了flag且第一次使用立刻触发不用倒计时
event.apply(this, args);//args将参数作为数组传给event函数
}
timer = setTimeout(() => {//倒计时开始,也是防抖的关键
event.apply(this, args);
}, time);
};
}
测试代码
<body>
<div
onclick="deli()"
style="background-color: pink; height: 1000px; width: 1000px"
>
<p>这是一个粉色的 div。</p>
</div>
<script>
var element = document.querySelector("div");
//防抖实现
//
function bigger() {
element.style.backgroundColor = "red";
console.log('work');
} // Cherry
var deli = debounce(bigger, 600);
</script>
</body>
PS:传入flag且第一次触发时会触发两次
节流
节流(throttle):不管事件触发频率多高,只在单位时间内执行一次。
1.时间戳实现(第一次立刻触发)
...args用于接受使用throttle的方法的传参
function throttle(event, time) {
let pre = 0;
return function (...args) {
if (Date.now() - pre > time) {
pre = Date.now();
event.apply(this, args);
}
}
2.定时器实现(最后一次一定触发)
function throttle(event, time) {
timer = null;
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
timer = null;//不添加这一行就无法再次进入if进行倒计时
event.apply(this.args);
}, time);
}
};
}
测试代码:与防抖相同
参考:www.conardli.top/docs/JavaSc…