函数防抖是频繁发生的状况下,当有足够的空闲时间,才会执行代码一次,是优化高频率执行代码的一种手段。实际开发中会遇到频发触发事件的状况,好比 resize
, scroll
, mousemove
事件。html
事件触发 n 秒后执行,若是在这 n 秒内再次触发,则以新的事件时间为准,n 秒后执行。不管触发多少次,都要等到最后一次触发 n 秒后才执行。app
用 mousemove
举例,当鼠标移入时,在 div
内显示事件函数执行的次数。防抖的简单实现以下:函数
<div id='container'></div>
let count = 0; let oDiv = document.querySelector('#container'); //防抖函数 function debounce(fn, delay) { let timer; return function() { clearTimeout(timer); timer = setTimeout(fn, delay); } } //事件函数 function eventFn() { oDiv.innerHTML = ++count; } oDiv.onmousemove = debounce(eventFn, 1000);
正常状况下,在事件函数中使用 this
指向该事件绑定的元素。而此时 eventFn
是做为定时器的一个参数,this
指向 window
,须要更正 this
指向。优化
function debounce(fn, delay) { let timer; return function() { let _this = this; clearTimeout(timer); timer = setTimeout(function () { fn.apply(_this); }, delay); } }
通常状况下,事件函数 eventFn
的第一个参数为 event
对象,但此时,值为 undefined
。修改防抖函数:this
function debounce(fn, delay) { let timer; return function() { let _this = this; let opt = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.apply(_this, arguments); }, delay); } }
防抖函数中使用了定时器,事件触发后会延迟必定时间才调用事件函数,有时咱们但愿触发事件能够当即执行,而后须要 n 秒后才能从新触发执行。咱们经过传入第三个参数,判断是否须要当即执行。code
function debounce(fn, delay, immediate) { let timer; return function() { let _this = this; let opt = arguments; timer && clearTimeout(timer); if(immediate) { let call = !timer; timer = setTimeout(function() { timer = false; }, delay); call && fn.apply(_this, opt); } else { timer = setTimeout(function() { fn.apply(_this, opt); }, delay); } } }