ejemplos - Herencia de Javascript: ¿llamar al superconstructor o usar la cadena de prototipos?
object.create javascript (3)
La forma ideal de hacerlo es no hacer Prod_dept.prototype = new Product();
, porque esto llama al constructor del Product
. Entonces, la forma ideal es clonarlo, excepto el constructor, algo como esto:
function Product(...) {
...
}
var tmp = function(){};
tmp.prototype = Product.prototype;
function Prod_dept(...) {
Product.call(this, ...);
}
Prod_dept.prototype = new tmp();
Prod_dept.prototype.constructor = Prod_dept;
Luego se llama al superconstructor en el momento de la construcción, que es lo que quiere, porque luego puede pasar los parámetros también.
Si observa cosas como la Biblioteca de Cierre de Google, verá que así es como lo hacen.
Recientemente leí sobre el uso de llamadas de JavaScript en MDC
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call
uno de los ejemplos que se muestran a continuación, todavía no entiendo.
¿Por qué están usando herencia aquí así?
Prod_dept.prototype = new Product();
¿Es esto necesario? Porque hay una llamada al superconstructor en
Prod_dept()
de todos modos, así
Product.call
¿esto está fuera del comportamiento común? ¿Cuándo es mejor usar el llamado al superconstructor o usar la cadena de prototipos?
function Product(name, value){
this.name = name;
if(value >= 1000)
this.value = 999;
else
this.value = value;
}
function Prod_dept(name, value, dept){
this.dept = dept;
Product.call(this, name, value);
}
Prod_dept.prototype = new Product();
// since 5 is less than 1000, value is set
cheese = new Prod_dept("feta", 5, "food");
// since 5000 is above 1000, value will be 999
car = new Prod_dept("honda", 5000, "auto");
Gracias por hacer las cosas más claras
La respuesta a la pregunta real es que debe hacer las dos cosas:
- Al configurar el prototipo para una instancia del padre se inicializa la cadena del prototipo (herencia), esto se hace solo una vez (dado que el objeto prototipo se comparte).
- Llamar al constructor del padre inicializa el objeto en sí, esto se hace con cada instanciación (puede pasar diferentes parámetros cada vez que lo construya).
Por lo tanto, no debe llamar al constructor principal al configurar la herencia. Solo cuando crea una instancia de un objeto que hereda de otro.
La respuesta de Chris Morgan está casi completa, falta un pequeño detalle (propiedad del constructor). Déjame sugerir un método para configurar la herencia.
function extend(base, sub) {
// Avoid instantiating the base class just to setup inheritance
// Also, do a recursive merge of two prototypes, so we don''t overwrite
// the existing prototype, but still maintain the inheritance chain
// Thanks to @ccnokes
var origProto = sub.prototype;
sub.prototype = Object.create(base.prototype);
for (var key in origProto) {
sub.prototype[key] = origProto[key];
}
// The constructor property was set wrong, let''s fix it
Object.defineProperty(sub.prototype, ''constructor'', {
enumerable: false,
value: sub
});
}
// Let''s try this
function Animal(name) {
this.name = name;
}
Animal.prototype = {
sayMyName: function() {
console.log(this.getWordsToSay() + " " + this.name);
},
getWordsToSay: function() {
// Abstract
}
}
function Dog(name) {
// Call the parent''s constructor
Animal.call(this, name);
}
Dog.prototype = {
getWordsToSay: function(){
return "Ruff Ruff";
}
}
// Setup the prototype chain the right way
extend(Animal, Dog);
// Here is where the Dog (and Animal) constructors are called
var dog = new Dog("Lassie");
dog.sayMyName(); // Outputs Ruff Ruff Lassie
console.log(dog instanceof Animal); // true
console.log(dog.constructor); // Dog
Ver la publicación de mi blog para obtener aún más azúcar sintáctico al crear clases. http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html
Técnica copiada de Ext-JS y http://www.uselesspickles.com/class_library/ y un comentario de https://.com/users/1397311/ccnokes
Si ha realizado la Programación Orientada a Objetos en JavaScript, sabrá que puede crear una clase de la siguiente manera:
Person = function(id, name, age){
this.id = id;
this.name = name;
this.age = age;
alert(''A new person has been accepted'');
}
Hasta ahora, nuestra persona de clase solo tiene dos propiedades y vamos a darle algunos métodos. Una forma limpia de hacer esto es usar su objeto ''prototipo''. A partir de JavaScript 1.1, el objeto prototipo se introdujo en JavaScript. Este es un objeto integrado que simplifica el proceso de agregar propiedades y métodos personalizados a todas las instancias de un objeto. Agreguemos 2 métodos a nuestra clase usando su objeto ''prototipo'' de la siguiente manera:
Person.prototype = {
/** wake person up */
wake_up: function() {
alert(''I am awake'');
},
/** retrieve person''s age */
get_age: function() {
return this.age;
}
}
Ahora hemos definido nuestra clase Persona. ¿Qué pasaría si quisiéramos definir otra clase llamada Manager que herede algunas propiedades de Person? No tiene sentido redefinir todas estas propiedades de nuevo cuando definimos nuestra clase Manager, podemos simplemente configurarla para que herede de la clase Person. JavaScript no tiene herencia incorporada, pero podemos usar una técnica para implementar la herencia de la siguiente manera:
Inheritance_Manager = {};
// Creamos una clase de administrador de herencia (el nombre es arbitrario)
Ahora demos a nuestra clase de herencia un método llamado extend que toma los argumentos de baseClass y subClassas. Dentro del método de extensión, crearemos una clase interna llamada inheritance function inheritance () {}. La razón por la que estamos usando esta clase interna es para evitar la confusión entre los prototipos de baseClass y subClass. A continuación, hacemos que el prototipo de nuestra clase de herencia apunte al prototipo baseClass como con el siguiente código: inheritance.prototype = baseClass. prototipo; Luego copiamos el prototipo de herencia en el prototipo de subclase de la siguiente manera: subClass.prototype = new inheritance (); Lo siguiente es especificar el constructor para nuestra subclase de la siguiente manera: subClass.prototype.constructor = subClass; Una vez que terminemos con nuestro prototipo de subclase, podemos especificar las siguientes dos líneas de código para establecer algunos punteros de clase base.
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
Aquí está el código completo para nuestra función de extensión:
Inheritance_Manager.extend = function(subClass, baseClass) {
function inheritance() { }
inheritance.prototype = baseClass.prototype;
subClass.prototype = new inheritance();
subClass.prototype.constructor = subClass;
subClass.baseConstructor = baseClass;
subClass.superClass = baseClass.prototype;
}
Ahora que hemos implementado nuestra herencia, podemos comenzar a usarla para extender nuestras clases. En este caso vamos a extender nuestra clase Person a una clase Manager de la siguiente manera:
Definimos la clase Manager
Manager = function(id, name, age, salary) {
Person.baseConstructor.call(this, id, name, age);
this.salary = salary;
alert(''A manager has been registered.'');
}
lo hacemos heredar de la Persona
Inheritance_Manager.extend(Manager, Person);
Si se dio cuenta, acabamos de llamar al método extendido de nuestra clase Inheritance_Manager y pasamos el subClass Manager en nuestro caso y luego la persona baseClass. Tenga en cuenta que el orden es muy importante aquí. Si los intercambias, la herencia no funcionará como quisieras. También tenga en cuenta que deberá especificar esta herencia antes de que pueda definir nuestra subclase. Ahora definamos nuestra subclase:
Podemos agregar más métodos como el siguiente. Nuestra clase Manager siempre tendrá los métodos y propiedades definidos en la clase Person porque hereda de ella.
Manager.prototype.lead = function(){
alert(''I am a good leader'');
}
Ahora para probarlo, vamos a crear dos objetos, uno de la clase Persona y el otro de la clase heredada Administrador:
var p = new Person(1, ''Joe Tester'', 26);
var pm = new Manager(1, ''Joe Tester'', 26, ''20.000'');
Siéntase libre de obtener el código completo y más comentarios en: http://www.cyberminds.co.uk/blog/articles/how-to-implement-javascript-inheritance.aspx