在面试中常见手写之防抖节流函数
防抖
防抖:在触发一次函数后的规定时间内,如果没有再次触发,才执行。 比如电梯进门,一直进就不关闭。只执行最后一次
节流
节流:一段时间内连续触发,在规定时间内只执行一次,控制高频事件执行次数。比如拖动滚动条,不用节流就会触发非常多次(技能cd)
重点
函数中的this指向问题
在settimeout中调用fun,fun的上下文会指向window,显然不正确。而且fun传入的参数也没有
所以要使用args记录fun传入时的参数
this则是使用箭头函数记录return function(){}的作用域,function(){}不使用箭头函数,this指向为和window
手写防抖函数
<body>
<button id="btn">按钮,一直按就不会加,停止然后等待1秒就会得出结果</button> <!-- 按钮实现 -->
<script>
function debounce(fun,wait){
let args = [...arguments]
let timeout
return function(){ //这里不能使用箭头函数,
clearTimeout(timeout)
timeout = setTimeout(() => {
fun.apply(this,args)
}, wait);
}
}
let count=0
let btn=document.getElementById("btn")
function add(e){
count++
console.log(count)
}
btn.addEventListener('click',debounce(add,1000))
</script>
</body>
手写节流函数
时间戳版本
function throttle(fun,wait){ //节流函数时间cuo版本
let args = [...arguments]
let pretime = 0
return function(){
let now = new Date().getTime()
if( now - pretime > wait ){//如果现在减去过去的时间大与等待cd,就执行
fun.apply(this,args)
pretime = now
}
}
}
还有计时器方法
function myThrottle(fn, delay) {
let timer = null;
return function () {
// 这儿是重点 如果时间没到 那么 timer 就不为 null 就会返回 不会往下执行!!!
if (timer) {
return
};
timer = setTimeout(() => {
// 时间到了 timer 被设置为null 就走到这儿来了 就会执行
fn.apply(this, arguments)
timer = null
}, delay);
}
};
// 综合上面两步 就实现了 英雄 技能cd 一样的节流
防抖函数中闭包起了什么作用?
防抖是闭包的重要应用例子之一,主要是timeout变量的保留上 在防抖函数中,闭包用来保存定时器的timeout(id),在每次函数被调用后,通过闭包中的定时器ID可以清除之前的定时器,从而避免函数被频繁触发。这样就能确保在一定的时间间隔内只执行一次函数,实现了防抖的效果。