概念
函数防抖和函数节流,都是为了限制函数的执行频次,以优化函数触发频率过高导致的响应速度跟不上触发频率,从而导致出现的延迟、假死和卡顿。
防抖:
触发高频事件后n秒内函数只会执行最后一次,如果n秒内高频事件再次被触发,则重新计算时间
节流:
高频事件触发,每隔特定的时间会执行一次,所以节流会稀释函数的执行频率
防抖
实现方式:每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法
<body>
<h4>频繁输入任意字符:</h4>
<input id="debounce"> </input>
</body>
<script>
document.getElementById("debounce").addEventListener("input", debounce())
function debounce() {
let timer;
// 使用闭包,多次调用都能访问到外层函数的变量,而不是生成新的变量
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
// 需要防抖的操作...
console.log(document.getElementById("debounce").value);
}, 500);
}
}
</script>
效果:
防抖函数的封装使用
<body>
<h4>频繁输入任意字符:</h4>
<input id="debounce"> </input>
</body>
<script>
// 防抖函数的封装
function debounce(fn, delay) {
let timer;
// 使用闭包,多次调用都能访问到外层函数的变量,而不是生成新的变量
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
}
// 防抖函数的使用
document.getElementById("debounce").addEventListener("input", debounce(function () {
console.log(document.getElementById("debounce").value);
}, 200))
</script>
节流
实现方式:每次触发事件时,如果当前有等待执行的延时函数,则直接return
<body>
<button id="throttle"> 频繁点我 </button>
</body>
<script>
document.getElementById("throttle").addEventListener("click", throttle())
function throttle() {
let flag = true;
return function () {
if (!flag) { return; }
flag = false;
setTimeout(() => {
console.log("节流成功!");
flag = true;
}, 1000);
};
}
</script>
效果:
节流函数的封装使用
<body>
<button id="throttle"> 频繁点我 </button>
</body>
<script>
// 节流函数的封装
function throttle(fn, delay) {
let flag = true;
return function () {
if (!flag) { return; }
flag = false;
setTimeout(() => {
fn.apply(this, arguments);
flag = true;
}, delay);
};
}
// 节流函数的使用
document.getElementById("throttle").addEventListener("click", throttle(function () {
console.log("节流成功!");
}, 1000))
</script>
总结:
函数防抖:将多次操作合并为一次操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
函数节流:使得一定时间内只触发一次函数。原理是通过判断是否有延迟调用函数未执行。
区别:
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。
应用场景:
- 防抖可应用于用户输入等
- 节流可以用于无限加载场景,如页面滚动