`
clone168
  • 浏览: 7321 次
  • 性别: Icon_minigender_1
  • 来自: 成都
文章分类
社区版块
存档分类
最新评论

js一个很奇怪的问题

阅读更多

 

前几天在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下面提示:“t1.begin is not a function”这样的错误,代码如下:

 

<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.beginTimer.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
0
分享到:
评论
1 楼 szcjlssx 2009-10-03  
这个问题在学JS的面向对象时就应该讲过了
事实上是这个问题,很简单
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,欢迎来讨论交流)
发表评论

文章已被作者锁定,不允许评论。

相关推荐

Global site tag (gtag.js) - Google Analytics