函数节流也是前端在监听处理高频事件时候,常用的优化方法,在不影响用户体验的情况下,限制事件触发的频率。常用的地方又页面 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 标记,如果不加第一次触发事件会立即执行,添加标记过滤第一次执行,这样就可以完美实现了
当然这些都只是从代码逻辑上来考虑,具体还是要结合业务需求灵活使用。