今天和别人聊到JavaScript函数的节流和防抖,发现自己对这两个的区别很是模糊,遂小小实践一下,在此记录,希望对需要的人有所帮助。
节流 - 频繁操作,间隔一定时间去做一件事
举例说明:假定时间间隔为 500ms,频繁不停的操作 2s,且每两次执行时间小于等于时间间隔 500ms,那么就会执行 4 次,也就是每隔 时间间隔 500ms 执行一次。
防抖 - 频繁操作,一定时间间隔内只执行最后一次操作
举例说明:假定时间间隔是 500ms,频繁不停的操作 5s,且每两次执行时间小于等于时间间隔 500ms,那么最后只执行了 1 次,也就是每一次执行时都结束了上一次的执行。
代码示例
//节流方法 1function throttle1(method, duration){var prevTime = new Date();return function () {var context = this,currentTime = new Date(),resTime = currentTime - prevTime;//打印出本次调用方法和上次执行方法的时间差console.log("时间差"+resTime);//当本次调用距离上次执行方法的时间差大于等于要求时间间隔时,执行一次方法if(resTime >= duration){method.apply(context);//记录执行方法的时间prevTime = currentTime;}}}//节流方法 2function throttle2(method, duration){//当前时间间隔内是否有方法在执行(或者说方法的调用是否在进行)var runningFlag = false;return function (e) {// 判断当前是否有方法在执行,有,则什么都不做if (runningFlag) {return false;}//开始执行runningFlag = true;setTimeout(function(){method(e);//执行完毕,声明当前没有正在执行的方法,方便下一个时间间隔内的调用runningFlag = false;}, duration)}}//防抖function debounce(method, duration){var timer = null;return function(){var context = this,args = arguments;//在本次调用之前的一个间隔时间内,有方法在执行,则终止该方法的执行if(timer){clearTimeout(timer);}//开始执行本次调用timer = setTimeout(function(){method.apply(context, args);},duration);}}//模拟三个执行方法function jieliu1(){console.log("节流 1");}function jieliu2(){console.log("节流 2");}function fangdou(){console.log("防抖");}//持续执行时间var totalTime = 2000;var jieliuFn1 = throttle1(jieliu1,500);var jieliuFn2 = throttle2(jieliu2,500);var fangdouFn = debounce(fangdou,500);(function(duration){setInterval(function(){if( totalTime > 0 ){jieliuFn1();jieliuFn2();fangdouFn();totalTime -= duration;}},duration);})(100);
运行结果
时间差 100
时间差 201
时间差 303
时间差 401
时间差 504
节流 1
时间差 98
节流 2
时间差 199
时间差 300
时间差 396
时间差 496
时间差 597
节流 1
时间差 100
节流 2
时间差 203
时间差 299
时间差 402
时间差 500
节流 1
时间差 103
时间差 204
节流 2
时间差 303
时间差 400
节流 2
防抖
结论
由以上运行结果可以看出,节流1 出现了 3 次,节流2 出现了 4 次,防抖出现了 1 次。防抖实现顺利,但是两个节流方法的执行结果存在差异。
观察时间差可以看出,每次节流1 执行时,时间差并不会都是 500 整,也就是说,一共调用 2 秒时,节流1 并不能做到每隔 500 毫秒执行一次而共执行 4 次,第四次执行往往因为前面的 3 次执行的时间误差,而导致到达时间 2 秒时,最后一次的时间差无法达到 时间间隔 500ms 以上,以至于只能执行 3 次。
结论:当在一个大范围的时间内,比如两小时内,每几分钟执行一次,超过2小时则不再实行,推荐使用第一种节流方式,;如果仅仅要求间隔一定时间执行一次,推荐使用第二种节流方法;防止频繁操作,比如表单多次提交,推荐使用防抖。