我正在尝试使用数组属性及其子类定义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?
正如您所看到的,我对原始数据类型没有这个问题......有什么建议吗?
答案 0 :(得分:4)
Wen你写Test2.prototype = new Test()
,创建一个Test
个实例,只有一个数组实例,每个Test2
个实例共享。
因此,所有Test2
实例共享相同的数组。
您可以通过从Test
构造函数调用基础Test2
构造函数来解决此问题,该构造函数将为每个Test2
实例创建一个新的数组实例。
例如:
function Test2() {
Test.call(this);
}
答案 1 :(得分: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();
答案 2 :(得分:1)
我唯一能想到的是数组是共享引用。应该有一个明显的解决方案,因为这种经典的OOP代码一直在Javascript中实现。
答案 3 :(得分:1)
JavaScript没有经典的继承系统,它有一个原型继承系统。所以在JavaScript技术上,没有“类”的概念。
对象继承自其他对象(所谓的原型对象),而不是抽象类。这样做的一个重要结果是,如果多个对象共享相同的原型,并且其中一个对象更改了原型中定义的属性,则该更改将立即对所有其他对象生效。
尝试使用JavaScript继承就好像它基于类通常会引起很大的麻烦,因为你总是会发现这类问题。
我知道这并没有真正回答你的特定问题,但在高层次我建议你接受原型继承,而不是试图使用“伪类”。即使它起初看起来很奇怪,你的代码也会更加可靠,你不会浪费时间去理解像这样的奇怪错误,这是由一个奇怪的原型链造成的。
观看Douglas Crockford解释继承的视频,可在Yahoo UI Theatre网站上在线获取。它改变了我在JavaScript中编程的方式:)