前言
防抖和节流是面试官最喜欢问的问题之一,那么我们怎么手写实现它们呢?下面我们一起来探究!
防抖(Debounce)
防抖是指在触发一次函数后的规定时间内没有再次触发,才执行。也就是在n秒内无论你触发多少次事件只响应最后一次,如果在规定时间内再次触发,则会重新计算时间。
案例1:
正常情况下每一次点击按钮后都会触发执行
<body>
<button id="btn">0</button>
<script>
let count=0 //记录点击次数
let btn=document.getElementById("btn") //获取DOM结构
function add(){
console.log(count);
btn.innerHTML=count++ //每点击一次++
}
btn.addEventListener('click',add)//给btn绑定监听事件
</script>
</body>
效果:
改成防抖后,只会执行规定时间内最后一次,也就是连续点击多次后之后并不会发送请求,只有在执行规定时间内没有再次触发才执行。
思路: 利用clearTimeout和setTimeout实现
<body>
<button id="btn">0</button>
<script src="./debounce.js"></script> //引入防抖js
<script>
let count=0 //记录点击次数
let btn=document.getElementById("btn") //获取DOM结构
function add(e){
// console.log(this);
console.log(count);
btn.innerHTML=count++ //每点击一次++
return 123//希望返回结果
}
// btn.addEventListener('click',add)
btn.addEventListener('click',debounce(add,1000))//防抖动 给btn绑定监听事件
// btn.addEventListener('click',throttle(add,2000))//节流
</script>
</body>
//debounce.js
function debounce(func,wait){
let timeout,result
return function(){
console.log(this);//this指向btn
let args=[...arguments]//获取到function中传的所有参数
clearTimeout(timeout) //每次执行前清空之前的定时器
timeout= setTimeout(()=>{ //形成了闭包
result=func.apply(this,args)//此时this和当前函数this相同
},wait)//定时器会修改this指向 定时器词法环境大多数都是window
return result //有无返回值取决于add 函数有无返回值
}
}//一个函数内部的this必然是函数的this
效果:
节流(Throttle)
不同于防抖——只有停下来不干才执行,节流就是连续触发的事件每隔规定时间只执行一次。
案例2:
思路: 利用时间戳实现。
<body>
<button id="btn">0</button>
<script src="./throttle.js"></script>
<script>
let count=0 //记录点击次数
let btn=document.getElementById("btn") //获取DOM结构
function add(e){
// console.log(this);
console.log(count);
btn.innerHTML=count++ //每点击一次++
return 123//希望返回结果
}
// btn.addEventListener('click',add)
// btn.addEventListener('click',debounce(add,1000))//防抖动
btn.addEventListener('click',throttle(add,2000))//节流
</script>
</body>
//引入throttle.js
function throttle(func,wait){
let preTime=0 //上次时间
return function(){
let args=[...arguments] //获取到function中传的所有参数
let now=+new Date() //时间戳 精准到秒
if(now-preTime>wait){ //判断现在点击的时间和上一次点击的时间是否在规定wait时间范围内
func.apply(this,args)
preTime=now //更新上一次时间
}
}
}
效果:
防抖和节流
相同点:
- 都是减少页面上没有必要的操作,一些可能多次手误的操作或手抖导致的没有必要的代码执行。
不同点:
- 防抖是将连续多次触发直到最后不触发了才执行一次;
- 节流是将连续多次触发变成每隔一段时间执行一次。
应用场景
防抖:
- 搜索框搜索输入。只有用户最后一次输入完,再发送请求
- 手机号、邮箱验证输入检测
节流:
- 监听页面的滚动事件
- 鼠标移动事件
总结
本篇文章就到此为止啦,由于本人经验水平有限,难免会有纰漏,对此欢迎指正。如觉得本文对你有帮助的话,欢迎点赞收藏❤❤❤,您的点赞是持续写作的动力,感谢支持。