应用场景:
1、当用户提交表单时,多次点击提交按钮
2、拖拽时的mousemove,window对象的resize、scroll,文字输入等事件触发了大量的回调函数
描述:
函数防抖: 当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间
适合多次事件一次响应的情况
函数节流: 当调用动作过n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作,则不理。若在这n毫秒之后又调用此动作,则进入下一个新周期
适合大量事件按时间做平均分配触发
function log(){ console.log(1) } function debounce(fn,wait){ var timer = null; return function () { var context = this var args = arguments if (timer) { clearTimeout(timer); timer = null; } timer = setTimeout(function () { fn.apply(context, args) }, wait) } } window.onscroll = debounce(log,500)
debounce函数存在一个缺点,当我们一直在滚动页面,那log方法就一直不执行。可升级一下上述的防抖方法,如updateDebounce函数
function updateDebounce(fn,wait,time){ var previous = null; //记录上一次运行的时间 var timer = null; return function(){ var now = +new Date(); if(!previous) previous = now; //当上一次执行的时间与当前的时间差大于设置的执行间隔时长的话,就主动执行一次 if(now - previous > time){ clearTimeout(timer); fn(); previous = now;// 执行函数后,马上记录当前时间 }else{ clearTimeout(timer); timer = setTimeout(function(){ fn(); },wait); } } } window.onscroll = updateDebounce(log, 500, 2000);
function throttle(fn, time) { let _self = fn, timer, firstTime = true //记录是否是第一次执行的flag return function() { let args = arguments, //解决闭包传参问题 _me = this //解决上下文丢失问题 if(firstTime) { //若是第一次,则直接执行 _self.apply(_me, args) return firstTime = false } if(timer) { //定时器存在,说明有事件监听器在执行,直接返回 return false } timer = setTimeout(function() { clearTimeout(timer) timer = null _self.apply(_me, args) }, time || 500) } } window.onscroll = throttle(log,500)
原链接:https://blog.liujiefront.com/2018/04/27/throttle-debounce/