Cha�ne de prototypes JavaScript : Guide court et simple, par Mensur Durakovic
Avant de commencer, permettez-moi de vous mettre en garde. Cet article s'adresse � ceux qui veulent comprendre comment fonctionne la cha�ne de prototypes en JavaScript.
Cela va �tre difficile pour certains d'entre vous et il se peut que cela ne soit pas tr�s clair � la premi�re lecture. Il se peut que vous deviez relire cet article plusieurs fois pour le comprendre.
Mais cela en vaut la peine. La question sur la cha�ne de prototypes est assez souvent pos�e dans les entretiens techniques.
Vous savez probablement d�j� que les tableaux et les fonctions sont des objets en JavaScript. JavaScript utilise ce que l'on appelle l'h�ritage prototypique. Vous voyez ces fl�ches ici :
Il s'agit de l'h�ritage prototypique. Qu'est-ce que cela signifie ?
L'h�ritage est essentiellement un objet qui a acc�s aux propri�t�s et aux m�thodes d'un autre objet.
Ainsi, tout est un objet en JavaScript. Le tableau a acc�s aux propri�t�s et aux m�thodes de l'objet. Il en va de m�me pour les fonctions. Gr�ce � cette cha�ne que nous appelons la cha�ne de prototypes, les fonctions ont acc�s aux m�thodes et aux propri�t�s des objets.
Voyons maintenant ce qu'il en est :
Tout d'abord, nous avons un tableau vide appel� "food".
Ensuite, nous acc�dons � cette propri�t� �trange appel�e "__proto__". Elle s'�crit avec 2 underscores avant et apr�s le mot proto. Nous pouvons voir dans la console que cette propri�t� bizarre est un tableau de fonctions :
- constructor,
- at,
- concat,
- copyWithin,
- fill,
- push, etc.
Ce sont toutes des m�thodes que les donn�es de type tableau obtiennent par d�faut.
Ce que nous avons fait ici, c'est de remonter dans la cha�ne des prototypes. Et nous sommes entr�s dans le prototype Array (remarquez l'image et le A majuscule). Puisque Array est le "parent" de notre tableau "food", nous h�ritons de toutes ces m�thodes.
Maintenant, � la ligne suivante, nous avons cette syntaxe bizarre "__proto__" 2 fois. Vous l'avez peut-�tre devin�, avec cela, nous montons d'un niveau dans la cha�ne des prototypes. Nous acc�dons donc au prototype du grand-parent "food". Et c'est Object.
C'est l'objet � partir duquel tout est cr�� en JavaScript. Y compris les fonctions et les tableaux.
Par exemple, nous avons la m�thode toString ici. Cela signifie que tout ce qui est un descendant d'Object obtiendra la m�thode toString. Cela signifie donc qu'un tableau "food" dispose de la m�thode toString.
Vous voyez que j'obtiens le m�me r�sultat pour un type de fonction :
Voil� ce qu'est l'h�ritage de prototype.
En fait, l'h�ritage de prototype est assez unique. Il n'est pas tr�s courant dans d'autres langages populaires comme C# ou Java. Ces derniers utilisent ce que l'on appelle l'h�ritage classique, tandis que JavaScript utilise l'h�ritage prototype.
M�me si le mot-cl� class existe en JavaScript, il n'y a en fait pas de class dans ce langage. Nous n'avons que l'h�ritage prototype.
Ainsi, lorsque vous �crivez un mot-cl� class, vous utilisez une fonction en arri�re-plan. C'est ce que nous appelons le sucre syntaxique.
Vous pouvez vous demander o� se trouve la fin de la cha�ne des prototypes.
Eh bien, c'est facile � trouver :
Ici, nous avons notre objet "food" et nous passons � deux niveaux sup�rieurs. Le premier niveau est donc notre type parent Object, mais si vous allez plus haut, vous obtenez null.
En JavaScript, undefined est souvent utilis� pour indiquer qu'une variable ou une propri�t� d'objet n'a pas �t� initialis�e ou qu'aucune valeur ne lui a �t� attribu�e. Ou lorsqu'une fonction ne renvoie aucune valeur.
Null signifie qu'il n'y a absolument rien. Il repr�sente l'absence intentionnelle de toute valeur d'objet.
Vous avez probablement entendu parler des listes cha�n�es, n'est-ce pas ? Vous pouvez repr�senter la cha�ne de prototypes dans votre t�te sous la forme d'une simple liste cha�n�e :
Tous les n�uds sont reli�s par les liens de leur cha�ne de prototypes. Le null est le dernier n�ud de la liste cha�n�e de la cha�ne de prototypes.
La cha�ne de prototypes dans le code
Jetons un coup d'�il � cet extrait de code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const human = {
name: "Joe",
canTalk: true,
getIntelligence(){
return 10;
},
talk(){
if(this.canTalk){
console.log(`Hi, my name is ${this.name}!`);
}
}
}
const chimpanzee = {
name: "Mowgli",
getIntelligence(){
return 5;
}
} |
Rien de sp�cial ici, nous avons 2 objets simples :
- human Joe. Il peut parler et son intelligence est de 10 points. Lorsqu'il parle, il dit : "Bonjour, je m'appelle Joe !".
- chimpanzee Mowgli. Il ne peut pas parler et son intelligence n'est que de 5 points.
Imaginons que je veuille faire parler Mogwli. Comment faire ?
Eh bien, je peux utiliser une astuce avec la m�thode .bind et "emprunter" la fonction de conversation � un human. Essayons ceci :
1 2 3 4
| const talkingChimpanzee = human.talk.bind(chimpanzee);
console.log(talkingChimpanzee());
// prints undefined |
Malheureusement, la propri�t� canTalk du chimpanz� n'est pas r�gl�e sur true. Ainsi, m�me si nous empruntons la m�thode, nous n'avons pas la capacit� de parler.
Que pouvons-nous donc faire ici ?
Nous pourrions ajouter la propri�t�, mais vous pouvez voir comment cela pourrait devenir de plus en plus compliqu�, n'est-ce pas ? Que se passerait-il si nous avions un gros objet et que nous voulions emprunter plus d'une propri�t�/m�thode ?
C'est l� que l'h�ritage de prototype entre en jeu.
Nous pouvons cr�er une cha�ne de prototypes qui h�ritera de toutes ces propri�t�s et m�thodes d'un humain.
1 2 3 4 5
| chimpanzee.__proto__ = human;
chimpanzee.talk(); // prints "Hi, my name is Mowgli!"
console.log(chimpanzee.canTalk); // prints true
console.log(chimpanzee.getIntelligence()); // prints 5 |
Nous pouvons voir que ce qui pr�c�de correspond exactement � ce dont nous avions besoin.
L'intelligence du chimpanz� est toujours de 5 car il est d�fini comme un objet chimpanz�. Nous sommes donc en mesure d'h�riter, par le biais de cette cha�ne de prototypes, de toutes les propri�t�s et m�thodes d'un humain.
Ensuite, nous rempla�ons tout ce que nous avons d�j� d�clar� dans notre propre objet. Dans ce cas, il s'agit de la propri�t� name et de la m�thode talk.
M�thode hasOwnProperty
Laissez-moi vous montrer une autre chose int�ressante :
1 2 3 4 5
| console.log("Has name property: ", chimpanzee.hasOwnProperty('name'));
console.log("Has canTalk property: ", chimpanzee.hasOwnProperty('canTalk'));
// Has name property: true
// Has canTalk property: false |
Tout d'abord, comment cela fonctionne-t-il ?
Nous savons qu'un chimpanz� n'a pas de m�thode appel�e hasOwnProperty. Un humain n'a pas non plus cette fonction.
Eh bien, un humain a �galement un "parent" dont il h�rite de toutes les m�thodes et propri�t�s. Ce parent est Object et je l'ai mentionn� au d�but. Object est le parent de tous les parents, le parent final.
Ainsi, en arri�re-plan, JavaScript essaie d'abord de trouver la fonction hasOwnProperty chez un chimpanz�. Mais il ne la trouve pas.
Il remonte alors dans la cha�ne de prototypes et commence � chercher dans un humain. Il ne la trouve pas.
Il remonte alors d'un niveau dans la cha�ne des prototypes, dans Object, et c'est l� que se trouve la m�thode :
Nous savons maintenant pourquoi le chimpanz� poss�de cette m�thode hasOwnProperty.
Mais que fait la m�thode hasOwnProperty ?
Elle renvoie un bool�en indiquant si cet objet poss�de la propri�t� sp�cifi�e comme sa propre propri�t�. Il ne s'agit donc pas d'une propri�t� h�rit�e, mais d'une propri�t� propre.
C'est pourquoi, dans le dernier extrait de code, la m�thode hasOwnProperty affiche true pour name et false pour canTalk.
Le chimpanz� a sa propre propri�t� name d�finie dans l'objet. La propri�t� canTalk ne lui appartient donc pas. Elle est h�rit�e d'un humain et c'est pourquoi elle affiche false.
Attention, attention, attention !
Vous vous demandez peut-�tre comment il se fait que je n'aie jamais vu cette chose "__proto__" avant ?
Cela semble tr�s utile. Pourquoi ne le voit-on pas dans les projets ?
Ce que je vous ai montr�, vous ne devriez le faire dans aucun projet. Et je veux dire ceci :
chimpanzee.__proto__ = human;
Vous ne devriez pas l'utiliser. En fait, vous ne devriez JAMAIS l'utiliser !
C'est mauvais pour les performances. Il existe diff�rentes fa�ons d'utiliser le prototype ou l'h�ritage.
Ainsi, nous ne voulons jamais assigner la cha�ne de prototypes et cr�er cette cha�ne nous-m�mes. Cela va perturber s�rieusement notre compilateur JavaScript.
Mais je voulais vous montrer comment cela fonctionne.
Que peut-on utiliser � la place de "__proto__" ?
Voyons comment nous pouvons cr�er nos propres prototypes et quelle est la mani�re la plus s�re de le faire.
V�rifions ce code :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const human = {
canTalk: true
}
const chimpanzee = Object.create(human);
chimpanzee.jumpOnTree = true;
console.log(chimpanzee);
// prints {jumpOnTree: true}
console.log(chimpanzee.canTalk);
// prints true
console.log(human.isPrototypeOf(chimpanzee));
// prints true |
Nous avons donc ici un humain qui peut parler. Puis nous avons un chimpanz� qui h�rite de l'humain. Nous faisons cela avec la m�thode Object.create.
Il existe de nombreuses fa�ons de proc�der, et c'est l'une d'entre elles qui nous permet d'h�riter d'un humain.
Si nous imprimons un objet chimpanz�, tout ce que nous pouvons voir est la propri�t� jumpOnTree. Mais si nous acc�dons explicitement � cette propri�t� h�rit�e d'un humain. Nous constatons qu'elle existe et qu'elle vaut true.
Enfin, nous v�rifions si un humain est le prototype d'un chimpanz� avec la m�thode isPrototypeOf. Et nous obtenons true parce que nous avons cr��, en utilisant Object.create, une cha�ne de prototypes jusqu'� un humain.
Maintenant, vous savez comment faire cela sans utiliser cette chose diabolique qu'est le "__proto__".
En fait, ils l'ont nomm�e ainsi (avec des doubles soulign�s) pour que personne ne s'amuse avec la cha�ne de prototypes.
Pourquoi la cha�ne de prototypes est-elle utile ?
Le fait que les objets puissent partager des prototypes signifie que vous pouvez avoir des objets dont les propri�t�s pointent vers le m�me endroit de la m�moire. Ils sont donc plus efficaces.
Imaginez que nous ayons un grand nombre de chimpanz�s, n'est-ce pas ? Et que nous copiions toutes les fonctionnalit�s de l'homme sur le chimpanz� � diff�rents endroits de la m�moire.
Cela pourrait vite devenir trop lourd et faire exploser votre code.
Au lieu de copier toutes ces fonctionnalit�s � diff�rents endroits de la m�moire, avec le prototype d'h�ritage, nous les avons en un seul endroit.
Tout ce qui h�rite d'un humain utilisera cette instance de cette m�thode. Car le moteur JavaScript va chercher la cha�ne de prototypes.
Source : "JavaScript Prototype Chain: Short And Simple Guide" (Mensur Durakovic)
Et vous ?
Quel est votre avis sur le sujet ?
Voir aussi :
Une proposition visant � ajouter des signaux � JavaScript afin de fournir une infrastructure, permettant aux d�veloppeurs de se concentrer sur la logique plut�t que sur les d�tails r�p�titifs
�tat de JavaScript 2022 : React reste le framework front-end dominant mais est en perte de vitesse c�t� satisfaction. JQuery est la troisi�me biblioth�que la plus utilis�e
Partager