Maison > interface Web > js tutoriel > le corps du texte

Compréhension approfondie des six méthodes d'héritage de JavaScript (image et texte)

黄舟
Libérer: 2017-03-24 14:44:19
original
1019 Les gens l'ont consulté

Cet article amènera tout le monde à recomprendre les six méthodes d'héritage de JavaScript Il est très bon et a une valeur de référence. Les amis qui en ont besoin peuvent se référer à

.

Héritage basé sur les classes (Constructeur)

Il n'y a en fait aucun concept de classes dans JS, et les soi-disant classes sont également simulé. Surtout lorsque nous utilisons le mot-clé new, le concept de « classe » ressemble davantage à des classes dans d'autres langages. L'héritage de classe consiste à appeler le constructeur de la classe parent dans l'objet fonction afin qu'il puisse obtenir les méthodes et propriétés de la classe parent. Les méthodes call et apply prennent en charge l’héritage de classe. En modifiant l'environnement d'action de celui-ci, la sous-classe elle-même possède divers attributs de la classe parent.

var father = function() {
this.age = 52;
this.say = function() {
alert('hello i am '+ this.name ' and i am '+this.age + 'years old');
}
}
var child = function() {
this.name = 'bill';
father.call(this);
}
var man = new child();
man.say();
Copier après la connexion

Héritage prototypique

L'héritage prototypique est souvent utilisé dans le développement. C'est différent de l'héritage de classe car l'héritage ne se trouve pas dans l'objet lui-même, mais dans le prototype de l'objet (prototype). Chaque objet a un prototype, qui est reflété dans le navigateur sous la forme d'un attribut proto caché. Dans certains navigateurs modernes, vous pouvez les modifier. Par exemple, dans zepto, en ajoutant l'objet fn de zepto à l'attribut proto d'un tableau vide, le tableau devient un objet zepto et possède toutes les méthodes. Cela dit, lorsqu'un objet a besoin d'appeler une méthode, il retourne au prototype le plus proche pour trouver la méthode. S'il n'est pas trouvé, il poursuivra sa recherche vers le bas. De cette façon, j’ai cherché étape par étape jusqu’à trouver la méthode que je cherchais. Ces prototypes recherchés forment la chaîne de prototypes de l'objet. Le prototype pointe finalement vers null. Ce que nous appelons l'héritage prototypique consiste à transférer les méthodes de l'objet parent vers le prototype de la classe enfant. Ces méthodes et propriétés ne sont pas disponibles dans le constructeur de sous-classes.

var father = function() {
}
father.prototype.a = function() {
}
var child = function(){}
//开始继承
child.prototype = new father();
var man = new child();
man.a();
Copier après la connexion

Vous pouvez voir que l'héritage prototypique est implémenté dans la septième ligne. Cette méthode est familière à de nombreuses personnes. En imprimant man dans le navigateur, nous pouvons vérifier la relation d'héritage de chaque prototype.

Vous pouvez voir la relation hiérarchique enfant->objet (l'objet instancié par le père)->père. L'enfant hérite des éléments du prototype du père via la couche intermédiaire. Mais pourquoi y a-t-il une couche d'objet au milieu ? Pourquoi ne pas définir child.prototype = Father.prototype. La réponse est que si vous faites cela, il n’y aura aucune différence entre l’enfant et le père. N'oubliez pas qu'il existe un attribut constructeur dans prototype, qui pointe vers le constructeur. Dans des circonstances normales, nous devons modifier la valeur du constructeur pour qu'il pointe vers le constructeur de l'enfant. Mais si père.prototype est directement affecté à enfant.prototype, vers qui le constructeur doit-il pointer ? Il est donc évident que l’enfant et le père ne peuvent être maintenus en tant qu’objets indépendants qu’à travers la couche intermédiaire.

Comparaison entre l'héritage de classe et l'héritage prototypique

Héritage de constructeur (classe)

Premier de Dans l'ensemble, les méthodes héritées du constructeur seront stockées dans l'objet parent et la fonction sera enregistrée dans la mémoire pour chaque instance. Cette approche ne devrait pas causer de problèmes de performances.

Deuxièmement, l'héritage de classe est immuable. Elle ne peut pas être réutilisée. Elle ne peut pas modifier ou ajouter de nouvelles méthodes pendant l'exécution. Cette méthode est une méthode morte et autonome. En pratique, il est rarement utilisé simplement.

Héritage prototypique

Avantages :

La chaîne de prototypes peut être modifiée : la classe parent sur la chaîne de prototypes est remplaçable et extensible

Les sous-classes peuvent être modifiées en changeant le lien du prototype. De plus, l'héritage de classe ne prend pas en charge l'héritage multiple, mais pour l'héritage prototypique, il vous suffit d'écrire extend pour étendre l'objet.

Mais l'héritage de chaîne de prototypes présente également deux problèmes.

Tout d'abord, l'attribut prototype contenant la valeur de type référence sera partagé par toutes les instances (cela peut être compris de cette façon : exécutez sub1.arr.push(2); effectuez d'abord un attribut recherchez sur sub1 et trouvez que j'ai cherché dans les attributs d'instance (il n'y avait aucun attribut d'instance dans cet exemple) et je ne l'ai pas trouvé, j'ai donc commencé à rechercher la chaîne de prototypes et j'ai obtenu l'objet prototype de sub1 que j'ai recherché et trouvé là-bas. était un attribut arr, j'ai donc inséré 2 à la fin de arr sub2.arr a également changé).

Deuxièmement, lors de la création d'une instance d'un sous-type, les paramètres ne peuvent pas être transmis au constructeur du supertype. (En fait, il faut dire qu'il n'existe aucun moyen de transmettre des paramètres au constructeur d'un supertype sans affecter toutes les instances d'objet.) En pratique, le chaînage de prototypes purs est rarement utilisé.

function Super(){
this.val = 1;
this.arr = [1];
}
function Sub(){
// ...
}
Sub.prototype = new Super(); // 核心
var sub1 = new Sub();
var sub2 = new Sub();
sub1.val = 2;
sub1.arr.push(2);
alert(sub1.val); // 2
alert(sub2.val); // 1
alert(sub1.arr); // 1, 2
alert(sub2.arr); // 1, 2
Copier après la connexion

Résumé :

Lors de l'instanciation de l'héritage de classe, la classe parent peut transmettre des paramètres et ne peut pas être réutilisée (la classe parent ne peut pas modifier , chaque instance enregistrera le contenu de la classe parent en mémoire)

原型继承在实例化时,父类不可传参,可以复用(原型链可改变(父类可替换可扩展),父类不会保存在内存中,而是顺着原型链查找,但是结果是原型属性会被所有实例共享(尤其影响引用类型值))

组合继承(最常用)

组合继承将原型链和借用构造函数的技术结合到一起,发挥两者之长的一种继承模式。

思路是使用原型链实现对原型属性和方法的继承,通过借用构造函数实现对实例属性的继承。

function SuperType(name){
this.name = name;
this.numbers = [1,2,3];
}
SuperType.prototype.sayName = function(){
console.log(this.name);
}
function SubType(name,age){
SuperType.call(this,name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.sayAge = function(){
console.log(this.age);
}
var instance1 = new SubType('aaa',21);
instance1.numbers.push(666);
console.log(instance1.numbers);
instance1.sayName();
instance1.sayAge();
var instance2 = new SubType('bbb',22);
console.log(instance2.numbers);
instance2.sayName();
instance2.sayAge();
Copier après la connexion

把实例函数都放在原型对象上,通过Sub.prototype = new Super();继承父类函数,以实现函数复用。

保留借用构造函数方式的优点,通过Super.call(this);继承父类的基本属性和引用属性,以实现传参;

优缺点

优点:

  1. 可传参

  2. 函数可复用

  3. 不存在引用属性共享问题(图纸)

缺点:

(一点小瑕疵)子类原型上有一份多余的父类实例属性,因为父类构造函数被调用了两次,生成了两份,而子类实例上的那一份屏蔽了子类原型上的。。。又是内存浪费,比刚才情况好点,不过确实是瑕疵。

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!