Bien que JavaScript soit une langue orientée objet, son mécanisme d'héritage était différent des autres langues traditionnelles orientées objet depuis sa création. Il s'agit d'un mécanisme d'héritage basé sur un prototype. Cependant, en vertu de ce mécanisme, il existe encore différentes méthodes de mise en œuvre d'hérédité.
Méthode 1: Héritage classique
Le soi-disant héritage de classe se réfère à l'imitation de la méthode d'héritage des langues orientées objet traditionnelles. L'héritage et les partis hérités sont des «classes». Le code est le suivant:
Définissez d'abord une classe parent (ou superclasse):
fonction personne (name) {this.name = name; } Personne.prototype.getName = function () {return this.name; };Les attributs de la personne de la classe parent sont définis dans le constructeur, ce qui peut garantir que l'attribut de nom de la sous-classe hérite qu'il ne partage pas cet attribut, mais appartient à la sous-classe séparément. La méthode GetName est montée sur le prototype afin d'autoriser plusieurs instances de la sous-classe dont l'héritage de partager ce corps de la méthode, afin que la mémoire puisse être enregistrée (pour plusieurs instances, chaque fois qu'une instance de nouveau sort, elle s'assurera que la méthode GetName de ces instances se réfère au même espace mémoire, plutôt qu'un espace indépendant).
Définir une méthode d'héritage, comme suit:
fonction extension (sous-classe, superclass) {var f = function () {}; F.prototype = superclass.prototype; sous-classe.prototype = new f (); sous-class.prototype.constructor = sous-classe; Subclass.Superclass = superclass.prototype; if (superclass.prototype.constructor == object.prototype.constructor) {superclass.prototype.constructor = superclass; }}Dans cette méthode, créez d'abord une nouvelle classe F, laissez son prototype être le prototype de la classe parent, et laissez le prototype de la sous-classe pointer vers une instance de la classe F, atteignant ainsi le but d'hériter de la classe parent. En même temps, puisque le prototype de la sous-classe est modifié, l'attribut de constructeur du prototype modifié est pointé vers la sous-classe, de sorte qu'il a une fonction de constructeur, et en même temps, la sous-classe peut monter un attribut de superclasse. La sous-classe peut appeler la classe parent par cette propriété, établissant ainsi la relation entre la sous-classe et la classe parent.
Définissez un auteur de sous-classe pour hériter de la personne de la classe parent, comme suit:
fonction auteur (nom, livres) {auteur.superclass.constructor.call (this, nom); this.book = livres; } extension (auteur, personne); Auteur.prototype.getBooks = function () {return this.book; }Ici, le constructeur de la classe parent est appelé via son attribut de superclasse dans le constructeur de la sous-classe. Dans le même temps, la méthode d'appel est utilisée pour convertir ce pointeur de l'appel de la méthode, de sorte que l'auteur de sous-classe possède également (hérite) les propriétés de la classe parent, et que la sous-classe a également son propre livre d'attribut. Par conséquent, les livres de paramètres sont attribués au livre d'attribut dans le constructeur pour atteindre l'objectif de la construction. Utilisez la fonction EXTENDRE pour hériter des propriétés et des méthodes du prototype de personne de classe parent (en fait, seules les méthodes sont héritées, car nous venons de monter les méthodes au prototype auparavant, et les propriétés sont définies dans le constructeur). Dans le même temps, l'auteur a sa propre méthode GetBooks, le montant sur le prototype correspondant, atteignant le but de se développer davantage sur la base de l'héritage.
Cette méthode d'héritage est évidemment un héritage de type similaire à la langue traditionnelle orientée objet. L'avantage est qu'il est facile pour les programmeurs habitués au concept traditionnel orienté objet. L'inconvénient est que le processus est relativement lourd et que la consommation de mémoire est légèrement plus grande, car la sous-classe a également son propre constructeur et prototype, et les attributs de la sous-classe et la classe parent sont complètement isolés. Même si les deux sont de la même valeur, ils ne peuvent pas partager la même mémoire.
Méthode 2: Héritage prototype
Définissez d'abord une classe parent. Ici, nous n'imiterons pas délibérément l'utilisation de constructeurs pour le définir, mais définirons directement un objet sous forme de littéraux d'objet, qui est la classe parentale
var personne = {name: 'par défaut name', getName: function () {return this.name; }};Comme la première méthode, l'objet a un nom de propriété et une méthode getName.
Définissez ensuite une méthode de clonage pour implémenter l'héritage de la sous-classe vers la classe parent, comme suit:
fonction clone (obj) {fonction f () {} f.prototype = obj; retourner nouveau f (); }La méthode de clonage crée un nouvel objet, pointe le prototype de l'objet à la classe parent, c'est-à-dire le paramètre OBJ, et renvoie l'objet en même temps.
Enfin, la sous-classe hérite de la classe parent à travers la fonction de clonage, comme suit:
var auteur = clone (personne); Auteur.book = ['javascript']; Auteur.showbook = function () {return this.book; }Ici, une sous-classe est définie, et la personne de la classe parent est héritée de la fonction de clone, et un livre d'attribut est élargi et un showbook de méthode est élargi. Ici, la sous-classe a également le nom d'attribut, mais c'est la même chose que la valeur de nom de la classe parent, il n'est donc pas remplacé. Si c'est différent, vous pouvez l'utiliser.
Auteur.name = 'nouveau nom'; Écrasez cette propriété pour obtenir une nouvelle valeur d'attribut de nom de la sous-classe.
Ce prototype d'hérédité est plus simple et plus naturel que l'héritage de classe. En même temps, si les attributs de la sous-classe et les valeurs d'attribut de classe parent sont les mêmes et peuvent être modifiés, ils partagent en fait le même espace mémoire. Par exemple, l'attribut de nom ci-dessus est difficile à comprendre pour les programmeurs qui sont habitués aux programmes traditionnels axés sur les objets. Si les deux doivent être choisis, cette méthode est sans aucun doute meilleure.
Étant donné que JavaScript adopte une approche basée sur un prototype pour mettre en œuvre l'héritage, et que le prototype de chaque objet ne peut que pointer vers une instance d'une classe spécifique (pas à plusieurs instances), comment mettre en œuvre un héritage multiple (c'est-à-dire que une classe a des méthodes et des attributs de plusieurs classes en même temps, et ne définit pas ces méthodes et attributs eux-mêmes en interne)?
Dans le modèle de conception JavaScript, une classe de mixin est donnée:
Tout d'abord, définissez une classe de dopage pour enregistrer certaines méthodes et attributs couramment utilisés. Ces méthodes et attributs peuvent être ajoutés à toute autre classe par extension, de sorte que la classe ajoutée a certaines méthodes et attributs de la classe. Si plusieurs classes de dopage sont définies et ajoutées à une classe en même temps, la classe implémente indirectement "héritage multiple". Sur la base de cette idée, la mise en œuvre est la suivante:
Définition de la classe dominante des éléments:
var mixin = function () {}; Mixin.prototype = {serialize: function () {var output = []; for (key in this) {output.push (key + ":" + this [key]); } return output.join (','); }}La classe de dopage a une méthode sérialisée utilisée pour se traverser, sortir ses propres attributs et attribuer des valeurs, et les renvoyer sous forme de chaînes, séparées par des virgules.
Définissez une méthode d'extension pour faire une classe a des attributs ou des méthodes d'une classe multi-groupe après l'expansion, comme suit:
function augment (receiveclass, don downclass) {if (arguments [2]) {for (var i = 2, len = arguments.length; i <len; i ++) {receivingclass.prototype [arguments [i]] = donnclass.prototype [arguments [i]]; }} else {for (Methodname dans don dingclass.prototype) {if (! receiveclass.prototype [méthodyname]) {receivingClass.prototype [méthodyname] = donnantClass.prototype [MethodnAm]; }}}}Cette méthode a deux paramètres par défaut. Le premier paramètre accepte la classe élargie, le deuxième paramètre est la classe dopée (utilisée pour développer d'autres classes), et il peut y avoir d'autres paramètres. S'il est supérieur à deux paramètres, les paramètres suivants sont des noms de méthode ou d'attribut, qui sont utilisés pour indiquer que la classe élargie souhaite hériter des attributs ou des méthodes spécifiés de la classe dopée. Sinon, tous les attributs et méthodes de la classe dopée sont hérités par défaut. Dans cette fonction, la première branche IF est utilisée pour hériter des attributs et des méthodes spécifiés, et la branche ELSE est le cas où tous les attributs et méthodes sont hérités par défaut. L'essence de cette méthode consiste à étendre (ajouter) les propriétés et les méthodes sur le prototype de la classe de dopage des éléments au prototype de la classe élargie, de sorte qu'il a des propriétés et des méthodes de la classe de dopage des éléments.
Enfin, utilisez la méthode d'expansion pour obtenir un héritage multiple
augmentation (auteur, mixin); var auteur = nouvel auteur ('js', ['javascript design motifs']); alert (auteur.serialize ());Voici une classe d'auteur. Cette classe hérite de la classe parent de la personne et possède également des méthodes et des propriétés du mixin de classe métabolisé. Si vous le souhaitez, vous pouvez définir N classes métabolisées pour développer la classe. Il peut également hériter des propriétés et des méthodes d'autres classes métabolisées que vous définissez, de sorte que l'héritage multiple est réalisé. Enfin, le résultat de l'opération de la méthode de sérialisation de l'auteur est le suivant:
Vous constaterez que cette classe a à la fois les propriétés et les méthodes de la classe Personne, de la classe d'auteur et de la classe de mixin. Les propriétés et les méthodes de personne et de mélange sont toutes obtenues par "héritage". En fait, il réalise l'héritage multiple.