índice
herdar
6.3.1 Cadeia de protótipo
Cadeia de protótipo como o principal método de herança: a ideia básica é usar o protótipo para permitir que um tipo de referência herde as propriedades e métodos de outro tipo de referência
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
O código acima define dois construtores: SuperType
e Subtype
, cada tipo possui uma propriedade e um método, a principal diferença entre eles é a SubType
herança SuperType
.
A herança é obtida criando SuperType
uma instância e atribuindo a instância à SubType.prototype
realização.
A essência da implementação é reescrever o objeto de protótipo e substituí-lo por uma instância de um novo tipo. Em outras palavras, SuperType
as propriedades e métodos que existiam originalmente em agora também existem em SubType.prototype
.
Depois de estabelecer a relação de herança, SubType.prototype
adicionamos um método, para SuperType
que um novo método fosse adicionado com base nas propriedades e métodos herdados .
O resultado final é este:
instance
SubType
Protótipo pontiagudo
SubType
Protótipo e SuperType
protótipo dirigido
getSuperValue()
Ainda no SuperType.prototype
meio, mas property
no SubType.prototype
meio. Isso ocorre porque property
é uma propriedade de instância, mas getSuperValue()
um método de protótipo
-
Observação:
instance.constructor
agora está apontando para oSuperType
motivo de isso ser porque oSubType.prototype
construtor original foi reescrito. -
Determine a relação entre protótipo e instância:
instanceof
OperadorisPrototypeOf()
método
-
Desvantagens da herança da cadeia de protótipo:
-
Todas as instâncias do construtor filho compartilharão a definição do construtor pai
引用类型值属性
.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"
As nossas
instance1.colors
alterações podem serinstance2.colors
refletidas, o que provou plenamente este ponto. -
Ao criar uma instância de um subtipo, você não pode passar parâmetros para o construtor do supertipo.
-
6.3.2 Construtor de empréstimo
Para resolver os problemas causados pela inclusão de valores de tipo de referência na cadeia de protótipos, os desenvolvedores começaram a usar uma técnica chamada construtores emprestados.
-
A ideia básica: chamar o construtor do supertipo dentro do construtor do subtipo (a função é apenas um objeto que executa o código em um ambiente específico, então o construtor também pode ser executado no objeto recém-criado usando os métodos apply () e 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"
A linha de fundo no código "secundou" o construtor do supertipo.
Ao usar o
call()``和apply()
método, realmenteSubType
chamamos oSuperType
construtor no ambiente da instância recém-criada .Desta forma, todos os códigos de inicialização do objeto definidos na função serão
SubType
executados no novo objetoSuperType()
,SubType
e todas as instâncias do resultado terãocolors
cópias de suas próprias propriedades. -
Parâmetros de passagem
Em comparação com a herança da cadeia de protótipo, tomar emprestado o construtor tem uma grande vantagem.Você pode passar parâmetros para o construtor do supertipo no construtor do 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
-
O problema de pegar emprestado o construtor
Se você apenas pegar emprestado o construtor, não poderá evitar o problema do modo do construtor. Os métodos são definidos no construtor, portanto, não há como falar sobre reutilização de função.
Os métodos definidos no protótipo do supertipo não são visíveis para o subtipo.
6.3.3 Herança combinada
-
Herança de combinação refere-se à combinação da cadeia de protótipo e a tecnologia de construtores de empréstimo
-
Idéia: Use a cadeia de protótipo para implementar a herança de propriedades e métodos de protótipo, e use o construtor para implementar a herança de propriedades de instância.
-
Ele não apenas realiza a reutilização de funções definindo métodos no protótipo, mas também garante que cada instância tenha suas próprias propriedades.
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
Neste exemplo,
SuperType
dois atributos são definidos:name
ecolors
.SuperType
O protótipo define um métodosayName()
.SubType
O construtorSuperType
passaname
parâmetros ao chamar o construtor e, em seguida, define suas próprias propriedadesage
.Em seguida, atribua
SuperType
a instância aoSubType
protótipo e defina o método no protótiposayAge()
Dessa forma, duas
SubType
instâncias diferentes podem ter seus próprios atributos, incluindocolors
atributos, e podem usar o mesmo método. -
A herança combinatória evita os defeitos da cadeia de protótipo e da herança do construtor emprestado, combina suas vantagens e se torna o modo de herança mais comumente usado em JavaScript.
-
instanceof
EisPrototypeOf
ser capaz de reconhecer objetos criados com base na herança combinada.
6.3.4 Herança de protótipo
Idéia: Com a ajuda de protótipos, novos objetos podem ser criados com base em objetos existentes sem a necessidade de criar tipos personalizados.
function object(o) {
function F() {
};
F.prototype = o;
return new F();
}
Dentro da função object (), um construtor temporário é criado e, em seguida, o objeto passado é usado como o protótipo do construtor e, finalmente, uma nova instância de um tipo temporário é retornada. Essencialmente, object () executa uma cópia superficial do objeto passado.
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 Herança parasitária
-
A herança parasitária é uma ideia intimamente relacionada à herança do protótipo
-
Ideia: Criar uma função que só serve para encapsular o processo de herança.A função aprimora internamente o objeto de uma certa maneira e, finalmente, retorna o objeto como se ele realmente fizesse todo o trabalho.
function createAnother(original) { var clone = object(original) // 通过调用函数创建一个新对象 clone.sayHi = function() { // 以某种方式来增强这个对象 alert("hi") } return clone // 返回这个对象 }
6.3.6 Herança combinada parasitária
A herança combinatória é o padrão de herança mais comumente usado em JavaScript, mas também tem suas próprias deficiências. O maior problema com a herança combinatória é que não importa qual seja a situação, o construtor do supertipo será chamado duas vezes: uma ao criar o protótipo da subclasse e outra vez dentro do construtor da subclasse.
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);
};
Ao chamar a SuperType()
função pela primeira vez , SuperType.prototype
você obterá duas propriedades: name
, colors
; Ambas são SuperType
propriedades de instância, mas agora estão no SubType
protótipo. Quando o SubType
construtor é chamado, o construtor é chamado novamente SuperType
, desta vez criando atributos de instância name
e no novo objeto colors
. Portanto, este atributo bloqueia os dois atributos com o mesmo nome no protótipo.
Em outras palavras, existem dois conjuntos de atributos de nome e cores: um definido no exemplo e outro definido no SubType
protótipo. Este é SubType
o resultado de chamar o construtor duas vezes .
Felizmente, encontramos uma maneira de resolver esse problema de herança combinada parasita.
-
Herança combinada de parasitas: herde propriedades emprestando construtores e herde métodos por meio de formas mistas de cadeia de protótipo
-
A ideia básica: você não precisa chamar o construtor do supertipo para especificar o protótipo do subtipo.O que queremos nada mais é do que uma cópia do protótipo do supertipo.
-
Essência: Use a herança parasitária para herdar o protótipo do supertipo e, em seguida, atribua o resultado ao protótipo do subtipo. O padrão básico de herança combinada parasitária é o seguinte:
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
A eficiência deste exemplo é refletida no fato de que ele chama o SuperType
construtor apenas uma vez e, portanto, evita a SubType.prototype
criação de propriedades desnecessárias e redundantes nele. Ao mesmo tempo, a cadeia de protótipo pode permanecer inalterada; ela também pode ser usada instanceof
eisPrototypeOf()