L'explication de l'héritage JavaScript a été convenue, mais elle a été retardée. Sans plus tarder, arrivez juste au point.
Puisque vous voulez comprendre l'héritage, cela prouve que vous avez déjà une certaine compréhension des objets JavaScript. Si vous ne comprenez rien, vous pouvez vous référer à l'explication de base de JS orienté objet, mode d'usine, mode constructeur, mode prototype, mode mixte, mode prototype dynamique ". Ensuite, parlons de l'héritage de JavaScript généralement via ces méthodes.
Chaîne prototype
La façon la plus simple d'implémenter l'héritage en JavaScript est d'utiliser une chaîne prototype et de pointer le prototype du type d'enfant sur une instance du type de parent, c'est-à-dire "sous-type.prototype = nouveau type de parent ();". La méthode d'implémentation est la suivante:
// Créer une fonction de constructeur SuperType () {this.name = ['wuyuchang', 'jack', 'tim']; this.property = true;} // ajouter la méthode supertype.prototype.getsuerperValue = function () {return this.property;} // Créer un sous-type de fonction de constructeur () {this.test = [h1 ',' h2 ',' h3 ',' h4 ']; this.subproperty = false;} // étapes clés pour implémenter l'héritage, le prototype du sous-type pointe vers une instance du sous-type de type parent.prototype = new SuperType (); // ajoute une méthode au type d'enfant ici. Il doit être une fois l'héritage implémenté, sinon le pointeur sera indiqué vers une instance du type de parent, et la méthode est vide. Sous-type.prototype.getSubValue = function () {return this.subproperty;} / * Ce qui suit est un exemple de code de test * / var instance1 = nouveau sous-type (); instance1.name.push ('wyc'); instance1.test.push ('h5'); alert (instance1.getSuerperValue ()); // trueAlert (instance1.getSubValue ()); // falSalert (instance1.name); // WUyuchang, Jack, Tim, Wycalert (instance1.test); // H1, H2, H3, H4, H5VAR Instance2 = nouveau sous-type (); alert (instance2.Name); // WUyuchang, Jack, Tim, Wycalert (instance2.test); // H1, H2, H3, H4Vous pouvez voir que le code ci-dessus est un héritage simple implémenté via la chaîne prototype, mais il y a encore des problèmes dans l'exemple de code de test. Je crois qu'après avoir lu mon article de blog "Explication de base de JS orienté objet, mode d'usine, mode constructeur, mode prototype, mode mixte, mode prototype dynamique", je dois savoir que le premier problème avec le code de chaîne prototype est que le prototype du sous-type est un exemple du type de parent, qui est l'attribution du prototy La valeur de type sera partagée par toutes les instances . Le instance1.name.push ('wyc'); du code ci-dessus peut prouver l'existence de ce problème. Le deuxième problème avec la chaîne prototype est que lors de la création d'une instance d'un sous-type, les paramètres ne peuvent pas être transmis au constructeur de supertype . Par conséquent, dans le développement réel, nous utilisons rarement les chaînes prototypes seules.
Constructeur d'emprunteurs
Pour résoudre deux problèmes dans la chaîne prototype, les développeurs ont commencé à utiliser une technique appelée constructeurs pour résoudre des problèmes dans la chaîne prototype. L'idée de mise en œuvre de cette technologie est également assez simple. Il vous suffit d'appeler le constructeur du type de parent dans le constructeur du sous-type. N'oubliez pas que les fonctions ne sont que des objets qui exécutent du code dans un environnement spécifique, afin que les constructeurs puissent être exécutés via la méthode applicable () ou call () . Le code est le suivant:
// Créer une fonction de constructeur SuperType (name) {this.name = name; this.color = ['rose', 'jaune']; this.property = true; this.testfun = function () {alert ('http://tools.vevb.com/'); }} // ajouter la méthode supertype.prototype.getsuerperValue = function () {return this.property;} // Créer un sous-type de fonction constructeur (name) {supertype.call (this, name); this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false;} // ajouter une méthode au sous-type ici. Assurez-vous d'implémenter l'héritage, sinon le pointeur sera indiqué une instance du type de parent, et la méthode est un sous-type vide.prototype.getsubValue = function () {return this.subproperty;} / * Ce qui suit est un exemple de code de test * / var instance1 = new sous-type (['wuyuchang', 'jack',,,, var instance1 = 'Nick']); instance1.name.push ('hello'); instance1.test.push ('h5'); instance1.color.push ('bleu'); instance1.testfun (); // http://tools.vevb.com/alert(instance1.name); // wuyuchang, jack, nick, bonjour // alert (instance1.getsuerpervalue ()); // alerte d'erreur (instance1.test); // H1, H2, H3, H4, H5 alerte (instance1.getSubValue ()); // false alert (instance1.color); // rose, jaune, bluevar instance2 = nouveau sous-type ('wyc'); instance2.TestFun (); // http://tools.vevb.com/alert(instance2.name); // wyc // alert (instance2.getsUerperValue ()); // alerte d'erreur (instance2.test); // H1, H2, H3, H4Alert (instance2.getSubValue ()); // falSalert (instance2.color); // rose, jauneVous pouvez voir que dans le code ci-dessus, le constructeur du sous-type de sous-type dans le code ci-dessus, l'héritage de l'attribut est réalisé en appelant le type de parent "SuperType.Call (this, nom);". Vous pouvez également transmettre des paramètres au type de parent lorsque le sous-type est créé, mais un nouveau problème arrive. Vous pouvez voir que j'ai défini une méthode dans le constructeur du type de parent: testfun, et une méthode dans le prototype du type parent: getSupervalue. Cependant, après avoir instancié le sous-type, il est toujours impossible d'appeler la méthode getSupervalue définie dans le prototype du type de parent , et ne peut appeler la méthode du constructeur dans le type de parent: testfun. Ceci est le même que d'utiliser uniquement le mode constructeur dans la création d'objets, de sorte que la fonction n'a pas de réutilisabilité. Compte tenu de ces problèmes, les techniques d'emprunt des constructeurs sont rarement utilisées seule.
Combinaison héritage (prototype chaîne + constructeur d'empruntes)
Comme son nom l'indique, l'héritage combiné est un modèle composé des avantages de combiner l'utilisation de chaînes prototypes et de constructeurs d'emprunt. L'implémentation est également très simple. Puisqu'il s'agit d'une combinaison, il combine bien sûr les avantages des deux parties, à savoir la méthode de l'héritage de la chaîne prototype, et le constructeur hérite des attributs . Le code spécifique est implémenté comme suit:
// Créer une fonction de constructeur SuperType (name) {this.name = name; this.color = ['rose', 'jaune']; this.property = true; this.testfun = function () {alert ('http://tools.vevb.com/'); }} // ajouter la méthode supertype.prototype.getsuerperValue = function () {return this.property;} // Créer un sous-type de fonction constructeur (name) {supertype.call (this, name); this.test = ['h1', 'h2', 'h3', 'h4']; this.subproperty = false;} sous-type.prototype = new SuperType (); // Ajoutez une méthode au sous-type ici. Il doit être après l'implémentation de l'héritage, sinon le pointeur sera indiqué une instance du type de parent, et la méthode est un sous-type vide.prototype.getSubValue = function () {return this.subproperty;} / * Ce qui suit est un exemple de code de test * / var instance1 = nouveau sous-type (['wuyuchang', 'jack',,, var instance1 = 'Nick']); instance1.name.push ('hello'); instance1.test.push ('h5'); instance1.color.push ('bleu'); instance1.testfun (); // http://tools.vevb.com/alert(instance1.name); // WUyuchang, Jack, Nick, HelloAlert (instance1.getsUerperValue ()); // trueAlert (instance1.test); // H1, H2, H3, H4, H5 alerte (instance1.getSubValue ()); // false alert (instance1.color); // rose, jaune, bluevar instance2 = nouveau sous-type ('wyc'); instance2.TestFun (); // http://tools.vevb.com/alert(instance2.name); // wyc alert (instance2.getsUerperValue ()); // trueAlert (instance2.test); // H1, H2, H3, H4Alert (instance2.getSubValue ()); // falSalert (instance2.color); // rose, jauneLe code ci-dessus hérite des propriétés du type de parent via SuperType.Call (this, nom); et hérite des méthodes du type de parent via le sous-type.prototype = new SuperType ();. Le code ci-dessus résout facilement les problèmes rencontrés par les chaînes prototypes et les constructeurs d'emprunt, et est devenu la méthode d'hérédité des instances la plus couramment utilisée en JavaScript. Cependant, le mode mixte n'est pas sans ses lacunes. On peut voir que dans le code ci-dessus, les attributs du type de parent ont en fait été hérités lorsqu'ils héritent de la méthode. Cependant, le type de référence est partagé pour le moment. Par conséquent, le constructeur du type de parent est appelé dans le constructeur du type d'enfant après le sous-type, héritant ainsi des attributs du type parent pour écraser les attributs hérités du prototype. Il n'est évidemment pas nécessaire d'appeler le constructeur deux fois, mais y a-t-il un moyen de le résoudre? Lors de la résolution de ce problème, regardez d'abord les deux modes suivants.
Héritage prototype
La méthode de mise en œuvre de l'héritage prototype est différente de celle de l'héritage ordinaire. L'héritage prototype n'utilise pas de constructeur au sens strict, mais utilise plutôt le prototype pour créer de nouveaux objets basés sur des objets existants, et il n'est pas nécessaire de créer des types personnalisés en conséquence. Le code spécifique est le suivant:
Fonction Object (o) {fonction f () {} f.prototype = o; retourner nouveau f ();}Exemple de code:
/ * Prototype Héritage * / Fonction Object (O) {Fonction f () {} f.prototype = o; return new f ();} var person = {name: 'wuyuchang', amis: ['wyc', 'nicholas', 'tim']} var an autre chose = objet (personne); autre personne.name = 'Greg'; AnotherSerson.friends.push ('bob'); var ano un autrePerson2 = objet (personne); AnotherSerson2.Name = 'Jack'; AnotherPerson2.friends.push ('rose'); alert (Person.friends); // Wyc, Nicholas, Tim, Bob, RoseHéritage parasite
/ * Hérédité parasite * / fonction Createanother (original) {var clone = objet (original); clone.sayhi = function () {alert ('hi'); } Clone de retour;}Exemple d'utilisation:
/ * Prototype Héritage * / Fonction Object (O) {Fonction f () {} f.prototype = o; return new f ();} / * héritage parasite * / fonction createArother (original) {var clone = objet (original); clone.sayhi = function () {alert ('hi'); } return clone;} var person = {name: 'wuyuchang', amis: ['wyc', 'nicholas', 'rose']} var an autre personne = createanother (personne); autre personne.sayhi ();Héritage de combinaison parasite
J'ai mentionné plus tôt les inconvénients de la mise en œuvre du modèle combiné de l'héritage en JavaScript. Maintenant, résolvons ses lacunes. L'idée de mise en œuvre est de hériter des attributs pour les constructeurs, et la méthode d'héritage de forme mixte de la chaîne prototype n'a pas besoin d'instancier le constructeur du type de parent lorsqu'il hérite de la méthode. Le code est le suivant:
Fonction Object (o) {fonction f () {} f.prototype = o; return new f ();} / * Parasitic Combination Héritage * / Fonction HéritPrototype (sous-type, supertype) {var prototype = objet (supertype.prototype); prototype.constructor = sous-type; sous-type.prototype = prototype;}Lorsque vous l'utilisez, il vous suffit de remplacer la ligne de code "sous-type.prototype = new SuperType ();" En mode combinaison avec HéritProtype (sous-type, supertype);. L'efficacité de l'héritage combinatoire parasite se reflète en ce qu'elle n'appelle le constructeur de type parent qu'une seule fois, en évitant la création de propriétés inutiles ou redondantes. Dans le même temps, la chaîne prototype peut rester inchangée, de sorte que l'instance OFF et iSprototypeOf () peuvent également être utilisées normalement. Il s'agit également actuellement de la méthode d'héritage la plus idéale, et elle se transforme actuellement en ce modèle. (Yui utilise également ce mode.)
Ce billet de blog fait référence à "JavaScript Advanced Programming 3rd Edition". Le code est réécrit et plus spécifique, et a commenté pour faciliter la compréhension de tout le monde. Si vous avez des informations uniques sur l'héritage de JS, ne soyez pas avare. Répondez à vos opinions pour votre référence!