Tabla de contenido
heredar
6.3.1 Cadena de prototipos
Cadena de prototipos como método principal de herencia: la idea básica es utilizar el prototipo para permitir que un tipo de referencia herede las propiedades y métodos de otro tipo de referencia.
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property;
};
function SubType(){
this.subproperty = false;
}
//inherit from SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.subproperty;
};
var instance = new SubType();
alert(instance.getSuperValue()); //true
alert(instance instanceof Object); //true
alert(instance instanceof SuperType); //true
alert(instance instanceof SubType); //true
alert(Object.prototype.isPrototypeOf(instance)); //true
alert(SuperType.prototype.isPrototypeOf(instance)); //true
alert(SubType.prototype.isPrototypeOf(instance)); //true
El código anterior define dos constructores: SuperType
y Subtype
, cada tipo tiene una propiedad y un método, la principal diferencia entre ellos es la SubType
herencia SuperType
.
La herencia se logra creando SuperType
una instancia y asignándola a la SubType.prototype
realización.
La esencia de la implementación es reescribir el objeto prototipo y reemplazarlo con una instancia de un nuevo tipo. En otras palabras, SuperType
las propiedades y métodos que existían originalmente en ahora también existen en SubType.prototype
.
Después de establecer la relación de herencia, SubType.prototype
agregamos un método, de modo SuperType
que se agregó un nuevo método sobre la base de las propiedades y métodos heredados .
El resultado final es este:
instance
SubType
Prototipo puntiagudo
SubType
Prototipo y SuperType
prototipo dirigido
getSuperValue()
Todavía en el SuperType.prototype
medio, pero property
en el SubType.prototype
medio. Esto se debe a que property
es una propiedad de instancia, pero getSuperValue()
un método prototipo
-
Nota:
instance.constructor
Ahora señala laSuperType
razón por la que esto se debe a que elSubType.prototype
constructor original se ha reescrito. -
Determine la relación entre el prototipo y la instancia:
instanceof
OperadorisPrototypeOf()
método
-
Desventajas de la herencia de la cadena de prototipos:
-
Todas las instancias del constructor hijo compartirán la definición del constructor padre
引用类型值属性
.function SuperType(){ this.colors = ["red", "blue", "green"]; } function SubType(){ } //inherit from SuperType SubType.prototype = new SuperType(); var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green,black"
Nuestras
instance1.colors
enmiendas puedeninstance2.colors
reflejarse, lo que ha demostrado plenamente este punto. -
Al crear una instancia de un subtipo, no puede pasar parámetros al constructor del supertipo.
-
6.3.2 Constructor de préstamos
Para resolver los problemas causados por la inclusión de valores de tipo de referencia en la cadena del prototipo, los desarrolladores comenzaron a utilizar una técnica llamada constructores prestados.
-
La idea básica: llamar al constructor de supertipo dentro del constructor de subtipo (la función es solo un objeto que ejecuta código en un entorno específico, por lo que el constructor también se puede ejecutar en el objeto recién creado usando los métodos apply () y call () .
function SuperType(){ this.colors = ["red", "blue", "green"]; } function SubType(){ // inherit from SuperType // here, this will point to instance of SubType SuperType.call(this); } var instance1 = new SubType(); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" var instance2 = new SubType(); alert(instance2.colors); //"red,blue,green"
La línea de fondo en el código "secundó" al constructor de supertipo.
Al usar el
call()``和apply()
método, en realidadSubType
llamamos alSuperType
constructor en el entorno de la instancia recién creada .De esta manera, todos los códigos de inicialización de objeto definidos en la función se
SubType
ejecutarán en el nuevo objeto y todas las instancias delSuperType()
resultadoSubType
tendráncolors
copias de sus propias propiedades. -
Pasar parámetros
En comparación con la herencia de la cadena de prototipos, tomar prestado el constructor tiene una gran ventaja: puede pasar parámetros al constructor de supertipo en el constructor de subtipo.
function SuperType(name){ this.name = name; } function SubType(){ //inherit from SuperType passing in an argument SuperType.call(this, "Nicholas"); //instance property this.age = 29; } var instance = new SubType(); alert(instance.name); //"Nicholas"; alert(instance.age); //29
-
El problema de pedir prestado al constructor
Si solo toma prestado el constructor, entonces no puede evitar el problema del modo constructor Los métodos están definidos en el constructor, por lo que no hay forma de hablar sobre la reutilización de funciones.
Los métodos definidos en el prototipo del supertipo no son visibles para el subtipo.
6.3.3 Herencia combinada
-
La herencia combinada se refiere a la combinación de la cadena de prototipos y la tecnología de los constructores prestatarios.
-
Idea: use la cadena de prototipos para implementar la herencia de propiedades y métodos de prototipos, y use el constructor para implementar la herencia de propiedades de instancia.
-
No solo se da cuenta de la reutilización de funciones mediante la definición de métodos en el prototipo, sino que también asegura que cada instancia tenga sus propias propiedades.
function SuperType(name){ this.name = name; this.colors = ["red", "blue", "green"]; } SuperType.prototype.sayName = function(){ alert(this.name); }; function SubType(name, age){ // 继承属性 SuperType.call(this, name); this.age = age; } // 继承方法 SubType.prototype = new SuperType(); SubType.prototype.constructor = SubType; SubType.prototype.sayAge = function(){ alert(this.age); }; var instance1 = new SubType("Nicholas", 29); instance1.colors.push("black"); alert(instance1.colors); //"red,blue,green,black" instance1.sayName(); //"Nicholas"; instance1.sayAge(); //29 var instance2 = new SubType("Greg", 27); alert(instance2.colors); //"red,blue,green" instance2.sayName(); //"Greg"; instance2.sayAge(); //27
En este ejemplo, se
SuperType
definen dos atributos:name
ycolors
.SuperType
El prototipo define un métodosayName()
.SubType
El constructorSuperType
pasaname
parámetros cuando llama al constructor y luego define sus propias propiedadesage
.Luego, asigne
SuperType
la instancia alSubType
prototipo y luego defina el método en el prototiposayAge()
De esta manera, dos
SubType
instancias diferentes pueden tener sus propios atributos, incluidos loscolors
atributos, y pueden utilizar el mismo método. -
La herencia combinatoria evita los defectos de la cadena de prototipos y la herencia del constructor prestado, combina sus ventajas y se convierte en el modo de herencia más utilizado en JavaScript.
-
instanceof
YisPrototypeOf
ser capaz de reconocer objetos creados en base a la herencia combinada.
6.3.4 Herencia de prototipos
Idea: Con la ayuda de prototipos, se pueden crear nuevos objetos basados en objetos existentes sin tener que crear tipos personalizados.
function object(o) {
function F() {
};
F.prototype = o;
return new F();
}
Dentro de la función object (), se crea un constructor temporal, y luego el objeto pasado se usa como prototipo del constructor, y finalmente se devuelve una nueva instancia de un tipo temporal. Esencialmente, object () realiza una copia superficial del objeto pasado.
function object(o){
function F(){
}
F.prototype = o;
return new F();
}
var person = {
name: "Nicholas",
friends: ["Shelby", "Court", "Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
6.3.5 Herencia parasitaria
-
La herencia parasitaria es una idea estrechamente relacionada con la herencia de prototipos
-
Idea: Crea una función que solo se use para encapsular el proceso de herencia, la función mejora internamente el objeto de cierta manera y finalmente devuelve el objeto como si realmente hiciera todo el trabajo.
function createAnother(original) { var clone = object(original) // 通过调用函数创建一个新对象 clone.sayHi = function() { // 以某种方式来增强这个对象 alert("hi") } return clone // 返回这个对象 }
6.3.6 Herencia combinada de parásitos
La herencia combinatoria es el patrón de herencia más utilizado en JavaScript, pero también tiene sus propias deficiencias. El mayor problema con la herencia combinatoria es que no importa cuál sea la situación, el constructor de supertipo se llamará dos veces: una vez al crear el prototipo de subclase y la otra vez dentro del constructor de subclase.
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
// 继承属性
SuperType.call(this, name); // 第二次调用SuperType()
this.age = age;
}
// 继承方法
SubType.prototype = new SuperType(); // 第一次调用 SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
Cuando llame a la SuperType()
función por primera vez , SuperType.prototype
obtendrá dos propiedades: name
, colors
; Ambas son SuperType
propiedades de instancia, pero ahora están en SubType
el prototipo. Cuando SubType
se llama al constructor, se vuelve a llamar al constructor SuperType
, esta vez creando atributos de instancia name
y sobre el nuevo objeto colors
. Por tanto, este atributo bloquea los dos atributos con el mismo nombre en el prototipo.
En otras palabras, hay dos conjuntos de atributos de nombre y colores: uno en el ejemplo y otro en el SubType
prototipo. Este es SubType
el resultado de llamar al constructor dos veces .
Afortunadamente, hemos encontrado una manera de resolver este problema de herencia combinada parasitaria.
-
Herencia combinada de parásitos: hereda propiedades tomando prestados constructores y hereda métodos a través de formas mixtas de cadena de prototipos
-
La idea básica: no es necesario llamar al constructor del supertipo para especificar el prototipo del subtipo, lo que queremos es nada más que una copia del prototipo del supertipo.
-
Esencia: utilice la herencia parasitaria para heredar el prototipo del supertipo y luego asigne el resultado al prototipo del subtipo. El patrón básico de herencia combinada parasitaria es el siguiente:
function inheritPrototype(subType, superType) {
var prototype = object(superType.prototype) // 创建对象(超类型原型的一个副本)
prototype.constructor = subType // 增强对象(为创建的副本添加constructor属性)
subType.prototype = prototype // 指定对象
}
function object(o){
function F(){
}
F.prototype = o;
return new F();
}
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //create object
prototype.constructor = subType; //augment object
subType.prototype = prototype; //assign object
}
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType);
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27
La eficiencia de este ejemplo se refleja en que solo llama al SuperType
constructor una vez y, por lo tanto, evita SubType.prototype
crear propiedades innecesarias y redundantes en él. Al mismo tiempo, la cadena de prototipos puede permanecer sin cambios; también se puede utilizar instanceof
yisPrototypeOf()