在我年轻的时候,写了这样一篇防抖和节流的文章。
那篇文章,既没有考虑到 dom调用监听器的this指向,也没有考虑其他方法。
因此现在来一个升级版。
防抖
function debounce(callback, time) {
let timer = null;
return function (e) {
// 如果timer存在,则清除定时器
timer && clearTimeout(timer);
// 然后重新开始计时
timer = setTimeout(() => {
// 这里的this是来自上级作用域的
callback.call(this, e);
timer = null; //重置定时器变量,不然上面的timer && clearTimeout(timer)就是无效代码了,不重置的话timer就一直有值
}, time);
}
}
验证
<input type="text">
<script src="./防抖.js"></script>
<script>
const input = document.querySelector('input');
input.onkeydown = debounce(function(e){
console.log(e.keyCode);
},500)
</script>
节流
// 延时器版本
// 第一次触发需要等待设定时间才会执行
function throttle(callback, time) {
let timer = null;
return function (e) {
if (!timer) {
timer = setTimeout(() => {
callback.call(this, e);
timer = null;
}, time);
}
}
}
// 时间戳版本
// 第一次触发就会立马执行
function throttle(callback, wait) {
let start = 0;
return function (e) {
// 如果时间间隔大于需要等待的时间
if (Date.now() - start >= wait) {
start = Date.now();
callback.call(this, e);
}
}
}
验证
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
body{
height: 2000px;
background: linear-gradient(#125,#eae);
}
</style>
</head>
<body>
<script src="./节流.js"></script>
<script>
// 绑定滚动事件
window.addEventListener('scroll',throttle(function(e){
console.log(Date.now());
console.log(e);
},500));
</script>
</body>
</html>