一、throttle
函数节流,指把很小时间内触发的N多事件,节流成1个事件。
我们这里说的throttle就是函数节流的意思。再说的通俗一点就是函数调用的频度控制器,是连续执行时间间隔控制。主要应用的场景比如:
- 鼠标移动,mousemove 事件
- DOM 元素动态定位,window对象的resize和scroll 事件
有人形象的把上面说的事件形象的比喻成机关枪的扫射,throttle就是机关枪的扳机,你不放扳机,它就一直扫射。我们开发时用的上面这些事件也是一样,你不松开鼠标,它的事件就一直触发。
简单的实现:
1 var resizeTimer=null; 2 $(window).on('resize',function(){ 3 if(resizeTimer){ 4 clearTimeout(resizeTimer) 5 } 6 resizeTimer=setTimeout(function(){ 7 console.log("window resize"); 8 },400); 9 } 10 );
setTimeout和clearTimeout其实就是一个简单的 throttle,很多好的控制了resize事件的调用频度。
二、debounce
间隔控制,指在一定时间内,指定的事件最多被触发一次。
debounce和throttle很像,debounce是空闲时间必须大于或等于 一定值的时候,才会执行调用方法。debounce是空闲时间的间隔控制。比如我们做autocomplete,这时需要我们很好的控制输入文字时调用方法时间间隔。一般时第一个输入的字符马上开始调用,根据一定的时间间隔重复调用执行的方法。对于变态的输入,比如按住某一个建不放的时候特别有用。
debounce主要应用的场景比如:
- 文本输入keydown 事件,keyup 事件,例如做autocomplete
这类网上的方法有很多,比如Underscore.js就对throttle和debounce进行封装。jQuery也有一个throttle和debounce的插件:jQuery throttle / debounce,所有的原理时一样的,实现的也是同样的功能。再奉上一个自己一直再用的throttle和debounce控制函数:
1 /* 2 * 频率控制 返回函数连续调用时,fn 执行频率限定为每多少时间执行一次 3 * @param fn {function} 需要调用的函数 4 * @param delay {number} 延迟时间,单位毫秒 5 * @param immediate {bool} 给 immediate参数传递false 绑定的函数先执行,而不是delay后后执行。 6 * @return {function}实际调用函数 7 */ 8 var throttle = function (fn,delay, immediate, debounce) { 9 var curr = +new Date(),//当前事件 10 last_call = 0, 11 last_exec = 0, 12 timer = null, 13 diff, //时间差 14 context,//上下文 15 args, 16 exec = function () { 17 last_exec = curr; 18 fn.apply(context, args); 19 }; 20 return function () { 21 curr= +new Date(); 22 context = this, 23 args = arguments, 24 diff = curr - (debounce ? last_call : last_exec) - delay; 25 clearTimeout(timer); 26 if (debounce) { 27 if (immediate) { 28 timer = setTimeout(exec, delay); 29 } else if (diff >= 0) { 30 exec(); 31 } 32 } else { 33 if (diff >= 0) { 34 exec(); 35 } else if (immediate) { 36 timer = setTimeout(exec, -diff); 37 } 38 } 39 last_call = curr; 40 } 41 }; 42 43 /* 44 * 空闲控制 返回函数连续调用时,空闲时间必须大于或等于 delay,fn 才会执行 45 * @param fn {function} 要调用的函数 46 * @param delay {number} 空闲时间 47 * @param immediate {bool} 给 immediate参数传递false 绑定的函数先执行,而不是delay后后执行。 48 * @return {function}实际调用函数 49 */ 50 51 var debounce = function (fn, delay, immediate) { 52 return throttle(fn, delay, immediate, true); 53 };
更多阅读: