函数防抖(debounce)
当函数被触发n秒后,再执行该函数,如果在这n秒内函数被再次触发,则重新计时
应用场景
连续的事件触发,只需要对最后一次进行处理
- 搜索框搜索输入,只需要在用户输入完成后,再发起请求
- 输入框进行输入验证检测
- 对窗口进行resize调整,在调整完成后,再进行渲染
实现
function debounce(fn, wait) {
var timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => fn.apply(this, arguments), wait);
};
}
函数节流(throttle)
最少间隔n秒,执行一次函数
应用场景
- 滚动加载
- 高频点击提交
时间戳方式实现
function throttle(fn, wait) {
// 初始时间设为0
var prevTime = 0;
return function () {
// 获取当前时间
let curTime = new Date();
// 如果当前时间距离上次函数执行时间的时间间隔已经足够长了
if (curTime - prevTime >= wait) {
// 执行函数,通过apply绑定this,传递参数
fn.apply(this, arguments);
// 将当前时间戳赋值给上一次执行时间
prevTime = curTime;
}
};
}
定时器方式实现
function throttle(fn, wait) {
let timer = null;
return function () {
// 如果timer不为null,说明有函数正在等待执行,直接跳过
if (timer) return;
// 通过setTimeout,保证一定时间内只执行一次函数
timer = setTimeout(() => {
fn.apply(this, arguments);
// 函数执行完成后,将timer清除
timer = null;
}, wait);
};
}
函数防抖和节流测试
简单的写了一个html页面测试,覆盖了函数防抖和节流的常见场景,input输入框输入即显示,提交按钮高频点击。codeSandbox链接
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
</head>
<body>
<input id="input" />
<button type="button">提交</button>
<div id="message"></div>
<script src="./index.js"></script>
</body>
</html>
// input输入框元素
let input = document.getElementById("input");
// 提交按钮元素
let submitBtn = document.querySelector("button");
// 函数防抖
function debounce(fn, wait) {
let timer = null;
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => fn.apply(this, arguments), wait);
};
}
// 函数节流
function throttle(fn, wait) {
let timer = null;
return function () {
if (timer) return;
timer = setTimeout(() => {
fn.apply(this, arguments);
timer = null;
}, wait);
};
}
// 将input输入的内容显示在页面上
function handleInput(event) {
let message = document.querySelector("#message");
message.textContent = event.target.value;
}
// 通过控制台查看提交按钮触发的提交次数
function handleSubmit() {
++submitCount;
console.log("提交次数:", submitCount);
}
let submitCount = 0;
// 监听input事件
input.addEventListener("input", debounce(handleInput, 1000));
// 监听点击事件
submitBtn.addEventListener("click", throttle(handleSubmit, 1000));