函数节流与去抖
https://github.com/hahnzhu/read-code-per-day/issues/5
又被坑了。。。
函数节流
函数节流英文为 throttle,其翻译是「节流阀、压制、减速」,很形象地表达了它的作用就是控制函数的调用频度,但为什么需要减少函数的调用频度呢?因为某些场景下一些 DOM 事件会鬼畜般触发(如 mousemove、scroll、resize 等);或者一个抽奖页中,某个人帕金森综合征病发般点击抽奖按钮。这个时候假如事件绑定了函数的话,就会频繁调用,甚至导致某些浏览器奔溃(一种叫 IE 的浏览器)。
函数节流的原理
函数节流应用非常广,在很多源码中都会出现。其原理就是定时器。当事件触发时,通过 setTimeout
让这个事件延迟一会再执行,如果在这个时间间隔内该事件又被触发了,那就 clear 掉原来的定时器,重新setTimeout
一个新的定时器延迟一会执行,就酱紫。上代码:
1、就是这样实现
var resizeTimer = null; $(window).on('resize', function () { /* 第一次访问,不存在 resizeTimer,跳过这里 */ if (resizeTimer) { clearTimeout(resizeTimer); } /* 第一次访问,赋值给 resizeTimer,绑定的函数 400ms 后调用 */ resizeTimer = setTimeout(function(){ console.log("window resize"); }, 400); }); var touchMoveTimer = null; $(window).on("touchmove",function(){ /* 第一次访问,不存在 resizeTimer,跳过这里 */ if (touchMoveTimer) { clearTimeout(touchMoveTimer); } /* 第一次访问,赋值给 resizeTimer,绑定的函数 400ms 后调用 */ touchMoveTimer = setTimeout(function(){ console.log("touchmove..."); }, 400); });
2、《JavaScript高级程序设计》
function throttle(method, context) { console.log(method.tId); clearTimeout(method.tId); method.tId = setTimeout(function(){ method.call(context); }, 300); };
下面是我的调用方法:
$(window).on("touchmove",function(){ throttle(function(){ //每次都是不同的function console.log("touchmove-----inner"); }); });
明显错了,因为touchmove的时候执行throttle。传进去的method每次都是一个新的函数啊。。。
类似下面这个。。
$(window).on("touchmove",function(){ var a = function(){ console.log("touchmove-----inner"); }; throttle(a); });
正确的姿势是:
var a = function(){ console.log("touchmove-----inner"); }; $(window).on("touchmove",function(){ throttle(a); });
3、impress.js实现
var throttle2 = function(fn, delay){ var timer = null; return function(){ var context = this, args = arguments; clearTimeout(timer); timer = setTimeout(function(){ fn.apply(context, args); }, delay); } } var myFunc = function(){ console.log("touchmove--inner"); }; $(window).on("touchmove",throttle2(myFunc, 400))