`
jianguang_qq
  • 浏览: 90739 次
  • 性别: Icon_minigender_1
  • 来自: 深圳南山
社区版块
存档分类
最新评论

【JS优化系列】从一个计时器的写法探讨js多种实现方式的优劣

阅读更多

      前几天帮erricwang写一个js计时器,发现可以用有很多种方式实现相同的功能。现将它写下来,和大家一起探讨分析比较。

 

实现一:

<body>
<div id="time1">time1</div>
<div id="time2">time2</div>
</body>
<script>
function Timer(id){
	this.id = id;
	this.begin = function(count){
		this.show(this.id, count)();
		setInterval(this.show(this.id, count-1),1000);
	}
	this.show = function(id, count){
		return function(){
			document.getElementById(id).innerHTML = count<0 ? "over" :count;
			count--;
		}
	}
} 

t1 = new Timer("time1");
t1.begin(50);

t2 = new Timer("time2");
t2.begin(10);
</script>

 

   且看第一种实现,显然这里有一个很不好的地方,计时完成之后,setInterval没有被clear,严重影响了性能。

 

实现二:

function Timer(id){
	this.id = id;
	this.timer = null;
	this.count = 0;
	this.begin = function(count){
		this.count = count;
		this.show(this)();
		this.timer = setInterval(this.show(this),1000);
	}
	this.show = function(obj){	
		return function(){
			if(obj.count < 0){
				document.getElementById(obj.id).innerHTML = "over";
				clearInterval(obj.timer);
				return ;
			}
			document.getElementById(obj.id).innerHTML = obj.count;
			obj.count--;
		}
	}
} 

       实现二解决了实现一的setInterval未被clear的问题,看上去也很“完美”,且看下面:

alert(t1.show == t2.show) //结果false
alert(t1.begin == t2.begin) //结果false

      很明显这里Timer每个实例都复制了一份show和begin,二不是共享同一份的,所以t1.showt和2.show所指向的并非同一份实现,这样对性能多少会有些影响。

 

实现三:

function Timer(id){
	this.id = id;
	this.timer = null;
	this.count = 0;
	this.begin = function(count){
		this.count = count;
		Timer.show(this)();
		this.timer = setInterval(Timer.show(this),1000);
	}
	Timer.show = function(obj){	
		return function(){
			if(obj.count < 0){
				document.getElementById(obj.id).innerHTML = "over";
				clearInterval(obj.timer);
				return ;
			}
			document.getElementById(obj.id).innerHTML = obj.count;
			obj.count--;
		}
	}
} 

      这里实现了让所有实例共享一份show函数:

alert(t1.begin == t2.begin) //结果true 

 

实现四:

 

function Timer(id){
	this.id = id;
	this.timer = null;
	this.count = 0;
	this.begin = function(count){
		this.count = count;
		this.show(this)();//注意和实现三的区别:这里不是Timer.show(this)();
		this.timer = setInterval(this.show(this),1000);//注意和实现三的区别:这里不是Timer.show(this)();
	}
} 
Timer.prototype.show = function(obj){	
	return function(){
		if(obj.count < 0){
			document.getElementById(obj.id).innerHTML = "over";
			clearInterval(obj.timer);
			return ;
		}
		document.getElementById(obj.id).innerHTML = obj.count;
		obj.count--;
	}
}

      实现三和实现四很有意思:二者都实现了让所有实例共享一份show方法。

      区别是:实现三show作为Timer对象的一个属性,这里有点类似与java的静态方法,show方法是属于Timer对象本身的,而不是其实例(t1、t2...)的,所以需要用Timer.show(..)来调用;而实现四采用了“原型”prototype方式来实现,这里show方法不是Timer对象本身,而是其实例(t1、t2...)的,所以使用this.show(..)或者t1.show(...)来调用,这里很有意思“原型”创建的属性是属于其实例的,而且所有实例共享同一份实现(不知道我这里的理解是否正确,欢迎大家拍砖)。这多少有些让学java等面向对象语言的人难以理解,而这也正式js有意思的地方。

      那么这两种实现方式那种更优呢?欢迎各位讨论。

 

实现五:

 

function Timer(id){
	this.id = id;
	this.timer = null;
	this.count = 0;

}
Timer.prototype.begin = function(count){
	this.count = count;
	this.show(this)();//注意这里不是Timer.show(this)();
	this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();
}
Timer.prototype.show = function(obj){	
	return function(){
		if(obj.count < 0){
			document.getElementById(obj.id).innerHTML = "over";
			clearInterval(obj.timer);
			return ;
		}
		document.getElementById(obj.id).innerHTML = obj.count;
		obj.count--;
	}
} 

      这里将begin也使用原型实现,可能这种写法让你看起来不太舒服,那我们换一种。

 

实现六:

 

function Timer(id){
	this.id = id;
	this.timer = null;
	this.count = 0;
}
Timer.prototype = {
	begin : function(count){
		this.count = count;
		this.show(this)();//注意这里不是Timer.show(this)();
		this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();
	},
	show : function(obj){	
		return function(){
			if(obj.count < 0){
				document.getElementById(obj.id).innerHTML = "over";
				clearInterval(obj.timer);
				return ;
			}
			document.getElementById(obj.id).innerHTML = obj.count;
			obj.count--;
		}
	} 
}

      或者,再换一种。

 

实现七:

 

function Timer(id){
	this.id = id;
	this.timer = null;
	this.count = 0;
	Timer.prototype.begin = function(count){
		this.count = count;
		this.show(this)();//主要这里不是Timer.show(this)();
		this.timer = setInterval(this.show(this),1000);//主要这里不是Timer.show(this)();
	}
	Timer.prototype.show = function(obj){	
		return function(){
			if(obj.count < 0){
				document.getElementById(obj.id).innerHTML = "over";
				clearInterval(obj.timer);
				return ;
			}
			document.getElementById(obj.id).innerHTML = obj.count;
			obj.count--;
		}
	} 
}

       这方式,看起来是不是更优雅一些呢。以上都采用面向对象的方式来实现的。那我们是否还可以采用其他方式实现呢? 

 

实现八:

var Timer = {
	begin : function(id,count){
		var obj = {};
		obj["id"] = id;
		obj["count"] = count;
		Timer.show(obj)();
		obj["timer"] = setInterval(Timer.show(obj),1000);//注意这里不是Timer.show(this)();
	},
	show : function(obj){	
		return function(){
			if(obj["count"] < 0){
				document.getElementById(obj["id"]).innerHTML = "over";
				clearInterval(obj["timer"]);
				return ;
			}
			document.getElementById(obj["id"]).innerHTML = obj["count"] ;
			obj["count"]--;
		}
	}
}

Timer.begin("time1", 30);
Timer.begin("time2", 60);

       这里采用了对象字面量的方式来实现的。对象字面量其实是一种单例模式,用在这里其实很变扭,本文这里引入只是引入一种js实现方式而已,仅供大家探讨。下一例也一样。

 

实现九:

 

var Timer = (function(){
	var items = {};
	function begin(id,count){
		var obj = {};
		obj["id"] = id;
		obj["count"] = count;
		Timer.show(obj)();
		obj["timer"] = setInterval(Timer.show(obj),1000);//注意这里不是Timer.show(this)();
		Timer.items[id] = obj;
	};
	function show(obj){	
		return function(){
			if(obj["count"] < 0){
				document.getElementById(obj["id"]).innerHTML = "over";
				clearInterval(obj["timer"]);
				return ;
			}
			document.getElementById(obj["id"]).innerHTML = obj["count"] ;
			obj["count"]--;
		}
	}
	return {
		items : items,
		begin : begin,
		show : show
	}
})()

Timer.begin("time1", 30);
Timer.items["time1"]["count"] = 80;//重新从80开始计时
Timer.begin("time2", 60);

       这里其实也是采用的对象字面量的方式来实现的,只是采用了闭包而已,应用闭包可以真正的实现属性私有化(不过这里没有体现出来)。这里还加了items属性,让其所有实例保存起来,以便后面还可以调用。

 

      平常用的比较多的还有最后一种闭包结合对象字面量的方式(不过在这个场景个人觉得用面向对象方式来实现更好一些)。对象字面量的方式其实也是js的单例模式,在js里应用很广泛,不过在这里应用好像不太合适,看这里的最后两个实现都觉得很牵强。

      从一个小小的计时器,可以衍生出如此多的方式来实现,真让人惊叹于js表现形式之丰富。如此众多实现方式,都有其优点和缺点,在不同的场合也有不同的应用。这里只是表达了一下个人的理解和观点,欢迎大家一起讨论js各种实现方式的优缺点及其适用场合。也欢迎拍砖,或者提供更好的实现方法。

 

 

【本人发帖抛砖引玉,希望能够引出更多的“玉”来,希望所写的每一段代码都能够得到一种最“优雅”的实现方式。以后本人会抛出更多的“砖”,希望能引来更多的“玉”,以供大家一起学习进步】

 

-------------------------------------------------------2009.08.17------------------------------------------------------------

 

到目前为止,个人觉得3楼zbm2001 的实现最优,让我学到了不少,希望能有更多的牛人来提供更优的实现。

function Timer(id){
	this.element = document.getElementById(id);
	this.timer = null;
	this.count = 0;
}
Timer.prototype = {
	begin : function(count){
		this.count = count;
		this.show();
		var _this = this;
		this.timer = setInterval(function(){_this.show();}, 1000);
	}
	,
	show : function(){
		this.element.innerHTML = this.count < 0 ? clearInterval(this.timer) || "over" : this.count--;
	} 
}

 

 

-------------------------------------------------------2009.08.21------------------------------------------------------------

继续收集评论中的实现方式,优劣请读者自评

janpoem

var Timer = function(id) {
	
	var _step = 500, _count = 0, _ticktark = 0, _element = document.getElementById(id);
	
	function __clear() {
		if (_ticktark != null) clearInterval(_ticktark);
	}
	
	return {
		
		begin: function(count, step) {
			if (_element && count > 0) {
				// 看看起始值多少,主要看看有没有被污染
				console.log('on start:', 'count:', _count, 'step:', _step);
				__clear();
				_step = step;
				_count = count;
				// 再看看
				console.log('on set:', 'count:', _count, 'step:', _step);
				_ticktark = setInterval(this.show, _step)
			}
			return this;
		},
		
		show: function() {
			_element && (_element.innerHTML = _count > 0 ? _count-- : 'over');
			if (_count <= 0) {
				console.log(_count);
				__clear();
			}
			return this;
		}
	}
}	

Timer('time1').begin(20, 100);
Timer('time2').begin(30, 200);

 

lifesinger

function Timer(id) {
    this.container = document.getElementById(id);
}

Timer.prototype = {

    constructor: Timer,

    begin: function(count) {
        var container = this.container;
        setTimeout(function() {
            container.innerHTML = count > 0 ? count-- : "over";
            if(count + 1) {
                setTimeout(arguments.callee, 1000);
            }
        }, 1000);
    }
    
};

new Timer("time1").begin(10);
 

 

 

分享到:
评论
32 楼 szcjlssx 2009-10-05  
我也回个
function Timer(count,id) {  
    var start=count,obj=document.getElementById(id);  
    do {  
        (function (count) {  
            setTimeout(function () {  
                obj.innerHTML=count;  
            },(start-count)*1000);  
        })(count);  
    } while (count--);  
} 



一个函数,不做构造了,直接调用就执行
Js代码
Timer(10,"oDiv");
31 楼 szcjlssx 2009-10-03  
我也回个
function Timer(count,id) {
	var start=count,obj=document.getElementById(id);
	do {
		(function (count) {
			setTimeout(function () {
				obj.innerHTML=count;
			},(start-count)*1000);
		})(count);
	} while (count--);
}

一个函数,不做构造了,直接调用就执行
Timer(10,"oDiv");
30 楼 cjj 2009-09-23  
<div class="quote_title">clone168 写道</div>
<div class="quote_div">
<p>放在Timer构造函数内部的话:</p>
<p> </p>
<pre name="code" class="js">function Timer(id){   
    this.id = id;   
    this.timer = null;   
    this.count = 0;   
    Timer.prototype = { 
        begin : function(count){   
            //alert(this); 
            this.count = count;   
            this.show(this)();//注意这里不是Timer.show(this)();   
            this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();   
        },   
        show : function(obj){      
            return function(){   
                if(obj.count &lt; 0){   
                    document.getElementById(obj.id).innerHTML = "over";   
                    clearInterval(obj.timer);   
                    return ;   
                }   
                document.getElementById(obj.id).innerHTML = obj.count;   
                obj.count--;   
            }   
        }   
    }; 
}  </pre>
<p> </p>
 很奇怪,不知道什么原因
<p> </p>
</div>
<p>其实只要把例子构造得稍微复杂点的例子,就很容易理解这个问题了</p>
<p> </p>
<pre name="code" class="js">function Timer(id){   
    this.id = id;   
    this.timer = null;   
    this.count = 0;
this.begin=function(count){
alert('this:'+id); 
            this.count = count;   
            this.show(this)();//注意这里不是Timer.show(this)();   
            this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();   
}

    Timer.prototype = {
id:"abcd",
        begin : function(count){   
alert('prototype'); 
            this.count = count;   
            this.show(this)();//注意这里不是Timer.show(this)();   
            this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();   
        },   
        show : function(obj){      
            return function(){   
                if(obj.count &lt; 0){   
                    document.getElementById(obj.id).innerHTML = "over";   
                    clearInterval(obj.timer);   
                    return ;   
                }   
                document.getElementById(obj.id).innerHTML = obj.count;   
                obj.count--;   
            }   
        }   
    }; 
}

new Timer('aaa').begin(10);</pre>
29 楼 ferreousbox 2009-08-24  
其实是js类化的一个体现
// 声明一个类(其实也就是对象),其中initialize是构造方法
function MyObj(){this.initialize.apply(this, arguments);}

// 类的属性和方法声明
MyObj.prototype = {
    attr1 : null, // 属性,当然也可以在方法中直接this.attr1=来设置
   
    // 构造方法,可以直接new MyObje(args)
    initialize : function() {

    },

    // 一般方法
    func1 : function() {
   
    }
}

// 类的静态方法
MyObj.func2 = function() {

};
28 楼 clone168 2009-08-20  
<div class="quote_title">jianguang_qq 写道</div><div class="quote_div"><div class="quote_title">lifesinger 写道</div>
<div class="quote_div">
<div class="quote_title">
<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/"></a>clone168 写道</div>
<div class="quote_div">
<p><span>作者js功力确实不错,可惜俺有一个疑问(具体<span style="background-color: #ffffff;">见</span><span><span style="font-weight: normal;"><span style="text-decoration: none;"><span style="font-size: small;"><span style="color: #000000;"><span style="background-color: #ffffff;"><a class="quote_title" style="color: white; background-color: #108ac6;" title="js一个很奇怪的问题" href="http://clone168.iteye.com/blog/452290" target="_blank">js一个很奇怪的问题</a><span>),当我把“代码六”中的</span></span></span></span></span></span></span></span></p>
<p> </p>
很奇怪,不知道什么原因
<p> </p>
</div>
<p> </p>
<p>是因为 new Timer(id) 的内部机制里,请参考:<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/">http://lifesinger.org/blog/2009/08/new-funtion-secret/</a></p>
</div>
<p> </p>
<p> </p>
<p>lifesinger牛人,从内部机制来分析,分析的很细,让我学习了不少。从内部来分析,需要对内部非常了解。因此看起来比较困难。</p>
<p>方式A:</p>
<pre name="code" class="java">function Dog() {
alert(this.__proto__.name); // undefined
Dog.prototype.name = 2; //方式A (注意这里)
  alert(this.__proto__.name); // 2 (注意这里)
 }

var dog1 = (function(){
var o = {__proto__: Dog.prototype};
alert(Dog.prototype.name);// undefined
alert(o.__proto__.name); // undefined
Dog.apply(o);
alert(Dog.prototype.name) //2
alert(o.__proto__.name); //2
return o;
})()

alert(dog1.__proto__.name) // 2
alert(dog1.name) // 2</pre>
<p> 方式B:
</p>
<pre name="code" class="js">function Dog() {
alert(this.__proto__.name); // undefined
Dog.prototype = {name : 2}//方式B (注意这里)
  alert(this.__proto__.name); // undefined (注意这里)
}

var dog1 = (function(){
var o = {__proto__: Dog.prototype};
alert(Dog.prototype.name);// undefined
alert(o.__proto__.name); // undefined
Dog.apply(o);
alert(Dog.prototype.name) //2
alert(o.__proto__.name); //undefined
return o;
})()

alert(dog1.__proto__.name) // undefined
alert(dog1.name) // undefined</pre>
<p>化简后的问题:</p>
<pre name="code" class="js">function Base(){
Base.prototype.name = 2; //方式A (注意这里)
alert(this.a.name) //2(注意这里)
}
var o = {a : Base.prototype};
Base.apply(o);
alert(o.a.name);// 2(注意这里)

function Base2(){
Base2.prototype = {name : 2}; //方式B(注意这里)
alert(Base2.prototype.name) //2
alert(this.a.name) //undefined(注意这里)
}
var o2 = {a : Base2.prototype};
Base2.apply(o2);
alert(o2.a.name);// undefined(注意这里)</pre></div><br/>楼上例子简明易懂,赞一个
27 楼 jianguang_qq 2009-08-19  
<div class="quote_title">lifesinger 写道</div>
<div class="quote_div">
<div class="quote_title">
<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/"></a>clone168 写道</div>
<div class="quote_div">
<p><span>作者js功力确实不错,可惜俺有一个疑问(具体<span style="background-color: #ffffff;">见</span><span><span style="font-weight: normal;"><span style="text-decoration: none;"><span style="font-size: small;"><span style="color: #000000;"><span style="background-color: #ffffff;"><a class="quote_title" style="color: white; background-color: #108ac6;" title="js一个很奇怪的问题" href="http://clone168.iteye.com/blog/452290" target="_blank">js一个很奇怪的问题</a><span>),当我把“代码六”中的</span></span></span></span></span></span></span></span></p>
<p> </p>
很奇怪,不知道什么原因
<p> </p>
</div>
<p> </p>
<p>是因为 new Timer(id) 的内部机制里,请参考:<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/">http://lifesinger.org/blog/2009/08/new-funtion-secret/</a></p>
</div>
<p> </p>
<p> </p>
<p>lifesinger牛人,从内部机制来分析,分析的很细,让我学习了不少。从内部来分析,需要对内部非常了解。因此看起来比较困难。</p>
<p>方式A:</p>
<pre name="code" class="java">function Dog() {
alert(this.__proto__.name); // undefined
Dog.prototype.name = 2; //方式A (注意这里)
  alert(this.__proto__.name); // 2 (注意这里)
 }

var dog1 = (function(){
var o = {__proto__: Dog.prototype};
alert(Dog.prototype.name);// undefined
alert(o.__proto__.name); // undefined
Dog.apply(o);
alert(Dog.prototype.name) //2
alert(o.__proto__.name); //2
return o;
})()

alert(dog1.__proto__.name) // 2
alert(dog1.name) // 2</pre>
<p> 方式B:
</p>
<pre name="code" class="js">function Dog() {
alert(this.__proto__.name); // undefined
Dog.prototype = {name : 2}//方式B (注意这里)
  alert(this.__proto__.name); // undefined (注意这里)
}

var dog1 = (function(){
var o = {__proto__: Dog.prototype};
alert(Dog.prototype.name);// undefined
alert(o.__proto__.name); // undefined
Dog.apply(o);
alert(Dog.prototype.name) //2
alert(o.__proto__.name); //undefined
return o;
})()

alert(dog1.__proto__.name) // undefined
alert(dog1.name) // undefined</pre>
<p>化简后的问题:</p>
<pre name="code" class="js">function Base(){
Base.prototype.name = 2; //方式A (注意这里)
alert(this.a.name) //2(注意这里)
}
var o = {a : Base.prototype};
Base.apply(o);
alert(o.a.name);// 2(注意这里)

function Base2(){
Base2.prototype = {name : 2}; //方式B(注意这里)
alert(Base2.prototype.name) //2
alert(this.a.name) //undefined(注意这里)
}
var o2 = {a : Base2.prototype};
Base2.apply(o2);
alert(o2.a.name);// undefined(注意这里)</pre>
26 楼 clone168 2009-08-19  
<div class="quote_title">lifesinger 写道</div>
<div class="quote_div">
<div class="quote_title">
<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/"></a>clone168 写道</div>
<div class="quote_div">
<p><span>作者js功力确实不错,可惜俺有一个疑问(具体<span style="background-color: #ffffff;">见</span><span><span style="font-weight: normal;"><span style="text-decoration: none;"><span style="font-size: small;"><span style="color: #000000;"><span style="background-color: #ffffff;"><a class="quote_title" style="color: white; background-color: #108ac6;" title="js一个很奇怪的问题" href="http://clone168.iteye.com/blog/452290" target="_blank">js一个很奇怪的问题</a><span>),当我把“代码六”中的</span></span></span></span></span></span></span></span></p>
<p> </p>
很奇怪,不知道什么原因
<p> </p>
</div>
<p> </p>
<p>是因为 new Timer(id) 的内部机制里,请参考:<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/">http://lifesinger.org/blog/2009/08/new-funtion-secret/</a></p>
</div>
<p>射雕的文章我看了,只可惜自己还是感觉不太明白:</p>
<p>
</p>
<div class="quote_title">射雕 写道</div>
<div class="quote_div">// Dog.prototype = {constructor: Dog};<br>var o = {__proto__: Dog.prototype};<br>// 此时,o = {__proto__: {constructor: Dog}}<br>Dog.apply(o);<br>// 此时,Dog.prototype = {shout: function(){...}}<br>return o;<br>显然,运行 dog1.shout() 时,dog1 的确没有 shout 方法。</div>
 
25 楼 lifesinger 2009-08-19  
<div class="quote_title">
<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/"></a>clone168 写道</div>
<div class="quote_div">
<p><span>作者js功力确实不错,可惜俺有一个疑问(具体<span style="background-color: #ffffff;">见</span><span><span style="font-weight: normal;"><span style="text-decoration: none;"><span style="font-size: small;"><span style="color: #000000;"><span style="background-color: #ffffff;"><a class="quote_title" style="color: white; background-color: #108ac6;" title="js一个很奇怪的问题" href="http://clone168.iteye.com/blog/452290" target="_blank">js一个很奇怪的问题</a><span>),当我把“代码六”中的</span></span></span></span></span></span></span></span></p>
<p> </p>
很奇怪,不知道什么原因
<p> </p>
</div>
<p> </p>
<p>是因为 new Timer(id) 的内部机制里,请参考:<a href="http://lifesinger.org/blog/2009/08/new-funtion-secret/">http://lifesinger.org/blog/2009/08/new-funtion-secret/</a></p>
24 楼 lifesinger 2009-08-19  
02221021 写道
setTimeout的开销大一点
setInterval有可能线程阻塞
孰优孰劣还是要看具体情况吧


的确如此。
对于复杂页面,线程阻塞比内存开销更恐怖,作为一个良好的编码习惯,推荐多用setTimeout
23 楼 clone168 2009-08-19  
<p><span style="">作者js功力确实不错,可惜俺有一个疑问(具体<span style="background-color: #ffffff;">见</span><span style=""><span style="font-weight: normal;"><span style="text-decoration: none;"><span style="font-size: small;"><span style="color: #000000;"><span style="background-color: #ffffff;"><a class="quote_title" style="color: white; background-color: #108ac6;" title="js一个很奇怪的问题" href="http://clone168.iteye.com/blog/452290" target="_blank">js一个很奇怪的问题</a><span style="">),当我把“代码六”中的</span></span></span></span></span></span></span></span></p>
<p> </p>
<pre name="code" class="js">Timer.prototype = {   
    begin : function(count){   
        this.count = count;   
        this.show(this)();//注意这里不是Timer.show(this)();   
        this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();   
    },   
    show : function(obj){      
        return function(){   
            if(obj.count &lt; 0){   
                document.getElementById(obj.id).innerHTML = "over";   
                clearInterval(obj.timer);   
                return ;   
            }   
            document.getElementById(obj.id).innerHTML = obj.count;   
            obj.count--;   
        }   
    }    
}    </pre>
<p> </p>
<p> 放在Timer构造函数内部的话:</p>
<p> </p>
<pre name="code" class="js">function Timer(id){   
    this.id = id;   
    this.timer = null;   
    this.count = 0;   
    Timer.prototype = { 
        begin : function(count){   
            //alert(this); 
            this.count = count;   
            this.show(this)();//注意这里不是Timer.show(this)();   
            this.timer = setInterval(this.show(this),1000);//注意这里不是Timer.show(this)();   
        },   
        show : function(obj){      
            return function(){   
                if(obj.count &lt; 0){   
                    document.getElementById(obj.id).innerHTML = "over";   
                    clearInterval(obj.timer);   
                    return ;   
                }   
                document.getElementById(obj.id).innerHTML = obj.count;   
                obj.count--;   
            }   
        }   
    }; 
}  </pre>
<p> </p>
<p> <span style="font-family: Arial; line-height: 18px;"><span style="">在</span><span lang="EN-US">firebug</span><span style="">下面提示:“</span><span class="objectboxobjectbox-errormessagehastwistyhasbreakswitchopened"><span lang="EN-US">t1.begin is not a function</span></span><span style="">”这样的错误,<span style="font-family: Arial;"><span>而且,看到“代码七”就发现,都用</span><span lang="EN-US">Timer.prototype.begin</span><span>和</span><span lang="EN-US">Timer.prototype.show</span><span>就算写在里面也能运行:</span></span></span></span></p>
<p>
</p>
<pre name="code" class="js">function Timer(id){   
    this.id = id;   
    this.timer = null;   
    this.count = 0;   
    Timer.prototype.begin = function(count){   
        this.count = count;   
        this.show(this)();//主要这里不是Timer.show(this)();   
        this.timer = setInterval(this.show(this),1000);//主要这里不是Timer.show(this)();   
    }   
    Timer.prototype.show = function(obj){      
        return function(){   
            if(obj.count &lt; 0){   
                document.getElementById(obj.id).innerHTML = "over";   
                clearInterval(obj.timer);   
                return ;   
            }   
            document.getElementById(obj.id).innerHTML = obj.count;   
            obj.count--;   
        }   
    }    
}    </pre>
 很奇怪,不知道什么原因
<p> </p>
22 楼 02221021 2009-08-19  
setTimeout的开销大一点
setInterval有可能线程阻塞
孰优孰劣还是要看具体情况吧
21 楼 lifesinger 2009-08-19  
function Timer(id) {
    this.container = document.getElementById(id);
}

Timer.prototype = {

    constructor: Timer,

    begin: function(count) {
        var container = this.container;
        setTimeout(function() {
            container.innerHTML = count > 0 ? count-- : "over";
            if(count + 1) {
                setTimeout(arguments.callee, 1000);
            }
        }, 1000);
    }
    
};

new Timer("time1").begin(10);


也来一个,补充两点:

1. prototype 的 constructor 不要搞丢了
2. 用 setTimeout,比 setInterval 好
20 楼 flyfan 2009-08-18  
对这些js牛人佩服呀,另外zbm2001写得确实不错
19 楼 black.angel 2009-08-18  
我纯粹只是欣赏 zbm2001 对软件代码质量的控制能力和严谨的学习态度.赞一个.
18 楼 02221021 2009-08-17  
此回帖已被管理员和谐.
17 楼 Saito 2009-08-17  
茴香豆的"茴"字有多少种写法.. 突然想到说Java的singleton有多少种写法.

     js太灵活了. 以至于我无法驾驭..  不过支持剑光.
16 楼 zbm2001 2009-08-17  
引用

1 ,这2个想当然尔的理论是从一些书上看到的,比如月影的王者归来,月影做为我眼里这个理论的发源地,相信他会为此负责的.

你难道总是希望别人为你的代码负责?
只可惜宁愿迷信所谓某人、某书、某权威,也不愿写几行代码测试一下。

引用

……john resig大人也说他真正理解闭包花去了相当多的精力和时间.

既然你已知道john resig都花去了相当多的精力和时间才真正理解闭包,所以你应该明白我所说的——你的结论在这(真正理解闭包)之后再下吧:
引用

……
如果你一直坚持尝试利用闭包来简化你的开发(虽然可能曾经会饱受挫折),并结合着不断阅读直到完全理解下文,再来回顾上面的结论看看……


不过对于一个对某些结论连几行测试代码都懒的写,还声称自有别人为这些结论负责的程序员
——估计也不能指望比john resig花更多的的精力和时间了!
15 楼 02221021 2009-08-17  
此回帖已被管理员和谐.
14 楼 zbm2001 2009-08-17  
02221021 写道
补充3楼1点啊, 频繁操作dom节点确实非常不好,不过也许document.getElementById和document.getElementsByTagName是两个例外.大部分浏览器都对这2个方法做了优化.速度跟用引用来取相差无几.

这个想当然尔的理论从哪里来?
你随便一说,也不知道谁会受到误导,测试几个主流浏览器出个数据再说吧。

02221021 写道


1. 可能存在的内存泄露.

2. 让scope chains难以维护.

3. 程序可读性降低,闭包引起的bug经常叫人抓狂.

其实闭包不是个很神秘的东西,没有必要想法设法跟它扯上关系.不过楼主的研究精神狠赞一个.

如果你一直坚持尝试利用闭包来简化你的开发(虽然可能曾经会饱受挫折),并结合着不断阅读直到完全理解下文,再来回顾上面的结论看看……
中译文:
http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html
原文:
http://www.jibbering.com/faq/faq_notes/closures.html
13 楼 jianguang_qq 2009-08-16  
sw1982 写道
呵呵。剑光也搬到javaeye了?

是啊,发现javaeye质量比csdn高好多哦

相关推荐

Global site tag (gtag.js) - Google Analytics