前言
在JavaScript中,当一个事件发生时,例如用户输入、滚动事件等,我们可能会触发一个函数来处理这个事件。如果没有对函数的执行进行限制,这个函数可能会被频繁地调用,导致性能问题和不必要的操作。而防抖和节流这两种常用的优化方法,就是用于限制函数的执行频率,以提高性能和流畅度,减少不必要的资源消耗。
防抖(debounce)
防抖会等待最后一次操作完成后的一段时间,如果还有其他的操作请求,在此期间被触发,则重新计时。这样可以保证在一段时间内只执行一次函数,而不是频繁地执行。这对于输入框的自动完成搜索建议非常有用,当用户停止输入一段时间后,才发送请求。
//代码如下
<button id="btn">提交</button>
<script>
function foo(e, a, b) {
console.log(this, "按钮点击", e);
}
//获取botton节点并监听他的点击事件,当点击时触发防抖函数
let btn = document.getElementById("btn");
btn.addEventListener("click", debounce(foo, 1000));
function debounce(fn, delay) {
let timer;
return function () {
let args = arguments;//debounce执行时传入的所有参数
//第一次点击时timer为undefined,跳过条件判断,并为其赋值一个定时器
//随后每次点击都会重置定时器,直到用户点击后1s内没有再次点击才会执行完这个定时器
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
//当前fn的实际函数foo在全局中,使用call方法在delay时间后将当前this上下文和传入的参数指向foo函数
fn.call(this, ...args);
}, delay);
};
}
</script>
</body>
节流(throttle)
节流会限制在一定时间内只能执行一次函数,即使在这个时间内多次触发了事件。节流可以保证在一段时间内有规律地执行函数,而不是频繁地执行。这对于滚动事件处理非常有用,使用节流后滚动不再会不断地调用函数,而是会在滚动停止后固定时间间隔执行一次函数。
//代码如下
<body>
<button id="btn">提交</button>
<script>
function foo(e){
console.log(this,"提交了",e);
}
let btn = document.getElementById('btn')
btn.addEventListener('click',throttle(send,1000))
function throttle(fn,delay){
let args = arguments
let last = Date.now()//获取最后一次点击时间
return function(){
当当前时间和你最后一次点击的时间差大于delay时,才会执行foo函数
if(Date.now()-last>delay){
fn.call(this, ...args);
//更新last
last = Date.now()
}
}
}
</script>
</body>
总结
防抖节流都是通过控制函数执行的频率来优化性能,但是二者原理不同,防抖是用户在规定的时间内没有第二次的操作才执行逻辑,如果用户一直点击,则逻辑不会执行.节流在规定的时间内这个逻辑最多只能执行一次,用户一直点击,则逻辑会在每次规定时间到达后执行