views:

90

answers:

4

Hi all! I am trying to define a javascript class with an array property, and its subclass. The problem is that all instances of the subclass somehow "share" the array property:

// 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?

As you can see I don't have this problem with primitive data types... Any suggestions?

+1  A: 

Only thing I can think of is that arrays are shared references. There should be an obvious solution since this kind of classic OOP code is implemented all the time in Javascript.

lark
+4  A: 

Wen you write Test2.prototype = new Test(), you create a single Test instance, with a single array instance, which is shared by every Test2 instance.

Therefore, all of the Test2 instances are sharing the same array.

You can solve this problem by calling the base Test constructor from the Test2 constructor, which will create a new array instance for every Test2 instance.

For example:

function Test2() {
    Test.call(this);
}
SLaks
+2  A: 

Another, rather inelegant, alternative is to move initialization code from the constructor to a method and call it from both constructors:

// 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();
Tim Down
A: 

JavaScript does not have a classical inheritance system, it has a prototypical inheritance system. So in JavaScript technically there is no concept of "Class".

Objects inherit from other objects (the so called prototype object), not abstract classes. One big consequence of this is that if several objects share the same prototype and one of these objects change an attribute defined in the prototype, that change is effective immediately to all other objects.

Trying to use JavaScript inheritance as if it was based on classes usually causes big headaches, because you find this type of problems all the time.

I know this does not really answer your particular questions, but at a high level I recommend you embrace the prototypical inheritance instead of trying to use "pseudo-classes". Even if it looks weird at first, your code will be much more reliable and you will not lose time trying to understand strange bugs like this, cause by a strange chain of prototypes.

Watch this video where Douglas Crockford explains inheritance, it's available online in Yahoo UI Theater website. It changed the way I programmed in JavaScript :)

http://video.yahoo.com/watch/111585/1027823 (link to the first part)

http://developer.yahoo.com/yui/theater/ (for all the videos)

fms