1.直接上码
1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>debounce-throttle</title> 6 <script type="text/javascript"> 7 8 //节流函数:时间戳节流,规定时间内一定执行一次 9 function throttle(fn, delay){ 10 var prev = Date.now(); 11 return () => { 12 var context = this,args = arguments; 13 var now = Date.now(); 14 if(now - prev >= delay){ 15 fn.apply(context, args); 16 prev = Date.now(); 17 } 18 }; 19 } 20 //节流函数:定时器节流,规定时间内一定执行一次 21 function _throttle(fn, delay){ 22 var timer; 23 return () => { 24 var context = this,args = arguments; 25 if(!timer){ 26 timer = setTimeout(function(){ 27 fn.apply(context, args); 28 timer=null; 29 },delay); 30 } 31 }; 32 } 33 //事件触发时立即执行,触发完毕还能执行一次的节流函数: 34 function __throttle(fn, delay){ 35 var timer,prev = Date.now(); 36 return () => { 37 var context = this,args = arguments; 38 var now = Date.now(); 39 clearTimeout(timer); 40 if(delay - (now - prev) <= 0){ 41 fn.apply(context, args); 42 prev = Date.now(); 43 }else{ 44 timer = setTimeout(function(){ 45 fn.apply(context, args); 46 },delay); 47 } 48 }; 49 } 50 //防抖函数:规定一定时间后只执行一次fn 51 function debounce(fn, delay){ 52 var timer; 53 return () => { 54 var context = this,args = arguments; 55 clearTimeout(timer); 56 timer = setTimeout(function(){ 57 fn.apply(context, args); 58 },delay); 59 }; 60 } 61 //防抖函数:立即执行然后一定时间后只执行一次fn 62 function _debounce(fn, delay, flag){ 63 var timer; 64 return () => { 65 var context = this,args = arguments; 66 clearTimeout(timer); 67 if(flag){ 68 var now = !timer; 69 timer = setTimeout(function(){ 70 timer = null; 71 },delay); 72 if(now){ 73 fn.apply(context, args); 74 } 75 }else{ 76 timer = setTimeout(function(){ 77 fn.apply(context, args); 78 },delay); 79 } 80 }; 81 } 82 function printLog(){ 83 var date = new Date(); 84 var second = date.getSeconds(),milliseconds=date.getMilliseconds(); 85 console.log('printLog:'+second+' ' +milliseconds); 86 } 87 window.onload = function(){ 88 document.getElementById('div').addEventListener('click', throttle(printLog,1000)); 89 } 90 91 </script> 92 </head> 93 <body> 94 <div id="div" style="200px;height:160px;background-color: yellow;"></div> 95 </body> 96 </html>
2.总结
防止一个事件频繁触发回调函数的方式:
防抖动:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
节流:使得一定时间内只触发一次函数。
它和防抖动最大的区别就是,节流函数不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而防抖动只是在最后一次事件后才触发一次函数。
原理是通过判断是否到达一定时间来触发函数,若没到规定时间则使用计时器延后,而下一次事件则会重新设定计时器。
3.参考资料
https://blog.csdn.net/crystal6918/article/details/62236730
http://www.ptbird.cn/javascript-anti-shake-throttle.html