multiple herencia constructores javascript inheritance prototype-programming

constructores - Herencia de JavaScript: cuando el constructor tiene argumentos



prototype chaining in javascript (4)

Aunque este es un tema antiguo, pensé que respondería de todos modos. Dos formas de hacerlo:

Aunque la forma Pseudo Clásica es la más popular, tiene sus lados negativos ya que necesita llamar al constructor padre una vez en el constructor hijo y una vez mientras hereda el prototipo. Además, el prototipo del niño contendrá todas las propiedades del constructor padre que de todos modos se sobreescribirá cuando se llame al constructor hijo. Mi elección personal es la herencia prototípica .

1. Herencia Pseudo Clásica:

function A(x, y) {} A.prototype.run = function () {}; function B(x, y) { A.call(this,x,y); } B.prototype = new A(); B.prototype.constructor = B;

2. Herencia prototípica:

function A(x, y) {} A.prototype.run = function () {}; function B(x, y) { A.call(this,x,y); } B.prototype = Object.create(A.prototype); B.prototype.constructor = B;

Usando JavaScript puro para hacer herencia, esto es lo que suelo hacer:

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

Como no hay argumentos para pasar al constructor, el nuevo A no tiene nada de qué quejarse. Ahora, no he descubierto una buena manera de hacer herencia si el constructor tiene argumentos para aprobar. Por ejemplo,

function A(x, y) {} A.prototype.run = function () {}; function B(x, y) {} B.prototype = new A; B.prototype.constructor = B;

Podría pasar algunos valores arbitrarios como:

B.prototype = new A(null, null);

En algunos casos, es posible que necesite validar xey en el constructor de A. En algunos casos extremos, necesito arrojar errores al verificar x o y. Entonces, no hay forma de que B herede de A usando el nuevo A.

¿Alguna sugerencia?

¡Gracias!


Bueno, si quiere hacer de B.prototype un objeto que herede de A.prototype , sin ejecutar el constructor A , para evitar todos los posibles efectos colaterales, podría usar un constructor ficticio para hacerlo, por ejemplo:

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

Puede crear una función para encapsular la lógica de la creación de este nuevo objeto, por ejemplo:

function inherit(o) { function F() {}; // Dummy constructor F.prototype = o; return new F(); } //... B.prototype = inherit(A.prototype); B.prototype.constructor = B;

Si se dirige a navegadores modernos, puede usar el método Object.create ECMAScript 5 para el mismo propósito, por ejemplo:

B.prototype = Object.create(A.prototype); B.prototype.constructor = B; //..


Considera esto:

function B( x, y ) { var b = Object.create( new A( x, y ) ); // augment b with properties or methods if you want to return b; }

Y entonces

var b = new B( 12, 13 );

Ahora b hereda de una instancia de A , que a su vez hereda de A.prototype .

Demostración en vivo: http://jsfiddle.net/BfFkU/

Object.create no está implementado en IE8, pero uno puede implementarlo manualmente fácilmente:

if ( !Object.create ) { Object.create = function ( o ) { function F() {} F.prototype = o; return new F(); }; }

Esto se puede colocar dentro de un archivo ie8.js que se carga solo para IE8 y abajo a través de comentarios condicionales.


El problema es que no puede crear fácilmente un objeto prototipo para B ya que no se puede invocar al constructor de A Esto se debe a que los parámetros para el constructor son desconocidos antes de que se ejecute la new B Se necesita una función de constructor ficticio para construir un prototipo para B que se vincule con el prototipo de A

B.prototype = (function(parent){ function protoCreator(){}; protoCreator.prototype = parent.prototype; // Construct an object linking to A.prototype without calling constructor of A return new protoCreator(); })(A);

Una vez que tenga el objeto prototipo para la configuración B , debe asegurarse de llamar al constructor de A en el constructor de B

function B(x, y) { // Replace arguments by an array with A''s arguments in case A and B differ in parameters A.apply(this, arguments); }

Ahora debería poder instanciar B llamando a la new B(x, y) .

Para obtener una misma validación completa de parámetros en A consulte a jsFiddle .

En su código original está configurando B.prototype.constructor = B No entiendo por qué estás haciendo esto. La propiedad de constructor no influye en la jerarquía de herencia de la que es responsable la propiedad de prototype . Si desea tener el constructor nombrado contenido en la propiedad del constructor , necesitará extender el código desde arriba un poco:

// Create child''s prototype – Without calling A B.prototype = (function(parent, child){ function protoCreator(){ this.constructor = child.prototype.constructor }; protoCreator.prototype = parent.prototype; return new protoCreator(); })(A, B);

Usando la primera definición de B.prototype obtendría los siguientes resultados:

var b = new B(4, 6); b.constructor // A console.info(b instanceof A); // true console.info(b instanceof B); // true

Con la versión extendida , obtendrás:

var b = new B(4, 6); b.constructor // B console.info(b instanceof A); // true console.info(b instanceof B); // true

La causa de la salida diferente es esa instanceof seguimiento de toda la cadena prototipo de b e intenta encontrar un objeto prototipo correspondiente para A.prototype o B.prototype (en la otra llamada). El prototipo de b.constructor refiere a la función que se utilizó para definir el prototipo de instancias. En caso de que se pregunte por qué no apunta a protoCreator esto se debe a que su prototipo fue sobreescrito con A.prototype durante la creación de B.prototype . La definición extendida como se muestra en el ejemplo actualizado corrige esta propiedad del constructor para apuntar a una función más apropiada (porque probablemente sea más esperada).

Para el uso diario, recomendaría descartar por completo la idea de utilizar la propiedad del constructor de las instancias. En su lugar, utilice instanceof ya que sus resultados son más predecibles / esperados.