解决频繁触发事件的操作。性能优化 click
防抖应用场景:resize、登录、输入内容后长时间没有操作,只执行最后一次保存。
节流应用场景:scroll每隔一秒计算一下位置信息、浏览器播放每隔一秒计算一次进度条、input的实时查询展示下拉框。
onmousemove、resize、onscroll时触发
防抖:事件响应函数在一段时间后才执行,如果在这段事件内再次调用,则重新计算执行时间。当在预定时间内没有再次调用该函数,则执行响应逻辑
//dobounce
//在触发响应逻辑的时候触发debounce函数
//container.onmousemove = debounce(dosomethig,wait)
//原理:通过settimeout的方式,在一定时间间隔内将多次触发变成一次触发
//两种
//最后一次才执行
//debounce 形成一个闭包,每次执行触发的函数都从保重寻找timeout
function debounce(fn,delay){//不管点击多少次,debounce只执行一次,即只执行一次绑定监听事件,后续触发所监听事件只执行返回的函数
let timer = null //借助闭包,仅声明一次该变量
return function() {
if(timer){
clearTimeout(timer) //进入该分支语句,说明当前正在一个计时过程中,并且又触发了相同事件。所以要取消当前的计时,重新开始计时
timer = setTimeout(fn,delay)
}else{
timer = setTimeout(fn,delay) // 进入该分支说明当前并没有在计时,那么就开始一个计时
}
}
}
//第一次的时候执行
function debounce(fn,wait){ //
var timeout=null;
return function(){//因为onmousemove的时候需要执行一个函数,所以返回一个函数
var firstClick = !timeout //firstClick只有在一个阶段的第一次为true
if( timeout){//只有一个阶段的第一次不走这
clearTimeout(timeout)//清除掉上一个定时器
}
//第一次
if(firstClick){
fn.apply(this,arguments)
}
timeout = setTimeout(()=>{ //最后一次抖动设置的定时器走完,timeout为空,再进入到防抖时又可以走firstclick分支
timeout = null
},wait)
}
}
//throttle:减少一段时间的触发频率
function throttle(fn,delay){
var brgin =0 //同样只声明一次
return function(){
var cur = new Date().getTime();
if(cur-begin > delay){
fn.apply(this,arguments)
begin = cur
}
}
}