decounce-and-throttle.png
1. 概念介绍
- debounce: 防抖函数,高频事件触发 在 n 秒内只会执行一次,节流会稀释函数的执行频率;
- debounce:节流函数,触发高频事件后 n 秒内函数只会执行一次,如果 n 秒内高频事件再次被触发,则重新计算时间;
- 区别:防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行
2. debounce 防抖实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>防抖</title>
</head>
<body>
<div style="height: 1000px;"></div>
</body>
<script>
function debounce(fn, interval) {
let timer = null;
return function (...args) {
if (timer !== null) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn(...args);
timer = null;
}, interval)
}
}
// 测试用例
var fn = function() {
console.log(1)
}
document.addEventListener('click', debounce(fn, 200));
</script>
</html>
3. throttle 节流实现
3.1 基于状态标记的实现
// 基于状态标记的实现
function throttle(func, timeout, firstCall) {
let run = true;
let timer = null;
let called = false;
function throttled() {
if (!run) {
return // 如果开关关闭了,那就直接不执行下边的代码
}
run = false;
if (firstCall && !called) {
func.apply(this, arguments)
called = true
run = true
} else {
timer = setTimeout(() => {
func.apply(this, arguments)
run = true;
}, timeout)
}
}
throttled.cancel = function () {
clearTimeout(timer);
run = true;
}
return throttled
}
3.2 基于时间刻度的实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>节流</title>
</head>
<body>
<div style="height: 1000px;"></div>
</body>
<script>
function throttle(fn, timeout, firstCall) {
let timer = null;
let lastTime = null;
let called = false;
function throttled(...args) {
let context = this;
function call() {
fn.call(context, ...args);
timer = null;
}
if (firstCall && !called) {
call();
called = true;
return;
}
if (timer === null) {
lastTime = Date.now();
timer = setTimeout(call, timeout);
} else {
clearTimeout(timer);
timer = setTimeout(call, lastTime + timeout - Date.now());
}
}
// 强制取消
throttled.cancel = function () {
clearTimeout(timer);
timer = null;
}
return throttled
}
// 测试用例
var fn = function () {
console.log(Date.now() / 1000, 1)
}
document.addEventListener('click', throttle(fn, 1000, true));
</script>
</html>