Maison >interface Web >js tutoriel >Quelles sont les deux formes d'héritage javascript ?

Quelles sont les deux formes d'héritage javascript ?

青灯夜游
青灯夜游original
2021-04-08 14:16:261742parcourir

L'héritage Javascript a deux formes : "usurpation d'identité d'objet" et "mode prototype". L'essence de l'usurpation d'identité d'objet est de changer le but de cela ; et l'héritage de prototype fait référence à l'utilisation d'un prototype ou d'un prototype remplaçant d'une manière ou d'une autre pour atteindre l'objectif de copier des méthodes d'attribut.

Quelles sont les deux formes d'héritage javascript ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, JavaScript version 1.8.5, ordinateur Dell G3.

Javascript lui-même a évolué à partir de la syntaxe du langage Perl. Il s'agit essentiellement d'un langage de script. Au fur et à mesure de la mise à jour de la version, une simulation orientée objet est progressivement ajoutée.

Je pense que la simulation orientée objet de JS est généralement bonne, car nous ne pouvons suivre aveuglément aucun concept, et nous ne pouvons pas faire de la POO uniquement pour le plaisir de la POO. Ce que nous devons comprendre, ce sont les avantages de l'objet. orienté quoi ? Passer à la POO pour ces avantages est le choix le plus judicieux, donc Js s'en sort plutôt bien. L'héritage des

Js est soigneusement divisé en de nombreux types et méthodes de mise en œuvre dans de nombreux livres. Il en existe généralement deux types : l'usurpation d'identité d'objet et la méthode de prototype. Les deux méthodes ont leurs propres avantages et inconvénients. Je vais d'abord les énumérer ici, puis analyser les différences à partir du niveau inférieur :

(1) Usurpation d'identité d'objet

function A(name){
this.name = name;
this.sayHello = function(){alert(this.name+” say Hello!”);};
}
function B(name,id){
this.temp = A;
this.temp(name); //相当于new A();
delete this.temp; //防止在以后通过temp引用覆盖超类A的属性和方法
this.id = id;
this.checkId = function(ID){alert(this.id==ID)};
}

Lors de la construction de l'objet B, appeler temp équivaut à démarrer le constructeur de A. Notez que cet objet dans le contexte ici est une instance de B, donc lorsque le script du constructeur A est exécuté, toutes les variables et méthodes de A le seront être assigné à ceci. L'objet auquel il fait référence est une instance de B. De cette façon, l'objectif de B héritant des méthodes d'attribut de A est atteint. La suppression de la température de référence temporaire après

empêche le maintien du changement de référence sur l'objet de classe de A (notez qu'il ne s'agit pas d'un objet instance) dans B, car la modification de la température entraînera directement la structure de la classe A (notez que ce n'est pas un objet de changement de classe A).

Nous avons vu que lors du processus de mise à jour de la version Js, afin d'effectuer plus facilement ce changement de contexte pour obtenir un héritage ou des objectifs plus larges, les fonctions d'appel et d'application ont été ajoutées. Leurs principes sont les mêmes, juste des versions différentes de paramètres (un paramètre arbitraire variable, un autre doit être passé dans un tableau en tant que jeu de paramètres). Ici, nous prenons call comme exemple pour expliquer l'héritage d'usurpation d'identité d'objet implémenté par call.

function Rect(width, height){
this.width = width;
this.height = height;
this.area = function(){return this.width*this.height;};
}
function myRect(width, height, name){
Rect .call(this,width,height);
this.name = name;
this.show = function(){
alert(this.name+” with area:”+this.area());
}
}

A propos de la méthode Call, explication officielle : Appeler une méthode d'un objet pour remplacer l'objet actuel par un autre objet.

call (thisOb,arg1, arg2…)

C'est aussi une sorte d'héritage d'usurpation d'identité d'objet. En fait, ce qui se passe lorsque la méthode d'appel est appelée est le remplacement de la variable d'environnement contextuelle this dans le corps de la fonction myRect, cela doit pointer vers un. instance de l'objet de classe myRect. Cependant, utilisez-la comme variable d'environnement contextuelle pour appeler la méthode nommée Rect, qui est le constructeur de la classe Rect.

Ainsi, lors de l'appel de Rect à ce moment-là, les attributs et méthodes d'affectation à celui-ci sont en fait effectués sur un objet myRect. Ainsi, bien que call et apply ne soient pas de nouvelles méthodes uniquement destinées à l’héritage, elles peuvent être utilisées pour simuler l’héritage.

C'est ce dont les objets prétendent hériter. Il peut obtenir un héritage multiple, il suffit de répéter cet ensemble de processus d'affectation. Cependant, il n’est pas vraiment utilisé à grande échelle à l’heure actuelle. Pourquoi ?

Parce qu'il présente un défaut de performances évident, il s'agit du concept d'OO. Nous disons qu'un objet est une collection de membres + méthodes membres. Lors de la construction d'instances d'objet, ces instances n'ont besoin que de leur propre membre. variables. C'est tout. La méthode membre est juste une zone de texte exécutable qui opère sur les variables. Cette zone n'a pas besoin d'être copiée pour chaque instance, et toutes les instances peuvent la partager.

Revenons maintenant à l'héritage de JS consistant à utiliser des objets pour faire semblant d'être simulés. Toutes les méthodes membres sont créées pour cela, c'est-à-dire que toutes les instances auront une copie de la méthode membre, qui est une référence aux ressources mémoire. Un gaspillage extrême.

Inutile de mentionner d'autres défauts, comme l'incapacité de l'usurpation d'identité d'objet à hériter des variables et des méthodes du domaine prototype, je pense que l'ancien défaut fatal est suffisant. Cependant, nous devons encore le comprendre, en particulier le principe de l'héritage des attributs et des méthodes de la classe parent, ce qui est très important pour comprendre l'héritage JS.

[Apprentissage recommandé : Tutoriel JavaScript avancé]

(2) Méthode prototype

La deuxième méthode d'héritage est la méthode prototype , ce qu'on appelle l'héritage de la méthode prototype, fait référence à l'utilisation d'un prototype ou à la couverture du prototype d'une manière ou d'une autre, afin d'atteindre l'objectif de copie de la méthode d'attribut. Il existe de nombreuses façons de le mettre en œuvre, et il peut y avoir des différences entre les différents cadres, mais si nous comprenons les principes, il n'y aura rien que nous ne comprenions pas. Regardez un exemple (une certaine implémentation) :

function Person(){
this.name = “Mike”;
this.sayGoodbye = function(){alert(“GoodBye!”);};
}
Person.prototype.sayHello = function(){alert(”Hello!”);};
function Student(){}
Student.prototype = new Person();

La clé est d'attribuer la valeur de l'attribut prototype Student dans la dernière phrase à l'objet construit par la classe Person. Ici, je vais expliquer comment les attributs et. les méthodes de la classe parent sont copiées dans la sous-classe de.

Lorsqu'un objet JS lit les attributs d'un objet, il vérifie toujours en premier la liste des attributs de son propre domaine, s'il y en a une, il la renvoie sinon, il lit le domaine prototype s'il est trouvé. , il le renvoie, car le prototype peut pointer vers d'autres choses. L'interpréteur JS recherchera donc récursivement le champ prototype vers lequel le champ prototype pointe vers l'objet, et s'arrêtera jusqu'à ce que le prototype soit lui-même s'il n'est pas trouvé. avec le temps, cela devient indéfini.

这样看来,最后一句发生的效果就是将父类所有属性和方法连接到子类的prototype域上,这样子类就继承了父类所有的属性和方法,包括name、 sayGoodbye和sayHello。这里与其把最后一句看成一种赋值,不如理解成一种指向关系更好一点。

这种原型继承的缺陷也相当明显,就是继承时 父类的构造函数时不能带参数,因为对子类prototype域的修改是在声明子类对象之后才能进行,用子类构造函数的参数去初始化父类属性是无法实现的, 如下所示:

function Person(name){
this.name = name;
}
function Student(name,id){
this.id = id;
}
Student.prototype = new Person(this.name);

两种继承方式已经讲完了,如果我们理解了两种方式下子类如何把父类的属性和方法“抓取”下来,就可以自由组合各自的利弊,来实现真正合理的Js继承。下面是个人总结的一种综合方式:

function Person(name){
this.name = name;
}
Person.prototype.sayHello = function(){alert(this.name+“say Hello!”);};
function Student(name,id){
Person.call(this,name);
this.id = id;
}
Student.prototype = new Person();
Student.prototype.show = function(){
alert(“Name is:”+ this.name+” and Id is:”+this.id);

总结就是利用对象冒充机制的call方法把父类的属性给抓取下来,而成员方法尽量写进被所有对象实例共享的prototype域中,以防止方法副本重复创 建。然后子类继承父类prototype域来抓取下来所有的方法。

如想彻底理清这些调用链的关系,推荐大家多关注Js中prototype的 constructor和对象的constructor属性,这里就不多说了。

更多编程相关知识,请访问:编程视频!!

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!

Déclaration:
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