函数节流也是前端在监听处理高频事件时候,常用的优化方法,在不影响用户体验的情况下,限制事件触发的频率。常用的地方又页面 scorll, resize 事件,还有用户提交复杂表单,有时候会有定时保存草稿箱的功能,都可以使用函数节流来做优化。
定时器的实现方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var throttle2 = function(func, delay ){ var timer = null; return function() { var context = this; var args = arguments; if (timer ) { clearTimeout(timer ) } else { timer = setTimeout(function(){ func.apply (context ,args ); timer = null; }, delay ); } } }
时间戳的实现方式 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var throttle1 = function (func, delay ) { var prev = Date .now (); return function ( ) { var context = this; var args = arguments; var now = Date .now (); if (now - prev >= delay) { func.apply(context, args); prev = Date .now (); } }; };function handle ( ) { console .log (Math.random ()); } window.addEventListener("scroll" , throttle1(handle, 1000 ));
组合防抖节流 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 var throttle = function (fn, delay, mustRunDelay ) { let startTime = Date .now (); let timer = null ; let isFirst = true ; return function ( ) { let context = this ; let args = [].slice .call (arguments ); let remaining = mustRunDelay-(Date .now ()-startTime); clearTimeout (timer) if (remaining <= 0 ){ startTime = Date .now (); if (!isFirst){ fn.apply (context, args); } else { isFirst = false ; } } else { timer = setTimeout (function ( ){ fn.apply (context, args); },delay) } } }window .addEventListener ("scroll" , throttle (function ( ){console .log (1 )}, 1000 , 2000 ));
总结对比优缺点
定时器的实现,缺点:最后一次时间不够一次 delay 仍然会触发执行
时间戳的实现,缺点:时间不够一次 delay,不会触发执行, 第一次会立即执行
组合实现,添加 isFirst 标记,如果不加第一次触发事件会立即执行,添加标记过滤第一次执行,这样就可以完美实现了
当然这些都只是从代码逻辑上来考虑,具体还是要结合业务需求灵活使用。