函数防抖
定义
触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;更直白一点就是:一个需要频繁触发的函数,在规定时间内,只让最后一次生效,前面的不生效。
实现思路
每次触发事件时设置一个延迟调用方法,并且取消之前的延时调用方法。
应用场景
- 搜索框输入
- 手机号、邮箱输入检测
- 拖拽窗口大小resize. 只要窗口调整完成之后,计算窗口大小,防止重复渲染
以搜索框输入为例
// 定义防抖函数,参数fn为具体应用中要使用的函数
function debounce(fn,delay) {
// 创建一个标记用来存放定时器的返回值
let timeout = null;
return function () {
// 每当用户输入的时候把前一个 setTimeout clear 掉
clearTimeout(timeout);
// 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
// 定义具体应用中要使用的函数
function sayHi() {
console.log('防抖成功');
}
var inp = document.getElementById('inp');
// 利用监听事件使用防抖函数
inp.addEventListener('input', debounce(sayHi,500));
函数节流
定义
高频事件触发,但在 n 秒内只会执行一次,所以节流会稀释函数的执行频率。更直白一点就是:一个函数执行后,只有大于设定的执行周期,才会执行第二次。
实现思路
每次触发事件时都判断当前是否有等待执行的延时函数,如果有,则直接return。
应用场景
- 滚动加载。加载更多或滚动到底部监听
- 谷歌搜索框,搜索联想功能
- 高频点击提交,表单重复提交
以滚动加载为例
//节流throttle代码:
function throttle(fn,delay) {
// 通过闭包保存一个标记
let timer = null;
return function () {
// 在函数开头判断标记是否为true,不为true则return
if (timer) return;
// 将外部传入的函数的执行放在setTimeout中
timer = setTimeout(() => {
// 最后在setTimeout执行完毕后再把标记设置为null(关键)表示可以执行下一次循环了。
// 当定时器没有执行的时候标记永远是false,在开头被return掉
fn.apply(this, arguments);
timer = null;
}, delay);
};
}
// 定义具应用中使用的函数
function sayHi() {
console.log("hello world");
}
// 利用监听事件,使用函数节流
window.addEventListener('scroll', throttle(sayHi,500));
异同比较
相同点
- 都可以通过使用 setTimeout 实现。
- 目的都是,降低回调执行频率。节省计算资源。
不同点
- 函数防抖,在一段连续操作结束后,处理回调,利用clearTimeout 和 setTimeout实现。函数节流,在一段连续操作中,每一段时间只执行一次,频率较高的事件中使用来提高性能。
- 函数防抖关注一定时间连续触发的事件只在最后执行一次,而函数节流侧重于一段时间内只执行一次。
原创文章,作者:ZERO,如若转载,请注明出处:https://www.edu24.cn/course/javascript/js-throttle-debounce.html