最简单的 节流防抖_debounce_throttle
特别鸣谢:https://segmentfault.com/a/1190000018428170
<!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>debounce_throttle_防抖_节流</title>
</head>
<body>
<div style="height: 2000px; padding: 30px;">
<div style="margin-top: 30px;">
<h2>1.防抖</h2>
<hr/>
> 1.停,才执行 <br/>
> 2.(优点:能保证最后一次被调用,但只执行一次)
</div>
<div style="margin-top: 30px;">
<h2>2.节流</h2>
<hr/>
> 1.动,才执行 <br/>
> 2.(缺点:最后一次不被调用,但中途会执行多次)
</div>
<div style="margin-top: 30px;">
<h2>3.防抖+节流</h2>
<hr/>
> 1.停,执行<br/>
> 2.动,执行 <br/>
> 3.(优点:几乎完美,缺点:逻辑稍微难一点) <br/>
> 4.(思路:在节流基础上,加防抖)
</div>
</div>
<script>
// 监听窗口滚动
// window.onscroll = debounce(showTop, 1000);
// window.onscroll = throttle(showTop, 1000);
window.onscroll = debounce_throttle(showTop, 1000);
// 要执行的函数
function showTop(){
let top = document.documentElement.scrollTop;
console.error('滚动条位置:', top);
}
// 防抖函数
function debounce(fn, delay){
let timer = null;
return function (){
if(timer){
// 又有一个调用进来了
// 如果存在,就清除
window.clearTimeout(timer);
}
// 马上建立下一个延时,只有停下来才执行一次
timer = setTimeout(fn, delay);
}
}
// 节流函数
function throttle(fn, delay){
// 上一次被触发时间
let lastName = Date.now()
// 先返回一个函数
return function(){
// 当前时间
let now = Date.now()
if(now - lastName > delay){
// 大于间隔时间了,执行
fn()
// 关键:本次执行完毕后,将当前时间赋值给上一次时间
lastName = now;
}
}
}
// 防抖+节流 (思路:在节流基础上,加防抖)
function debounce_throttle(fn, delay){
let timer = null;
let lastName = Date.now()
// 先返回一个函数
return function(){
let now = Date.now()
// 如果间隔时间够了(上一次距离这次的时间)
if(now - lastName > delay){
// 执行节流
fn()
// 交换时间,更新上一次时间
lastName = now
}else{
// 如果这时候又有调用进来了,马上清除
if(timer){
window.clearTimeout(timer);
timer = null;
}
// 如果时间还不够,保存最后一次,稍后执行
// 再间隔2秒,如果没触发,就执行:保证最后一次被执行
timer = setTimeout(fn, delay);
}
}
}
</script>
</body>
</html>