2010-06-07 49 views
5

我想要定义一个数组属性及其子类的JavaScript类。问题是,子类莫名其妙地“共享”数组属性的所有实例:JavaScript的继承和阵列

// class Test 
function Test() { 
    this.array = []; 
    this.number = 0; 
} 

Test.prototype.push = function() { 
    this.array.push('hello'); 
    this.number = 100; 
} 

// class Test2 : Test 
function Test2() { 
} 

Test2.prototype = new Test(); 

var a = new Test2(); 
a.push(); // push 'hello' into a.array 

var b = new Test2(); 
alert(b.number); // b.number is 0 - that's OK 
alert(b.array); // but b.array is containing 'hello' instead of being empty. why? 

正如你可以看到我没有这个问题的基本数据类型...任何建议?

+1

见http://stackoverflow.com/questions/1485824/javascript编程方式-inheritance-objects-declared-in-constructor-are-shared-between-inst – 2010-06-07 13:41:10

回答

1

我唯一能想到的就是数组是共享引用。应该有一个明显的解决方案,因为这种经典的OOP代码始终在Javascript中实现。

4

温你写了Test2.prototype = new Test(),你创建了一个单一的Test实例,其中有一个数组实例,每个实例共享一个数组实例。因此,所有Test2实例共享相同的数组。

您可以通过调用Test2构造函数中的基构造函数Test来解决此问题,该构造函数将为每个Test2实例创建一个新的数组实例。

例如:

function Test2() { 
    Test.call(this); 
} 
3

另一个,而不雅,另一种方法是从构造移动初始化代码的方法和从两个构造调用它:

// class Test 
function Test() { 
    this.init(); 
} 

Test.prototype.init = function() { 
    this.array = []; 
    this.number = 0; 
}; 

Test.prototype.push = function() { 
    this.array.push('hello'); 
    this.number = 100; 
}; 

// class Test2 : Test 
function Test2() { 
    this.init(); 
} 

Test2.prototype = new Test(); 
+0

+1为清楚起见。 – jvenema 2011-03-25 12:14:41

1

JavaScript没有一个古典继承制度,它有一个典型的继承制度。所以在JavaScript技术上没有“类”的概念。

对象从其他对象(所谓的原型对象)继承,而不是抽象类。这样做的一个重大后果是,如果多个对象共享相同的原型,并且其中一个对象更改了原型中定义的属性,则该更改对所有其他对象立即生效。

尝试使用JavaScript继承,就好像它基于类一样,通常会引起很大的麻烦,因为您始终都会发现此类问题。

我知道这并不能真正回答您的特定问题,但在高层次上,我建议您接受原型继承,而不是尝试使用“伪类”。即使它起初看起来很怪异,你的代码将会更加可靠,并且你不会失去尝试理解这种奇怪的错误的时间,这是由一连串奇怪的原型造成的。

观看道格拉斯克罗克福德解释继承的视频,它可以在Yahoo UI Theatre网站上在线获得。它改变了我在JavaScript :)

http://video.yahoo.com/watch/111585/1027823(链接到第一部分)

http://developer.yahoo.com/yui/theater/(所有视频)