2010-06-07 20 views
5

Estoy tratando de definir una clase javascript con una propiedad de matriz y su subclase. El problema es que todas las instancias de la subclase de alguna manera "compartir" la propiedad de matriz:Herencia de Javascript y matrices

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

Como se puede ver que no tengo este problema con los tipos de datos primitivos ... ¿Alguna sugerencia?

+1

Ver http://stackoverflow.com/questions/1485824/javascript -heritance-objects-declared-in-constructor-are-shared-between-inst –

Respuesta

1

Lo único que se me ocurre es que las matrices son referencias compartidas. Debería haber una solución obvia ya que este tipo de código OOP clásico se implementa todo el tiempo en Javascript.

4

Cuando escribe Test2.prototype = new Test(), crea una sola instancia de Test, con una única instancia de matriz, que se comparte con cada instancia de Test2.

Por lo tanto, todas las instancias de Test2 comparten la misma matriz.

Puede resolver este problema llamando al constructor base Test desde el constructor Test2, que creará una nueva instancia de matriz para cada instancia Test2.

Por ejemplo:

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

Otro, poco elegante, alternativa es mover el código de inicialización del constructor a un método y llamaremos a partir de los dos constructores:

// 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 para mayor claridad. – jvenema

1

JavaScript no tiene una sistema de herencia clásica, tiene un sistema de herencia prototípico. Entonces en JavaScript técnicamente no hay concepto de "Clase".

Los objetos heredan de otros objetos (el llamado objeto prototipo), no clases abstractas. Una gran consecuencia de esto es que si varios objetos comparten el mismo prototipo y uno de estos objetos cambia un atributo definido en el prototipo, ese cambio se aplica inmediatamente a todos los demás objetos.

Tratar de usar la herencia de JavaScript como si estuviera basada en clases generalmente causa grandes dolores de cabeza, porque este tipo de problemas se presentan todo el tiempo.

Sé que esto realmente no responde a sus preguntas particulares, pero a un alto nivel le recomiendo que abrace la herencia prototípica en lugar de tratar de usar "pseudo-clases". Incluso si se ve raro al principio, su código será mucho más confiable y no perderá tiempo tratando de entender errores extraños como este, debido a una extraña cadena de prototipos.

Vea este video donde Douglas Crockford explica la herencia, está disponible en línea en el sitio web de Yahoo UI Theatre. Se cambió la forma en que programé en JavaScript :)

http://video.yahoo.com/watch/111585/1027823 (enlace a la primera parte)

http://developer.yahoo.com/yui/theater/ (para todos los vídeos)