上代码:
var throttle = function(targetFunc, delay, mustRunDelay) { var throttleInstance = { timer: null, lastTime: 0, context: null, args: null, delay: function(context, args) { clearTimeout(this.timer); var currentTime = +new Date(); if(!this.lastTime) { this.lastTime = currentTime; } this.context = context; this.args = args; if(currentTime - this.lastTime >= mustRunDelay) { this.doAction(); } else { this.timer = setTimeout(this.timerHandler, delay); } }, doAction: function() { targetFunc.apply(this.context, this.args); this.lastTime = 0; }, timerHandler: function() { throttleInstance.doAction(); } }; return function() { throttleInstance.delay(this, arguments); }; };
使用举例:
1. 包装单独的裸函数
比如需要监听浏览器窗口大小变化事件,每次变化输出一个字符串。
window.onresize = throttle(function(){ console.log("resized..."); }, 500, 3000 );
2. 包装全局变量的共有方法
var listener = new Object(); listener.mouseover = function(e){ console.log("mouseover"); } listener.click = function(e){ console.log("click"); }有如上 listener全局变量,以及其click和mouseover两个公有方法,两个方法都是即时响应
document.getElementById('test').onclick = throttle(listener.click, 500, 3000); //或者 document.getElementById('test').onmouseover = function() { return throttle(listener.mouseover, 500, 3000); }();//括号不能掉
经过如上包装后,即为节流版本
3.在prototype构造的对象内部包装其公有方法
var Typeahead = function (element, options) { //do something init... } Typeahead.prototype = { constructor: Typeahead, keyup: function () { console.log("keyup"); }//keyup为同步响应 }
Typeahead.prototype = { constructor: Typeahead, doKeyUp: function () { console.log("keyup"); }, keyup: throttle(function(e){ this.realDoKeyUp(e) }, 500, 3000) //务必用一层匿名函数嵌套this.realDoKeyUp, 因为在throttle层面访问不到this }
4.在非prototype方式构造的对象内部包装其公有方法
var HighChartDrawer = { createNew: function (containerId, conf) { var drawer = {}; drawer.init = function() { //do something init... }; drawer.listenSelectChange = function () { console.log("change..."); }//listenSelectChange同步响应 return drawer; } }此时drawer对象的listenSelectChange是即时响应的,如下改变后成为节流版本
var HighChartDrawer = { createNew: function() { var drawer = {}; drawer.init = function() { //do something init... }; drawer.DoSelectChange = function() { console.log("change..."); }, drawer.listenSelectChange = throttle(function () { drawer.DoSelectChange(); //转一次手,转而调用真正响应函数 DoSelectChange }, 500, 3000) return drawer; } }或者
var HighChartDrawer = { createNew: function(containerId, conf) { var drawer = {}; drawer.init = function() { //do something init... }; drawer.DoSelectChange = function() { console.log("change..."); }, drawer.listenSelectChange = throttle(drawer.DoSelectChange, 500, 3000) return drawer; } }