?
前几天在javaeye上看到一篇帖子:【JS优化系列】从一个计时器的写法探讨js多种实现方式的优劣,感觉楼主确实厉害,一个计时器能有那么多优雅的写法,而且全部是用的面向对象的思想,我花了整整一天时间把那些写法全部消化,也看了那些留下的评论,发现javaeye上面确实人才辈出,难怪我师兄把博客都从csdn搬到javaeye了。这里我把我发现的一个很奇怪的问题贴出来,希望有大牛能帮我解惑哈
帖子里的“代码六”是这样的:
?
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--;
}
}
}
?
这份代码没有任何问题,运行结果一切正常,可是,当我把“Timer.prototype={”这一行以及后面的移到Timer构造函数内部的时候,却发现在firebug下面提示:“”这样的错误,代码如下:
?
<body>
<div id="time1">time1</div>
<div id="time2">time2</div>
</body>
<script>
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 < 0){
document.getElementById(obj.id).innerHTML = "over";
clearInterval(obj.timer);
return ;
}
document.getElementById(obj.id).innerHTML = obj.count;
obj.count--;
}
}
};
}
t1 = new Timer("time1");
t2 = new Timer("time2");
t1.begin(10);
t2.begin(10);
</script>
?而且,看到“代码七”就发现,都用Timer.prototype.begin和Timer.prototype.show就算写在里面也能运行:
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--;
}
}
}
?我不明白为什么会这么诡异,希望俺帖能起到抛砖引玉的效果。期待大牛们的精彩解答!
?
?
?
1 楼
szcjlssx
2009-10-03
这个问题在学JS的面向对象时就应该讲过了
事实上是这个问题,很简单
应该记得,prototype方式的继承,如果要继承另一个类,写法是这样的
如果换个方式写
因为Class.prototype被替换成了一个新对象,要让实例c继承Parent的attr属性,必须写成
查看你的代码,写的是
最后,对于这个贴子,我也回了一个代码,没有用构造函数,你可以去看看,(嗯,再打个广告,留个联系方法 Q-Q-群 AjaxLife 57847622,欢迎来讨论交流)
事实上是这个问题,很简单
function Class() {
//空的
}
Class.prototype.method=function () {
alert("继承的方法");
};
var c = new Class();
c.method();//正常
应该记得,prototype方式的继承,如果要继承另一个类,写法是这样的
Class.prootype=new Parent();//Class类继承Parent父类
//注意这里是直接赋值去一个对象(new Parent());但这样有个问题,往下
function Class() {
//空的
}
function Parent() {
this.attr=123;
}
Class.prototype=new Parent();//继承Parent
var c = new Class();
alert(c.attr);//正常,123
如果换个方式写
function Class() {
//空的
}
function Parent() {
this.attr=123;
}
var c = new Class();
Class.prototype=new Parent();//已经实例化过了,再继承Parent
alert(c.attr);//没有了
因为Class.prototype被替换成了一个新对象,要让实例c继承Parent的attr属性,必须写成
//要么先继承,再实例化,要么就用克隆属性的方法 Class.prototype.attr=(new Parent()).attr;
查看你的代码,写的是
Timer.prototype = { };
//但将其放在构造函数内部时,注意 ,在这行之上,已经有了this了,证明已经实例化了
//这时再去用这种直接将prototype重置为另一个对象的继承方法,就不行了
最后,对于这个贴子,我也回了一个代码,没有用构造函数,你可以去看看,(嗯,再打个广告,留个联系方法 Q-Q-群 AjaxLife 57847622,欢迎来讨论交流)