2011-07-05 9 views
5

Estoy tratando de "obtener" la herencia en JS. acabo de descubrir una clara forma de copiar, básicamente, todas las propiedades de un objeto en otro:Herencia en JS: this.base = Class(); this.base() o ...?

function Person(name){ 
    this.name="Mr or Miss: "+name; 

    this.introduce = function(){ 
    console.log("Hi, I am "+this.name); 
    } 
} 

function Employee(name,title){ 
    this.title=title; 

    this.base=Person; 
    this.base(name); 

} 

e = new Employee('tony', 'manager') 
e.introduce(); 

Tenga en cuenta que tengo una clase Persona() con un constructor, y su atributo "name" es generado por el constructor. Lo bueno de esto también es que el empleado TAMBIÉN tiene el nombre en el constructor y, además, crea el objeto Person utilizando el mismo parámetro.

si hubiera hecho esto con la forma "prototipo":

function Person(name){ 

    this.introduce = function(){ 
    console.log("Hi, I am "+this.name); 
    } 
} 

function Employee(name, title){ 
    this.name = name; /* ?!?!?!?!? I can't call the proper constructor here */ 
    this.title = title; 
} 
Employee.prototype= new Person(); /* ?!?!? NO NAME HERE..>? */ 
Employee.prototype.constructor = Employee; 


e = new Employee('tony', 'manager') 
e.introduce(); 

Err .... ahora qué? Ni siquiera puedo completar esto: this.name en Employee no se puede configurar con el constructor Person adecuado; la creación de un objeto Persona ocurre solo una vez en la herencia.

Entonces ... ¿qué me estoy perdiendo? ¿Es el primer ejemplo que di "el" camino a seguir en mi caso? ¿Y hay una manera de obtener el mismo resultado con el segundo ejemplo?

¡Ayuda!

Respuesta

9

Este tipo de herencia de prototipo se hace a menudo de esta manera:

function Parent() {} 

function Child() { 
    Parent.call(this); // call the constructor of the parent 
} 

var Constr = function() {}; 
Constr.prototype = Parent.prototype; 

Child.prototype = new Constr(); 
Child.prototype.constructor = Child; 

Así que el "truco" consiste en asignar el Parent.prototype como prototipo de una función vacía y establecer una nueva instancia de esta función como prototipo de Child .

Esto se hace para que la extensión Child.prototype no se extienda Parent.prototype.

También debe llamar al constructor principal en el constructor del elemento secundario. Supongo que esta es la parte con la que luchaste. Cada función tiene un método call[docs] y apply[docs] que le permite configurar explícitamente que el elemento this se refiera a dentro de la función.

En su ejemplo, que se vería así:

function Employee(name,title){ 
    this.title=title; 

    Person.call(this, name); 
} 

sin asignar al constructor a una propiedad de la instancia.

En su ejemplo, this.base(name) funciona, porque mediante la asignación del constructor a una propiedad de la instancia (y llamándolo de esta manera), this dentro de la función se refiere a esa instancia.


Existen varias bibliotecas que implementan este patrón, p. Google Closure library:

goog.inherits = function(childCtor, parentCtor) { 
    /** @constructor */ 
    function tempCtor() {}; 
    tempCtor.prototype = parentCtor.prototype; 
    childCtor.superClass_ = parentCtor.prototype; 
    childCtor.prototype = new tempCtor(); 
    childCtor.prototype.constructor = childCtor; 
}; 
+0

No puedo expresar lo agradecido que estoy por esta respuesta ... – Merc

+0

entiendo totalmente la función en la biblioteca de Google Closure (vaya, tengo que llegar a alguna parte: D) Pero! Por lo que entiendo, cuando creo una clase derivada, me corresponde a mí si quiero heredar los atributos internos o no, escribiendo Parent.call (this); o Parent.call (este, nombre) - ¿es eso correcto? Sin embargo, SIEMPRE no querrías hacer eso realmente? – Merc

+0

@Tony: creo que lo harías. Pero si tienes herencia clásica en mente (como Java), entonces también debes llamar al constructor del padre si lo sobreescribes.La única diferencia es que en JavaScript básicamente * siempre * sobrescribe el constructor porque así es como simulamos las clases. Por lo tanto, en realidad no es tan diferente y tal vez sea aún más fácil entender lo que está sucediendo. –

Cuestiones relacionadas