前言: 防抖和节流都是防止函数多次调用,在时间轴上控制函数的执行次数。 函数防抖(debounce) 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时,先计算时间后执行。 生活中的实例:有人进入电梯,电梯则在10秒后自动关门,如果10秒内又有人进入电梯,则电梯重新计时,自动关门。 function debounce(fn, delayTime) { let timer = null return function (args) { if (timer) { timer = null clearTimeout(timer) } let _this = this let _args = args timer = setTimeout(function () { fn.call(_this, _args) }, delayTime) } } let inputDom = document.getElementById('input2') inputDom.addEventListener('keyup', debounce((e) => {console.log(e.target.value)}, 1000)) 防抖原理 为了减少频繁发生的事件的资源请求,防抖是通过在用户没有操作的情况下,如果在等待时间内用户没有操作,则执行回调,如果有操作,继续等待相应时间间隔。所以在闭包函数内,初始化一个时间参数timer,如果timer为空,则表示回调事件没执行或者已执行完毕,代表在等待时间内用户没有操作,相反,如果timer不为null,清空timer,重新计时。 函数节流(throttle) n秒内回调函数只会被执行一次,先执行后计算。 setTimeout实现函数节流 function throttle(fn, wait) { var timer = null if (timer) return return function() { let _this = this let args = arguments timer = setTimeout(function() { fn.apply(_this, args) timer = null }, wait) } } 时间差实现函数节流 function throttle(fn, wait) { var lastTime = 0 return function() { let _this = this let args = arguments let nowTime = new Date() if (nowTime - lastTime > wait) { fn.apply(_this, args) lastTime = nowTime } } } 节流原理 函数节流的目的是为了让函数在特定时间内疚执行一次,这也是setTimeout的设计初衷,所以可以直接用setTimeout实现,当然执行完回调一定要将timer置空。另外一种思路就是计算触发时间和执行时间的差值,大于再执行回调。 总结 函数防抖就是特定时间内触发动作的话,重新计时。函数节流是特定时间内触发动作只会有一次回调。 所以函数防抖适用的场景:监听窗口的滚动,缩放。高频发生的一些事件。 函数节流适用的场景:涉及与后端交互的按钮,由于网络原因或者其他原因,导致接口没有返回值,用户一直点点点的问题。