javascript 函数节流

1. 函数节流的概念,意义就不多说了,看腾讯web前端AlloyTeam团队的文章,清晰易懂。给个地址:

http://www.alloyteam.com/2012/11/javascript-throttle/

2.文章中给出3个节流的例子,但是实际项目中需要升级到节流版本的javascript函数太多了,总不能一个个对葫芦画瓢,每个函数依次修改吧。习惯 Python装饰器了,决定写一个通用的javascript函数,能够将其他函数简单的包装之后,使其他函数变为节流版本。

上代码:

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为同步响应
}

此时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;
 	}
}



你可能感兴趣的:(JavaScript,函数节流)