本文着中讲述防抖与节流的实现原理。
那么在开始实际代码之前,我们先来说说防抖与节流的本质意思。
1.防抖:在一段时间内,用户不断通过浏览器实现某些功能太过频繁,我们想实现直至用户在一段时间内不再触发某个事件后,我们再执行并实现该功能。
2.节流:在一段时间内,用户通过频繁调用某项功能,而我们只选择一次完成后就不再执行第二次,以达到节省流量的效果。
<script>
//防抖
//获取input标签节点
var input = document.getElementsByClassName("input")[0]
//先执行外部函数,由于还未调用内部函数故不输出
var debounceFunc = debounce(2000)
//监听键盘的按键抬起事件,回调函数的参数为源事件
input.addEventListener("keyup",function(e){
//调用内部函数
debounceFunc(e.target.value)
})
//封装防抖函数
function debounce(delay){
let timer
//在此处定义闭包(也就是在函数中返回一个函数),以达到将函数暴漏出去,并借此将timer这个变量全局化。
//如果没有闭包,每次进入debounce函数的timer都是最初始的undefined,故无法达到清除定时器的效果。
return function(value){
//此时第一次进入时timer是undefined,第二次之后则可以清除外部函数残留的上一次timer计时器,取消执行上一次。
clearTimeout(timer)
//timer真正完全执行并渲染将会是最后一次timer
timer = setTimeout(function(){
console.log(value)
},delay)
}
}
</script>
2.节流函数演示如下
html
<button id="btn">节流按钮</button>
js
function runThro(){
console.log("我是要节流执行的函数")
}
document.getElementById("btn").onclick = saveThro(2000,runThro)
function saveThro(delay,func){
let timer
return function(){
//判断是否为timer是undefined时进入该函数
if(!timer){
//此时timer为undefined
timer = setTimeout(function(){
//进入定时器,delay期间都在执行这个函数,重复点击是不会触发同时执行的
func()
//运行到此处,则想调用的函数已经执行完毕,把timer重新修改为undefined,等待下一个delay期间的函数被调用。
timer = null
},delay)
}
}
}
由此可知: 1.在防抖函数中,被执行的是最后一次调用的函数,而在节流函数中,被执行的是一段事件内第一次被调用的函数。 2.防抖函数之前的所有触发的事件全都被完全取消,最后一次没被取消,所以执行。 3.而节流函数则是第一次才符合判断条件执行,后面调用的所有事件都因timer被占用而无法执行,必须等到第一次调用的函数执行完毕后,timer重新释放,在下一个时间的第一次调用才可以顺利执行,用这样的方式来达到节流的效果。