La chaîne prototype est un peu déroutante à comprendre, et il y a beaucoup d'informations en ligne. Chaque fois que je ne peux pas dormir la nuit, j'aime toujours trouver des prototypes de chaînes et de fermetures d'articles en ligne à lire, ce qui est très efficace.
Ne vous inquiétez pas pour ces nombreux termes, cela ne vous aidera vraiment pas, sauf pour que votre cerveau se tordit. Regardez simplement la chaîne du prototype simplement et à peu près, et pensez à des choses qui n'ont rien à voir avec le code, comme les humains, les démons et les hommes transexuels.
1) Les gens sont nés par des êtres humains et les monstres sont nés par des démons. Les humains et les démons sont tous deux des cas d'objets, tandis que les humains et les démons sont des prototypes. Un prototype est également un objet, appelé un objet prototype.
2) La mère d'une personne et son père peuvent donner naissance à un tas de bébés, et une mère démoniaque et son père peuvent donner naissance à un tas de bébés. La femme d'un homme et un homme peuvent donner naissance à un tas de bébés. Un homme est un constructeur, communément appelé homme.
3) Les gens peuvent enregistrer des informations sur le sexe, afin que les gens puissent trouver des informations sur le sexe par le sexe, c'est-à-dire qu'ils peuvent trouver le constructeur via des objets prototypes.
4) Les gens peuvent donner naissance à de nombreux bébés dans leur mère, mais ces bébés n'ont qu'une seule mère, qui est le caractère unique du prototype.
5) Les gens sont également nés par des gens, ils trouvent des gens par le biais de gens, puis trouvent des gens par le biais de gens ... Cette relation est appelée chaîne prototype.
6) La chaîne prototype n'est pas infinie. Lorsque vous continuez à regarder les gens, vous constaterez que les gens sont putains ... ne sont pas des humains, c'est-à-dire que la chaîne prototype pointe enfin de Null.
7) Les gens nés avec une maman ressembleront à des gens, et les monstres nés avec une maman seront laids. C'est ce qu'on appelle l'héritage.
8) Vous avez hérité de la couleur de la peau de votre mère, votre mère a hérité de la couleur de la peau de votre mère, de votre mère ..., c'est l'héritage de la chaîne prototype.
9) Si vous n'avez pas de maison, votre maison fait référence à la maison de votre mère; Si votre mère n'a pas de maison, votre maison fait référence à la maison de votre mère ... c'est la recherche à la hausse de la chaîne prototype.
10) Vous hériterez de l'apparence de votre mère, mais vous pouvez également teindre vos cheveux, shampooing, coupe et souffle, c'est-à-dire que les attributs de l'objet peuvent être personnalisés et l'emporter sur les attributs hérités.
11) Bien que vous ayez lavé, coupé, soufflé et teint les cheveux jaunes, vous ne pouvez pas changer l'apparence de votre mère. Le frère cadet et la sœur nés de votre mère n'ont rien à voir avec votre lavage de cheveux jaunes, votre coupe et vos cheveux jaunes soufflés, c'est-à-dire que l'instance d'objet ne peut pas changer les propriétés du prototype.
12) Mais si votre maison est brûlée par vous, cela signifie que votre mère et vos frères sont brûlés, et c'est le partage d'attributs prototypes.
13) Le surnom de votre mère est Azhen, et la tante de son voisin vous appelle Azhener, mais après que les cheveux de votre mère sont passés de Piaorou au roi du lion d'or, la tante d'à côté a changé ses mots et vous a appelé le prince du lion d'or. C'est ce qu'on appelle la nature dynamique du prototype.
14) Votre mère aime la beauté et est allée en Corée pour une chirurgie plastique. Elle ne pouvait même pas reconnaître sa mère. Même si les cheveux de votre mère ont changé pour la douceur, le voisin d'à côté vous a toujours appelé le Golden Lion Prince. Parce que personne n'a reconnu votre mère, votre mère est retournée à l'usine après une chirurgie plastique. Il s'agit de la réécriture globale du prototype.
Bon sang! Tu as assez! Ne bb pas! Montrez-moi le code!
fonction personne (name) {this.name = name; } fonction mère () {} mère.prototype = {// Prototype de la mère Age: 18, maison: ['beijing', 'shanghai']}; personne.prototype = new Mother (); // Le prototype de la personne est mère // utilise l'outil de débogage chromé pour afficher le prototype, fournissant l'interface __proto__ pour afficher le prototype var p1 = new personne ('jack'); // p1: «Jack»; __proto __: 18, ['beijing', 'shanghai'] var p2 = nouvelle personne ('mark'); // p2: 'mark'; __proto __: 18, ['beijing', 'shanghai'] p1.age = 20; / * L'instance ne peut pas modifier l'attribut de valeur de base du prototype, tout comme vous lavez, coupez, soufflez et teint, les cheveux jaunes n'ont rien à voir avec votre mère * Le fonctionnement ordinaire d'ajouter un attribut d'âge sous l'instance P1 n'a rien à voir avec le prototype. Identique à var o {}; O.age = 20. * P1: Il y a un âge d'attribut supplémentaire ci-dessous, et __proto__ est le même que Mother.prototype, âge = 18. * p2: seul nom d'attribut, __proto__ est le même que mère.prototype * / p1.home [0] = 'Shenzhen'; / * Le partage des attributs de type de référence dans le prototype est comme si vous brûliez votre maison, il brûle la maison de toute votre famille * C'est un peu un laissez-passer, allons-y soigneusement ci-dessous? * P1: «Jack», 20; __proto __: 18, [«Shenzhen», «Shanghai»] * P2: «Mark»; __proto __: 18, ['Shenzhen', 'Shanghai'] * / P1.Home = ['Hangzhou', 'Guangzhou']; / * En fait, la même opération que p1.age = 20. Changer dans cette compréhension: var o {}; O.house = [«Big», «House»] * P1: «Jack», 20, [«Hangzhou», «Guangzhou»]; __proto __: 18, [«Shenzhen», «Shanghai»] * P2: «Mark»; __proto __: 18, ['Shenzhen', 'Shanghai'] * / Delete p1.age; / * Après la suppression des attributs personnalisés, la valeur prototype initialement écrasée sera réexpectée. Il s'agit du mécanisme de recherche ascendant, il y a donc la dynamique suivante * P1: «Jack», [«Hangzhou», «Guangzhou»]; __proto __: 18, [«Shenzhen», «Shanghai»] * P2: «Mark»; __proto __: 18, ['Shenzhen', 'Shanghai'] * / personne.prototype.lastName = 'Jin'; / * Réécrivez le prototype et réagissez dynamiquement à l'instance. Tout comme votre mère est devenue une personne à la mode, les voisins disent que vous êtes le fils d'une femme tendance lorsqu'il le mentionne * Notez que nous réécrivons le prototype de personne ici, qui est d'ajouter un attribut de LastName à Mère, ce qui équivaut à mère.lastname = 'Jin' * Il ne s'agit pas de changer Mother.prototype. Si vous modifiez différents niveaux, les effets seront souvent très différents. * P1: «Jack», [«Hangzhou», «Guangzhou»]; __proto __: 'Jin'; __ Proto __: 18, ['Shenzhen', 'Shanghai'] * P2: 'Mark'; __proto __: 'Jin'; __ Proto __: 18, ['Shenzhen', 'Shanghai'] * / Person.prototype = {Age: 28, Adresse: {Country: 'USA', City: 'Washington'}}; var p3 = New Person ('Obama'); / * Réécrivez le prototype! À cette époque, le prototype de la personne était complètement devenu un nouvel objet, ce qui signifie que cette personne avait changé sa mère. * Pour le comprendre comme ceci: var a = 10; b = a; a = 20; c = a. Donc, B reste inchangé et devient C, donc P3 change et n'a rien à voir avec la mère. * P1: «Jack», [«Hangzhou», «Guangzhou»]; __proto __: 'Jin'; __ Proto __: 18, ['Shenzhen', 'Shanghai'] * P2: 'Mark'; __proto __: 'Jin'; __ Proto __: 18, ['Shenzhen', 'Shanghai'] * P3: 'Obama'; __ Proto__: 28 {country: 'usa', ville: 'Washington'} * / mère.prototype.no = 9527; / * réécriture le prototype du prototype et réagit dynamiquement et réagit dynamiquement. Tout comme votre mère est devenue une nouvelle tendance, les voisins disent que vous êtes vraiment une grand-mère à la mode * que nous réécrivons la mère.Protype ici, P1P2 changera, mais le P3 ci-dessus n'a rien à voir avec la mère, et cela ne l'affectera pas. * P1: «Jack», [«Hangzhou», «Guangzhou»]; __proto __: 'Jin'; __ Proto __: 18, ['Shenzhen', 'Shanghai'], 9527 * P2: 'Mark'; __proto __: 'Jin'; __ Proto __: 18, ['Shenzhen', 'Shanghai'], 9527 * P3: 'Obama'; __proto__: 28 {country: 'USA', ville: 'Washington'} * / Mother.prototype = {Car: 2, Hobby: ['Run', 'Walk']}; var p4 = nouvelle personne ('Tony'); / * réécrire le prototype du prototype! À l'heure actuelle, le prototype de la mère est complètement devenu un nouvel objet! * Étant donné que la personne et la mère ont été déconnectées d'en haut, le changement de mère n'affectera plus la personne. * P4: 'Tony'; __ Proto__: 28 {Country: 'USA', City: 'Washington'} * / Person.prototype = new Mother (); // lier var à nouveau p5 = new personne ('Luffy'); // Si vous devez appliquer ces modifications pour le moment, vous devez refaire le prototype de la personne à Mère // P5: 'Luffy'; __ Proto__: 2, ['Run', 'Walk'] P1 .__ Proto __.__ Proto __.__ Proto __.__ Proto__ // Mère .__ Proto __.__ Proto __.__ Proto__ // NULL, pensez-vous que le point final de la chaîne prototype n'est pas nul?Vous pouvez essentiellement comprendre après l'avoir lu?
Parlons maintenant de la différence entre p1.age = 20, p1.home = ['hangzhou', 'guangzhou'] et p1.home [0] = 'Shenzhen'. p1.home [0] = 'Shenzhen'; Pour résumer, il s'agit d'une forme telle que p1.object.method, p1.object.property.
p1.age = 20; p1.home = ['hangzhou', 'guangzhou']; Ces deux phrases sont faciles à comprendre. Oubliez d'abord le prototype et réfléchissez à la façon dont nous ajoutons des attributs à un objet ordinaire:
var obj = nouveau objet (); obj.name = 'xxx'; obj.num = [100, 200];
Comprenez-vous de cette façon? C'est la même chose.
Alors pourquoi p1.home [0] = 'Shenzhen' ne crée-t-il pas une propriété de tableau domestique sous P1, puis définit sa première position sur 'Shenzhen'? Oublions d'abord cela, réfléchissez à l'objet OBJ ci-dessus. S'il est écrit comme ceci: var obj.name = 'xxx', obj.num = [100, 200], pouvez-vous obtenir le résultat que vous souhaitez? De toute évidence, vous n'obtiendrez rien sauf pour une erreur. Parce que OBJ n'a pas encore été défini, comment pouvez-vous y ajouter quelque chose? De même, la maison de P1.Home [0] n'est pas définie sous P1, il est donc impossible de définir directement la maison [0]. Si vous souhaitez créer un tableau domestique sous P1, bien sûr, il est écrit comme ceci:
p1.home = []; p1.home [0] = 'Shenzhen';
N'est-ce pas la méthode la plus couramment utilisée?
La raison pour laquelle p1.home [0] = 'Shenzhen' ne signale pas directement une erreur est qu'il existe un mécanisme de recherche dans la chaîne prototype. Lorsque nous entrons P1.Object, le mécanisme de recherche de la chaîne prototype consiste d'abord à rechercher la valeur correspondante dans l'instance. S'il ne peut être trouvé, il sera fouillé dans le prototype. S'il ne peut être trouvé, il recherchera au niveau précédent de la chaîne prototype ... il atteindra la fin de la chaîne prototype, c'est-à-dire si elle n'a pas encore été trouvée, elle renverra un indéfini. Lorsque nous entrons P1.Home [0], le même mécanisme de recherche est également vrai. Recherchez d'abord P1 pour voir s'il y a des attributs et des méthodes nommés à la maison, puis recherchez vers le haut étape par étape. Enfin, nous l'avons trouvé dans le prototype de la mère, donc le modifier équivaut à modifier le prototype de la mère.
En résumé: p1.home [0] = 'Shenzhen' équivaut à mère.prototype.home [0] = 'Shenzhen'.
D'après l'analyse ci-dessus, nous pouvons voir que le principal problème de l'héritage de la chaîne prototype réside dans le partage des attributs. Plusieurs fois, nous ne voulons partager les méthodes mais pas les attributs. Idéalement, chaque instance doit avoir des attributs indépendants. Par conséquent, il existe deux façons d'améliorer l'héritage du prototype:
1) Hémit de combinaison
fonction mère (âge) {this.age = age; this.hobby = ['running', 'football']} mère.prototype.showage = function () {console.log (this.age); }; fonction de fonction (nom, âge) {mère.Call (this, âge); // deuxième exécution this.name = name; } Personne.prototype = new Mother (); // première exécution personne.prototype.constructor = personne; personne.prototype.showname = function () {console.log (this.name);} var p1 = new personne ('jack', 20); p1.hobby.push («basket-ball»); // p1: «Jack»; __proto __: 20, [«Running», «Football»] var P2 = New Person («Mark», 18); // p2: 'mark'; __Proto __: 18, [«Running», «Football»]Le résultat est violet:
Lorsque la première exécution est effectuée ici, vous obtenez personne.prototype.age = Undefined, personne.prototype.hobby = ['Running', 'Football']. La deuxième exécution est que var p1 = new personne ('jack', 20) et vous obtenez p1.age = 20, p1.hobby = ['Running', 'Football']. Après avoir poussé, il devient p1.hobby = ['Running', 'Football', 'Basketball']. En fait, il est relativement simple de comprendre les changements de cela. Vous pouvez obtenir ce résultat en remplaçant simplement cela. Si vous sentez que c'est un peu déroutant à comprendre, essayez de jeter les concepts dans votre esprit et d'exécuter le code de haut en bas en tant que navigateur. Va-t-il sortir?
En exécutant le constructeur prototype mère () pour la deuxième fois, nous avons copié une copie des propriétés du prototype dans l'instance de l'objet, afin que nous puissions séparer et séparer les propriétés prototypes. Si vous faites attention, vous constaterez que la première fois que nous avons appelé Mother (), il semble qu'il n'y a pas de usage. Comment ne pouvons-nous pas l'appeler? Oui, il y a l'héritage de combinaison parasite suivante.
2) Héritage de combinaison parasite
Fonction Object (o) {fonction f () {} f.prototype = o; return new f ();} function hheRitProtype (personne, mère) {var prototype = objet (mère.prototype); prototype.constructor = personne; Personne.prototype = prototype; } fonction mère (âge) {this.age = Âge; this.hobby = ['running', 'football']} mère.prototype.showage = function () {console.log (this.age); }; fonction de fonction (nom, âge) {mère.Call (this, âge); this.name = name; } Héritpototype (personne, mère); Personne.prototype.showname = function () {console.log (this.name);} var p1 = new Person ('Jack', 20); p1.hobby.push («basket-ball»); // p1: «jack»; __proto __: 20, [«Running», «Football»] var P2 = New Person («Mark», 18); // p2: 'mark'; __Proto __: 18, [«Running», «Football»]Le résultat est violet:
Il n'y a plus d'âge et d'attributs de passe-temps dans le prototype, il n'y a que deux méthodes, qui sont exactement le résultat que nous voulons!
Le point clé est dans l'objet (o), où un objet temporaire est emprunté ici pour éviter intelligemment appeler New Mother (), puis renvoyer une nouvelle instance d'objet avec le prototype O, terminant ainsi le réglage de la chaîne prototype. C'est très déroutant, non? C'est parce que nous ne pouvons pas définir directement personne.prototype = mère.prototype.
résumé
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Cela dit, il n'y a en fait qu'un seul noyau: le partage d'attribut et le contrôle indépendant. Lorsque votre instance d'objet a besoin d'attributs indépendants, l'essence de toutes les pratiques est de créer des attributs dans l'instance d'objet. Si vous ne pensez pas trop, vous pouvez définir directement les attributs indépendants dont vous avez besoin en personne pour écraser les propriétés du prototype. En bref, lorsque vous utilisez l'héritage du prototype, vous devez prêter une attention particulière aux attributs du prototype, car ce sont toutes des existences qui affectent tout le corps.
Vous trouverez ci-dessous une liste simple de diverses méthodes pour créer des objets dans JS. La méthode la plus couramment utilisée est maintenant le mode de combinaison. Les étudiants familiers peuvent sauter à la fin de l'article et l'aimer.
1) Mode d'origine
// 1. Mode original, objet Mode littéral var personne = {nom: 'jack', Âge: 18, SayName: function () {alert (this.name); }}; // 1. Mode d'origine, mode constructeur d'objets var personne = new object (); personne.name = 'jack'; Person.age = 18; personne.sayName = function () {alert (this.name);};De toute évidence, lorsque nous voulons créer des lots de Person1, Person2 ..., nous devons taper beaucoup de code à chaque fois, et même les copypasters seniors ne peuvent pas le supporter! Ensuite, il existe un modèle d'usine de production de masse.
2) Modèle d'usine
// 2. Mode d'usine, définissez une fonction pour créer une fonction d'objet CreateSerson (nom, âge) {var temp = new Object (); Person.name = name; Person.age = age; Person.sayName = function () {alert (this.name);}; retour tempor; }Le mode d'usine est la production de masse et vous pouvez entrer dans le mode d'homme avec un appel simple (papapa ...). Vous pouvez créer un tas de bébés en spécifiant votre nom et votre âge et libérer vos mains. Cependant, comme il est opéré dans une usine, vous ne pouvez pas identifier le type d'objet, qu'il s'agisse d'un humain ou d'un chien (instance de test est un objet). De plus, chaque fois que vous créez un humain, vous devez créer un objet temporaire indépendant, le code est gonflé et le papillon est élégant.
3) constructeur
// 3. Mode constructeur, définissez une fonction constructeur pour la fonction de fonction d'objet (nom, âge) {this.name = name; this.age = age; this.sayName = function () {alert (this.name);}; } var p1 = new personne ('jack', 18); // Créer une personne d'objet P1 ('Jack', 18); // Des méthodes d'attribut sont données à l'objet Window, window.name = 'jack', window.sayName () sortira la priseLe constructeur est similaire aux constructeurs de classes en C ++ et Java, et est facile à comprendre. De plus, la personne peut être utilisée comme reconnaissance de type (le test d'instance est personne et objet). Cependant, toutes les instances sont toujours indépendantes et les méthodes de différentes instances sont en fait des fonctions différentes. J'ai oublié la fonction de mot ici, traitez simplement SayName comme un objet et comprenez-le. C'est-à-dire que Sayname de Zhang San et le SayName de Li Si ont des existences différentes, mais évidemment ce que nous attendons, c'est de partager un SayName pour enregistrer la mémoire.
4) Mode prototype
// 4. Mode Prototype, Définissez directement l'attribut Prototype Person () {} personne.prototype.name = 'jack'; personne.prototype.age = 18; personne.prototype.sayName = function () {alert (this.name); }; // 4. Prototype, méthode de définition littérale Person () {} personne.prototype = {nom: 'jack', Âge: 18, SayName: function () {alert (this.name); }}; var p1 = new personne (); // name = 'jack'var p2 = new personne (); // name = 'jack'Ce qui doit être noté ici, c'est le partage d'attributs et de méthodes prototypes, c'est-à-dire que tous les cas se réfèrent uniquement aux méthodes d'attribut du prototype, et les modifications générées en n'importe quel endroit entraîneront des changements dans d'autres cas.
5) Mode mixte (construction + prototype)
// 5. Mode de combinaison de construction de prototypes, fonction de fonction (nom, âge) {this.name = name; this.age = age;} personne.prototype = {hobby: ['running', 'football']; sayName: function () {alert (this.name); }, sayage: function () {alert (this.age); }}; var p1 = new personne ('jack', 20); // P1: «Jack», 20; __proto__: ['Running', 'Football'], SayName, Sayagevar P2 = New Person ('Mark', 18); // P1: 'Mark', 18; __ Proto__: ['Running', 'Football'], Sayname, SayageL'approche consiste à mettre les méthodes de propriété qui doivent être indépendantes dans le constructeur, et les pièces qui peuvent être partagées sont placées dans le prototype. Cela peut maximiser les économies de mémoire tout en conservant l'indépendance des instances d'objet.