Préface
J'ai vu une question comme celle-ci sur segmentfault:
var f = function () {}; object.prototype.a = function () {}; Function.prototype.b = fonction () {}; var f = new f ();Q: F peut-il obtenir A et B? Quel est le principe?
À première vue, j'étais vraiment confus. Après une étude minutieuse, j'ai constaté que je ne comprenais toujours pas le prototype soigneusement, donc je l'ai résumé et rempli un trou ~
Fonction et objet
Avant de résoudre le problème, parlons du prototype, de la chaîne de prototypes et de la relation entre la fonction et l'objet, qui est également au centre de cet article.
prototype
Lors de la création d'une fonction, un objet prototype sera automatiquement créé pour celui-ci, qui peut être accessible via la propriété Prototype de la fonction.
Créez un objet d'instance du constructeur, qui contiendra un pointeur (propriété interne) à l'intérieur, pointant vers l'objet prototype du constructeur. ECMA-262 La 5e édition de ce pointeur est appelée [[prototype]]. Bien qu'il n'y ait pas de moyen standard d'accéder à [[Prototype]] dans les scripts, Firefox, Safari et Chrome prennent en charge une propriété __proto__ sur chaque objet pour accéder à l'objet prototype de leur constructeur.
Permettez-moi de dire quelque chose d'important à nouveau:
Le constructeur accède à l'objet Prototype via la propriété Prototype.
L'objet d'instance accède à l'objet Prototype via l'attribut interne [[prototype]], et le navigateur implémente l'attribut _proto_ pour l'objet d'instance pour accéder à l'objet Prototype.
var f = function () {}; var f = new f (); // en supposant que l'objet prototype de f est p, alors // f.prototype === p; // f .__ proto__ === p;Répétez à nouveau. . Le prototype fait référence à la relation entre le constructeur et l'objet prototype, et __proto__ fait référence à la relation entre l'objet d'instance et l'objet prototype.
Chaîne prototype
La classe A hérite B, B hérite C ... En fait, il y a un objet prototype avec un pointeur pointant vers B dans l'objet prototype de A, et un objet prototype avec un pointeur pointant vers C dans l'objet prototype ... Notez qu'il s'agit de la connexion entre les objets prototypes. Il n'y a pas de relation entre les trois constructeurs d'ABC, il est donc appelé "chaîne prototype" ~
En supposant que A est un objet d'instance de A, la chaîne prototype de A est représentée dans la ligne violette dans la figure ci-dessous, et la ligne orange relie le constructeur et son objet prototype.
Comme le montre la figure, la fin de la chaîne prototype est objet.prototype .__ proto__ c'est-à-dire null. Lorsque vous recherchez une propriété ou une méthode de A, recherchez d'abord si A lui-même a ou non. Sinon, recherchez le long de la chaîne prototype jusqu'à ce qu'elle soit trouvée ou finalement retournée à unde défini après null.
Fonction et objet
La relation entre la fonction et l'objet est un peu emmêlée:
L'objet est un constructeur. Puisqu'il s'agit d'une fonction, c'est l'objet d'instance de fonction; La fonction est un constructeur, mais la fonction.prototype est un objet. Puisqu'il s'agit d'un objet, c'est l'objet d'instance de l'objet.
Tous les objets sont des instances d'objet, et toutes les fonctions sont des instances de fonction.
L'objet est une instance de fonction et function.prototype est une instance d'objet.
La relation entre les deux est représentée dans la figure ci-dessous.
Comme on peut le voir, objet en tant que constructeur, il a l'attribut prototype pointant vers objet.prototype, et en tant qu'objet d'instance, il a l'objet .__ Proto__ pointant vers la fonction.prototype. La fonction est un constructeur, il a un attribut prototype pointant vers la fonction.prototype, et la fonction est une fonction, et c'est aussi une instance de fonction, donc il a une fonction .__ Proto__ pointant vers la fonction.prototype, donc la fonction .__ proto === function.prototype est vrai.
Il peut être vérifié sous la console chromée, comme indiqué sur la figure.
Analyse de la question d'origine
La meilleure façon de résoudre le problème de la chaîne prototype est de dessiner une image. Après l'analyse précédente, cette image ne doit pas être un problème, comme suit ~
La chaîne prototype de F est tracée par une ligne bleue, donc F peut accéder à A, mais B ne peut pas accéder.
Si vous ne tracez pas une image, à première vue, vous pouvez penser que F peut accéder à b. C'est peut-être comme moi que F.prototype pointe vers la fonction.prototype, mais en fait, F.prototype est un objet plutôt qu'une fonction, donc son objet prototype ne sera pas de fonction.prototype.
Par conséquent, vous devez dessiner une image chaque fois que le problème de la chaîne prototype est ~
Sujet prolongé
Dans la question ci-dessus, F ne peut accéder qu'à A, mais pas b. Mais f peut accéder à la fois a et b. Si vous modifiez la question à ce qui suit, quel est le résultat de fb ()? Pourquoi? Vous pouvez y penser ~
var f = function () {}; object.prototype.a = function () {}; Function.prototype.b = fonction () {console.log ('f .__ proto__')}; F.prototype.b = fonction () {console.log ('f.prototype');};Résumer
Après avoir lu ceci, avez-vous trouvé une caractéristique spéciale de la fonction?
Pour un objet général, il n'y a qu'un seul attribut __proto__ utilisé pour accéder à l'objet prototype de son constructeur, et pour une fonction, il est à la fois une fonction et un objet.
En tant que fonction, il est né avec un attribut prototype pointant vers son prototype de fonction d'objet Nom.prototype.
En tant qu'objet d'instance de fonction, il a l'attribut __proto__ pointant vers la fonction.prototype
Habituellement, ces deux propriétés pointent vers deux objets, mais les deux propriétés de la fonction pointent vers la même, les deux pointent de la fonction. ProTotype.
Pour la fonction a (), les méthodes de A.Prototype sont pour l'appel à son objet d'instance et ne seront pas utilisées par elle-même; Lorsque A est exécuté en instance, les méthodes dans un .__ proto__ sont appelées. En d'autres termes, lorsqu'ils sont utilisés comme constructeur, la chaîne A.Prototype est prise et les méthodes et attributs sont affectés à leurs exemples; Lorsqu'il est utilisé comme objet, la chaîne A .__ Proto__ est prise. Dans différents scénarios, il n'est pas faux de distinguer son identité.
Après l'ensemble de l'article, je pense que ce que j'ai dit est assez lancinant ... s'il vous plaît, corrigez-moi s'il y a des lacunes ~ Quant à la question, je ne sais vraiment pas comment l'appeler. .
Que cet article vous apporte quelques gains après l'avoir lu ~ ^ _ ^
Merci pour votre soutien à ce site Web. Nous continuerons à mettre à jour les informations pertinentes à l'avenir pour vous aider à apprendre et à comprendre cette partie des connaissances!