Friday, September 4, 2009

Javascript Inheritance Gotcha


This is a short warning about inheritance with Javascript :

A = function() {
  this.value=5;
  this.arr = new Array();
}
A.prototype.changeValue = function() { this.value=6; this.arr.push(4);}
A.prototype.getValue = function() { return this.value;}
A.prototype.getArray = function() { return this.arr; }

B = function() {}
B.prototype = new A;

function doit() {

  var b = new B();
  alert('#1 : '+b.getValue()); // Should be 5
  alert('#2 : '+b.getArray()); // Should be empty
  b.changeValue();
  alert('#3 : '+b.getValue()); // Should be 6
  alert('#4 : '+b.getArray()); // Should be 4

  var b2 = new B();
  alert('#5 : '+b2.getValue()); // Should be 5,
    // because value didn't change for this instance yet
  alert('#6 : '+b2.getArray()); // Should be empty,
    // because this.arr didn't change for this instance,
    // and yet it is not empty, it contains the value of the previous instance
}

So you've be warned ! Javascript inheritance doesn't work well with objects !

Or maybe I missed something...

This happened on firefox3.0 and firefox 3.5 on ubuntu 9.04

This can be dealt with by adding
B.prototype=new A();
also in the constructor of B. Then the constructor of A get called every time B's get called, and the new object addresses are recomputed.
But then the class specific methods are lost. So they have to be declared again.

This lead to the following solution :
B = function() {
  B.buildPrototype();
  this.that=something;
}
B.buildPrototype = function() {
  B.prototype = new A();
  B.prototype.aMethod = function() {...}
  B.prototype.anotherMethod = function() {...}
}
B.buildPrototype();
This way, the new object is built with the correct dynamic inherited properties, and it's prototype methods are not lost.

No comments:

Post a Comment