我记得之前我能手写的。
talk is cheap,show me the code
思路:总是保留最后一个定时器,这样就可以每次都是最后的时候再执行函数。
<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>Document</title>
</head>
<body>
<input type="text">
<script>
const ipt = document.querySelector('input');
// 简单版本
// 思路就是:每次输入都高频率触发事件,防抖就是 设置一个定时器,只在最后的一次触发,如果前面有定时器就清除掉。
// let timer =null;
// ipt.oninput = function(){
// if(timer){
// clearTimeout(timer);
// }
// timer=setTimeout(()=>{
// console.log(this.value);
// },500);
// }
// 封装防抖函数
const onDebounce = (fn, delay) => {
let timer = null;
// 这里返回函数,主要是ipt.oninput之前也调用一个函数,this指向ipt
// 再然后就是闭包,让timer得以变量引用,保存局部变量。
return function () {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.call(this);
}, delay);
}
}
// ipt.oninput = onDebounce(function(){
// console.log(this.value);
// },500)
ipt.addEventListener('input', onDebounce(
function () {
console.log(this.value);
}, 500
))
</script>
</body>
</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>Document</title>
</head>
<body style="height:2000px">
<script>
// 定时器器方式
// function throttle(fn, delay) {
// // 初始设置为真,设置一个定时器
// let valid = true;
// return function () {
// // 函数内局部作用域,可访问外部valid。
// // 之后valid重新赋值后,优先使用局部作用域内的valid;
// if (!valid) {
// return;
// }
// valid = false;
// setTimeout(() => {
// fn();
// // 定时器生效后重新设置一个定时器
// valid = true;
// }, delay)
// }
// }
// 时间戳方式
function throttle(fn, delay) {
let previous = 0;
return function () {
let now = new Date().getTime();
if (now - previous > delay) {
fn.call(this);
previous = now;
}
}
}
function showTop() {
var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
console.log('滚动条位置:' + scrollTop);
}
window.onscroll = throttle(showTop, 1000);
</script>
</body>
</html>
参考资料: