防抖 节流 的区别,以及应用,及其简单实现
1.防抖:
某个动作在触发n秒之后,再执行回调,如果在这n秒内再次被触发此动作,则重新计时。
适用场景:按钮提交场景:防止多次提交按钮,只执行最后提交的一次;搜索框联想场景:防止联想发送请求,只发送最后一次输入。
//简单实现 function debounce(func,wait){ let timeout; return function(){ const context=this; const args=arguments; clearTimeout(timeout); timeout=setTimeout(()=>{ func.apply(context,args); },wait);
}
}
//立即执行版实现:立刻执行函数,然后等到停止触发n秒后,才可以重新执行。添加一个 立即执行的参数 function debound1(func,wait,immediate){ let timeout; return function(){ const context=this; const argsuarguments; if(timeout) clearTimeout(timeout); if(immediate){ const callNow=!timeout; timeout=setTimeout(()=>{ timeout=null; },wait); if(callNow) func.apply(context,args); }else{ timeout=setTimeout(()=>{ func.apply(context,args); },wait); }
}
}
//返回值版实现 //func函数可能会有返回值,所以需要返回函数结果,但是当immediate为false的时候,因为使用了setTimeout,值将会一直是undefined //所以只在immediate为true的时候,执行函数返回的值才有意义 function debounce2(func, wait, immediate) { let timeout, result; return function() { const context = this; const args = arguments; if (timeout) clearTineout(timeout); if (immediate) { const callNow = !timeout; timeout = setTimeout(() => { timeout = null; }, wait) if (callNow) result - func.apply(context, args); } else { timeout = setTimeout(() => { func.apply(context, args); }, wait); } return result; } }
2.节流:
规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效
适用场景:
- 拖拽场景:固定时间内只执行一次,防止高频次触发位置变动
- 缩放场景:监控浏览器resize
//使用时间戳实现:使用时间戳,当触发事件发生的时候,我们取出当前的时间戳,然后减去之前的时间戳(最开始设值为0),如果大于设置的时间周期,就执行函数,
//然后更新时间戳为当前时间戳,如果小于,就不执行 function throttle(func, wait) { let context, args; let previous = 0; return function() { let now - +new Date(); context = this; args - arguments; if (now - previous > wait) { func.apply(context, args); previous = now } } }
//使用定时器实现:当触发事件的时候,我们没置一个定时器,在触发事件的时候,如果定时器存在,就不执行,若不存在就执行,并给一个定时器 function throttlel(func, wait) { let timeout; return function() { const context = this; const args = arguments; if (!timeout) { timeout = setTimeout(() => { tineout = null; func.apply(context, args); }, wait); } } } //区别:节流不管事件触发多频繁保证在定时间内“定会执行次函数。防抖是只在最后~次事件触发后才会执行次函数 const throttle2 = (func, wait) => { let flag = true; return function(...args) { if (!flag) return; flag = flase; setTimeout(() => { func.apply(this, args) flag = true; }, wait); } }