-
转载
让某个函数在一定 事件间隔条件(去抖debounce) 或 时间间隔条件(节流throttle) 下才会去执行,避免快速多次执行函数(操作DOM,加载资源等等)给内存带来大量的消耗从而一定程度上降低性能问题。
debounce: 当调用动作n毫秒后,才会执行该动作,若在这n毫秒内又调用此动作则将重新计算执行时间。
debounce使用场景:
- scroll事件(资源的加载)
- mouseover事件(拖拽)
- resize事件(响应式布局)
- keyup事件(输入框文字停止打字后再进行校验)
方法实现:
/** * 防反跳。fn函数在最后一次调用时刻的delay毫秒之后执行! * @param fn 执行函数 * @param delay 时间间隔 * @param isImmediate 为true,debounce会在delay时间间隔的开始时立即调用这个函数 * @returns {Function} */ function debounce(fn, delay, isImmediate) { var timer = null; //初始化timer,作为计时清除依据 return function() { var context = this; //获取函数所在作用域this var args = arguments; //取得传入参数 clearTimeout(timer); if(isImmediate && timer === null) { //时间间隔外立即执行 fn.apply(context,args); timer = 0; return; } timer = setTimeout(function() { fn.apply(context,args); timer = null; }, delay); } } /* 方法执行e.g. */ var btn = document.getElementById('btn'); var el = document.getElementById('display'); var init = 0; btn.addEventListener('click', debounce(function() { init++; el.innerText = init; }, 1000,true));
- 截流
throttle:预先设定一个执行周期,当调用动作的时刻大于等于执行周期则执行该动作,然后进入下一个新周期。
throttle使用场景:
- click事件(不停快速点击按钮,减少触发频次)
- scroll事件(返回顶部按钮出现隐藏事件触发)
- keyup事件(输入框文字与显示栏内容复制同步)
- 减少ajax请求,降低请求频率
方法实现:
/** * 创建并返回一个像节流阀一样的函数,当重复调用函数的时候,最多每隔delay毫秒调用一次该函数 * @param fn 执行函数 * @param delay 时间间隔 * @returns {Function} */ function throttle(fn, delay) { var timer = null; var timeStamp = new Date(); return function() { var context = this; //获取函数所在作用域this var args = arguments; //取得传入参数 if(new Date()-timeStamp>delay){ timeStamp = new Date(); timer = setTimeout(function(){ fn.apply(context,args); },delay); } } } /* 方法执行 */ var btn = document.getElementById('btn'); var el = document.getElementById('display'); var init = 0; btn.addEventListener('click', throttle(function() { init++; el.innerText = init; }, 1000));
或者:
function throttle(fn, threshhold, scope) { threshhold || (threshhold = 250); var last, deferTimer; return function () { var context = scope || this; var now = +new Date(), args = arguments; if (last && now < last + threshhold) { // hold on to it clearTimeout(deferTimer); deferTimer = setTimeout(function () { last = now; fn.apply(context, args); }, threshhold); } else { last = now; fn.apply(context, args); } }; }