


Analyse d'une question d'entretien sur une chaîne de prototypes javascript (détails)
Le contenu de cet article est une analyse (détaillée) d'une question d'entretien sur la chaîne de prototypes JavaScript. Il a une certaine valeur de référence. Les amis dans le besoin peuvent s'y référer.
Devant les bases, toutes les compétences sont vaines.
La question est comme ça
Elle nécessite d'écrire la sortie de la console.
function Parent() { this.a = 1; this.b = [1, 2, this.a]; this.c = { demo: 5 }; this.show = function () { console.log(this.a , this.b , this.c.demo ); } } function Child() { this.a = 2; this.change = function () { this.b.push(this.a); this.a = this.b.length; this.c.demo = this.a++; } } Child.prototype = new Parent(); var parent = new Parent(); var child1 = new Child(); var child2 = new Child(); child1.a = 11; child2.a = 12; parent.show(); child1.show(); child2.show(); child1.change(); child2.change(); parent.show(); child1.show(); child2.show();
Les points de connaissance impliqués dans la question
Cela pointe vers
Chaîne de prototypes
Héritage de classe
Primitive types et références Différences de types
Chaque point de connaissance peut être extrait pour une recherche spéciale distincte.
Détails des points de connaissances nécessaires pour résoudre le problème
1 Le constructeur a un attribut prototype, pointant vers l'objet prototype du constructeur, et le. l'instance partagera le même Un objet prototype ;
2. Lorsqu'une instance est générée, une nouvelle mémoire tas sera générée dans la mémoire. Les opérations générales sur l'instance n'affecteront pas les autres instances, car elles occupent des espaces différents. dans la mémoire du tas et ne s'affectent pas. ;
3 Chaque instance a un prototype implicite __proto__ qui pointe vers l'objet prototype du constructeur
4. Les situations sont les suivantes :
4.1 Lorsqu'elle est appelée en tant que méthode objet, elle pointe vers celui qui l'appelle (cette question implique principalement cet article)
4.2 Lorsqu'elle est appelée en tant que fonction, elle pointe vers la fenêtre de variable globale de niveau supérieur
4.3 En tant que constructeur Lorsqu'une fonction est appelée, c'est-à-dire lorsque l'opérateur new génère une instance, celle-ci dans le constructeur pointe vers l'instance
4.4 Dans le méthodes d'appel et d'application, la liaison de ce qui est spécifié est affichée comme le contexte spécifié
5. Méthode quantitative littérale (il existe également des informations qui traduisent le littéral en quantité directe. Je pense personnellement que cette dernière traduction est en fait plus intuitif et plus vivant). Lors de l'attribution d'objets et de tableaux (l'essence des tableaux est également des objets), ce sont toutes des références, c'est-à-dire que les ressources sont générées dans la mémoire tas. La mémoire de pile génère des variables, puis les variables pointent vers le tas. adresse de la ressource.
6. Les règles de recherche de la chaîne de prototypes suivent le principe du chemin le plus court, c'est-à-dire qu'il faut d'abord rechercher les attributs de l'instance, puis rechercher les attributs spécifiés le long de la chaîne de prototypes jusqu'à ce que Object.prototype et null soient présents. fin de la chaîne de prototypes. Si l'instance elle-même et si la propriété recherchée n'existe pas dans toute la chaîne de prototypes, undefined sera renvoyé
7 La différence détaillée entre les instructions d'affectation pour l'affectation de valeur primitive et le type de référence. mission
Commencez à analyser la question
1.parent.show()
Il n'y a fondamentalement rien à expliquer.
Vous pouvez obtenir la réponse en prenant directement la valeur1 [1,2,1] 5
;
2.child1.show()
Child
Le constructeur a initialement pointé le Child
de
Dans la question, l'objet prototype de la classe Child
pointait vers une instance de la classe Parent
. en programmation orientée objet JavaScript. 🎜>Une des méthodes d'héritage. Il convient de noter ici que pointe vers l'instance Child.prototype
de Parent
, pas vers la classe parent
Parent
Vous pouvez directement afficher la réponse sur la console pour obtenir <.>
11 [1,2,1] 5
Ce qui est déroutant ici, c'est pourquoi la dernière colonne du tableau pointée par this.b est
? >1
vient en premier Regardez à quoi ressemble child1 : 11
Lorsque la méthode child1.show() est exécutée, puisque child1, en tant qu'instance de Child, a l'attribut a, donc dans la méthode show() this.a pointera directement sur la valeur de cet attribut, qui est 11, au lieu de continuer le long de la chaîne de prototypes pour obtenir l'attribut a sur l'objet pointé par __proto__ cherche ensuite this.b, car child1 Il n'y a pas d'attribut b, donc l'attribut b sur le parent sera récupéré le long de la chaîne du prototype. Sa valeur est un tableau. Les deux premiers éléments sont des constantes, ce qui n'a rien à dire. Le dernier élément du tableau est une référence, et le pointeur ici ne l'est pas. Ce n'est pas un pointeur dynamique, car il a été exécuté une fois lors de l'étape new Parent() et il est déterminé qu'il pointe vers la ressource pointée par. parent.a, qui est la ressource pointée par l'attribut a dans child1.__proto__, c'est-à-dire la valeur 1.
Il est à noter que :
Du point de vue du code, l'enfant1.__proto__. b array est Les trois éléments pointent vers child1.__proto__.a, donc si nous modifions la valeur de child1.__proto__.a à ce moment, cela affectera-t-il le résultat de child1.show() :
-
La réponse est que cela n'a aucun impact. Pourquoi les attributs qui semblent pointer vers la même adresse ont-ils des valeurs différentes ? Parce que lorsque l'instance parent est générée, this.a pointe vers une valeur primitive 2, donc le troisième élément de this.b se voit en fait attribuer une valeur primitive, donc cela ressemble à première vue à une affectation de type référence, mais ce n'est pas le cas. . L'attribution de valeurs primitives ouvrira un nouvel espace de stockage, rendant les valeurs de this.a et this.b[2] égales, mais pointant vers des adresses différentes dans la mémoire du tas. Pour des explications plus détaillées, veuillez consulter les articles de blog recommandés dans [Lecture approfondie].
2. Comment faire en sorte que le troisième élément du tableau child1.__proto__.b produise également 11 ? Modifiez-le après l'instanciation
Une autre façon consiste à définir la méthode get/set pour l'attribut a Oui, chaque fois que la valeur de l'attribut a change, la valeur de b[2] est modifiée de manière synchrone. . Le code et les résultats d'exécution sont les suivants :
-
3.child2. show( )
Si vous comprenez l'explication ci-dessus, vous pouvez obtenir la réponse par la même méthode ici : 12 [1,2,1] 5
Ensuite, le code est exécuté : child1.change(); child2.change();
4.parent.show()
parent est une instance de la classe Parent et Child.prorotype pointe vers une autre instance de la classe Parent. Les deux sont deux ressources dans la mémoire tas et ne s'affectent pas, donc les opérations ci-dessus n'affectent pas le parent. instance, et les résultats de sortie restent inchangés : 1 [1,2,1] 5;
5.child1.show(),child2.show()
Quels changements se sont produits après que child1 ait exécuté la méthode change() ?
this.b. push(this.a)
En raison des caractéristiques de pointage dynamique de this, this.b pointera vers le tableau b sur Child.prototype, et this.a pointera vers l'attribut a de child1, donc Child.prototype. b devient Il devient [1,2,1,11];
this.a = this.b.length
Les points de this.a et this.b dans this sont les mêmes que La phrase précédente est cohérente, donc le résultat est que child1.a devient 4;
this.c.demo = this.a++
Puisque les propres attributs de child1 n'ont pas c est l'attribut, donc this.c ici pointera vers Child.prototype.c La valeur de this.a est 4, qui est un type primitif, donc. l'opération d'affectation attribuera directement la valeur à Child.prototype.c Le résultat de la démo est 4, et this.a augmente alors à 5(4 + 1 = 5). .
Ensuite, child2 exécute la méthode change(), et child2 et child1 sont tous deux des instances de la classe Child, donc leurs chaînes de prototypes pointent vers le même objet prototype Child.prototype, qui est la même instance parent, donc toutes les instructions dans child2.change()
qui affectent l'objet prototype affecteront le résultat final de child1
this.b.push(this.a)
En raison des caractéristiques de pointage dynamique de this, this.b pointera vers Pour le tableau b sur Child.prototype, this.a pointera vers l'attribut a de child2, donc Child.prototype.b devient
[1,2,1,11,12];
this.a = this.b.length
Les directions de this.a et this. b dans cette instruction sont cohérents avec la phrase précédente, donc le résultat est child2.a devient 5 ;
this.c.demo = this.a++
Puisque le propre attribut de child2 le fait n'a pas l'attribut c, this.c pointera ici vers Child.prototype.c, donc le résultat de l'exécution est Child. La valeur de .prototype.c.demo passe à la valeur 5 de child2.a, et child2.a finit par incrémenter à 6 (5 + 1 = 6).
Ensuite, exécutez la commande de sortie et le résultat final sera affiché :
child1.show():5 [1,2,1 ,11,12] 5
child2.show():6 [1,2,1,11 ,12] 5
Pensée étendue
Quand je résolvait le problème, j'ai fait une erreur dans this.c.demo = this.a++ Je pensais qu'une référence serait passée ici, mais en fait, une valeur a été passée Après analyse, nous comprenons cela parce que this.a pointe. à une valeur d'origine, cela équivaut à attribuer la valeur d'origine à l'attribut d'objet, donc la valeur de child.c.demo ne sera plus affectée par les modifications de child.a après l'affectation. Si child.a est un type référence, à quoi ressemblera le résultat ?
Nous apportons quelques modifications au code source et pointons child.a vers un objet (c'est-à-dire un type de référence) :
Ensuite, après l'avoir exécuté, nous constaterons que la valeur de Child.prototype.c suivra la valeur de child1.a change avec les changements, car la valeur de child1.a est un type de référence à ce moment-là, et le processus d'affectation fera que Child.prototype.c et child1.a pointent vers l'adresse de l'espace mémoire de la même ressource . Pour une explication plus détaillée des types originaux et des types de référence, vous pouvez vous référer au blog dans Extended Reading à la fin de cet article.
Récolte et réflexion
1. Les connaissances de base sont intrinsèquement des détails dispersés et doivent être apprises avec une attitude tenace.
2. Les connaissances de base sont les plus ennuyeuses, et c'est aussi ce qui creuse vraiment le fossé entre les gens. C'est aussi le seuil qu'il faut franchir si l'on veut entrer dans une grande usine. urgent. Nous sommes également des novices. Certaines personnes deviendront des architectes front-end après 3 à 5 ans. Certaines personnes utiliseront encore une infinité de nouveaux frameworks pour lier des événements à des boutons après 3 à 5 ans. Celui que vous voulez être dépend des efforts que vous déployez. à mettre dedans. , la plupart du temps, il n'y a rien de mal à cela. La fondation est très importante ! Très important ! Très important !
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!

Outils d'IA chauds

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool
Images de déshabillage gratuites

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Article chaud

Outils chauds

Bloc-notes++7.3.1
Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Des questions et des solutions fréquemment posées pour l'impression de billets thermiques frontaux pour le développement frontal, l'impression de billets est une exigence commune. Cependant, de nombreux développeurs mettent en œuvre ...

Il n'y a pas de salaire absolu pour les développeurs Python et JavaScript, selon les compétences et les besoins de l'industrie. 1. Python peut être davantage payé en science des données et en apprentissage automatique. 2. JavaScript a une grande demande dans le développement frontal et complet, et son salaire est également considérable. 3. Les facteurs d'influence comprennent l'expérience, la localisation géographique, la taille de l'entreprise et les compétences spécifiques.

JavaScript est la pierre angulaire du développement Web moderne, et ses principales fonctions incluent la programmation axée sur les événements, la génération de contenu dynamique et la programmation asynchrone. 1) La programmation axée sur les événements permet aux pages Web de changer dynamiquement en fonction des opérations utilisateur. 2) La génération de contenu dynamique permet d'ajuster le contenu de la page en fonction des conditions. 3) La programmation asynchrone garantit que l'interface utilisateur n'est pas bloquée. JavaScript est largement utilisé dans l'interaction Web, les applications à une page et le développement côté serveur, améliorant considérablement la flexibilité de l'expérience utilisateur et du développement multiplateforme.

Comment fusionner les éléments du tableau avec le même ID dans un seul objet en JavaScript? Lors du traitement des données, nous rencontrons souvent la nécessité d'avoir le même ID ...

La discussion sur la réalisation des effets de défilement de parallaxe et d'animation des éléments dans cet article explorera comment réaliser le site officiel de Shiseido (https://www.shiseido.co.jp/sb/wonderland/) ...

Apprendre JavaScript n'est pas difficile, mais c'est difficile. 1) Comprendre les concepts de base tels que les variables, les types de données, les fonctions, etc. 2) Master la programmation asynchrone et les implémenter via des boucles d'événements. 3) Utilisez les opérations DOM et promettez de gérer les demandes asynchrones. 4) Évitez les erreurs courantes et utilisez des techniques de débogage. 5) Optimiser les performances et suivre les meilleures pratiques.

Discussion approfondie des causes profondes de la différence de sortie Console.log. Cet article analysera les différences dans les résultats de sortie de la fonction Console.log dans un morceau de code et expliquera les raisons derrière. � ...

Explorez la mise en œuvre de la fonction de glisser et de réglage du panneau de type VScode dans le frontal. Dans le développement frontal, comment implémenter un VScode comme ...
