Fermer

janvier 9, 2026

Simplification des prototypes JavaScript dans l’invocation du constructeur

Simplification des prototypes JavaScript dans l’invocation du constructeur


Découvrez les prototypes JavaScript et les chaînes de prototypes, qui expliquent comment les objets sont créés.

En tant que développeur JavaScript, vous avez probablement entendu la phrase : « En JavaScript, chaque objet est créé à partir d’un objet existant. »

Mais comme il existe plusieurs façons (quatre, pour être précis) de créer un objet, par exemple en utilisant un constructeur de fonction ou une classe, cette affirmation peut sembler fausse. Comment créer un objet à partir d’un objet existant ?

Dans cet article, mon objectif est de vous donner une compréhension claire des prototypes JavaScript et de la façon dont les objets sont créés. À la fin, vous serez en mesure de comprendre ces concepts à l’aide d’un diagramme comme celui présenté ci-dessous :

Objet - prototype

Commençons par la déclaration suivante :

« En JavaScript, chaque objet est lié à un objet existant, et cet objet existant est connu comme le prototype de cet objet. »

X rouge - Un nouvel objet est CRÉÉ à partir d'un objet existant. Coche verte : le nouvel objet est lié à un objet existant.

Ainsi, autrement dit, chaque objet JavaScript que vous créez est lié à son objet prototype. Cela signifie qu’un nouvel objet JavaScript est toujours lié à son objet prototype.

Considérez cette fonction constructeur :

function  Product(name, price) {
  this.name = name;
  this.price = price;
}

let  p1 = new  Product('Pen', 1.2);
console.log(Object.getPrototypeOf(p1));

Quand vous créez p1 avec new Product(...)JavaScript fait deux choses importantes pour vous :

  • Il crée un nouvel objet p1.
  • Il définit le prototype interne de ce nouveau (p1) objet ([[Prototype]]) à Product.prototype.

Donc p1 est lié au Product.prototype objet.

Le diagramme montrant que p1 est lié à Product.prototype

Tout autre objet créé à l’aide du nouveau Product(...) sera lié au même Product.prototype objet.

let  p2 = new  Product('Pencil', 0.8);
console.log(Object.getPrototypeOf(p2));

Diagramme montrant que P2 est lié à Product.prototype

Puisque les deux p1 et p2 sont créés en utilisant la même fonction constructeur Productils sont liés au même objet prototype et ont accès en lecture aux propriétés de l’objet prototype.

Diagramme montrant que p1 et P2 sont tous deux = liés à Product.prototype

Avant de continuer, regardons les différentes manières de créer un objet en JavaScript :

  1. Utiliser une fonction comme constructeur
  2. Utiliser un objet littéral
  3. Utiliser une classe
  4. En utilisant le Object.create() méthode

Modèle d’appel de constructeur

Commençons par la fonction en tant que constructeur. Lorsque vous utilisez une fonction pour créer un objet, elle est également appelée modèle d’appel de constructeur.

Lorsqu'un objet est créé à l'aide d'une fonction, il est appelé modèle d'appel de constructeur.

En JavaScript, chaque fonction régulière (mais pas les fonctions fléchées) possède un objet prototype. Lorsque vous utilisez une fonction normale comme constructeur, le prototype interne de l’objet nouvellement créé ([[Prototype]]) est lié au prototype de cette fonction. Les fonctions fléchées n’ont pas de propriété prototype, elles ne peuvent donc pas être utilisées comme constructeurs. Pour démontrer cela, imprimez les deux valeurs suivantes :

function  Product(title, price) {
  this.title = title;
  this.price = price;
}

console.log(Product.prototype); 

var Invoice = (title, price) => {
  this.title = title;
  this.price = price;
}
console.log(Invoice.prototype); 

Comme le montre le résultat, le prototype d’une fonction fléchée n’est pas défini, elle ne peut donc pas être utilisée comme constructeur pour créer des objets.

Autres fonctions - prototype - {}. Fonctions fléchées - prototype - non défini

Nous ne pouvons donc pas utiliser une fonction flèche comme constructeur pour créer un objet.

Diagramme prototype

Dans cette section, créons un diagramme prototype étape par étape à l’aide du modèle d’appel de constructeur pour créer des objets. Certaines règles que nous allons suivre sont les suivantes :

  • Dessiner une fonction sous forme de cercle
  • Dessinez l’objet sous forme de rectangle
  • Dessinez un objet prototype sous la forme d’un rectangle rouge

Nous avons une fonction Produit :

function  Product(title, price) {
  this.title = title;
  this.price = price;
}

Dessinons le Product fonctionner comme un cercle :

cercle de produits

Ensuite, ajoutez une propriété de quantité à la fonction Produit :

Product.prototype.quantity = 10;

Ceci est représenté dans le diagramme en utilisant une réactance rouge et une flèche de Product fonction ci-dessous :

produit - prototype - quantité : 10

Créons ensuite deux objets, p1 et p2du Product constructeur comme indiqué ci-dessous :

let  p1 = new  Product('Pen', 100);
let  p2 = new  Product('Pencil', 200);

Cela peut être représenté dans le diagramme ci-dessous :

Même diagramme, maintenant avec p1 et p2 pointant les constructeurs vers le produit

Parce que p1 et p2 sont des objets, nous les dessinons sous forme de rectangles. Et depuis le Product constructeur a créé les deux, chaque rectangle a une flèche pointant vers le Product fonction. Si vous vous connectez p1.constructor ou p2.constructorça revient Product.

console.log(p1.constructor === Product);
console.log(p2.constructor === Product); 

Jusqu’à présent, nous avons connecté les instances, le constructeur et le prototype.

console.log(p1.quantity); 
console.log(p2.quantity); 
console.log(p1.hasOwnProperty('quantity'));
console.log(p2.hasOwnProperty('quantity')); 

Maintenant, quand vous lisez le quantity propriété sur p1 ou p2JavaScript suit ces étapes :

  • Vérifiez l’objet lui-même (p1) pour son propre propriété nommée quantité. S’il est trouvé, renvoyez cette valeur et arrêtez.
  • S’il n’est pas trouvé, suivez les instructions internes [[Prototype]] lien vers Product.prototype et cherchez la quantité là-bas. Si trouvé sur le prototype, renvoyez cette valeur et arrêtez.
  • S’il n’est toujours pas trouvé, continuez la chaîne de prototypes jusqu’à Object.prototype et vérifiez là-bas.
  • Si la propriété ne figure nulle part sur la chaîne, renvoyez undefined.

Vous pouvez maintenant suivre la chaîne du prototype pour lire la valeur de la quantité pour p1 et p2. En fait, en regardant le schéma, vous pouvez voir que p1.quantity se résout à la même valeur que p1.constructor.prototype.quantityfourni p1 n’a pas sa propre propriété de quantité.

console.log(p1.quantity == p1.constructor.prototype.quantity); 
console.log(p2.quantity == p2.constructor.prototype.quantity); 
console.log(p1.quantity)
console.log(p2.quantity)
console.log(p1.constructor.prototype.quantity); 
console.log(p2.constructor.prototype.quantity); 

Le prototype est accessible de deux manières :

  1. Grâce au constructeur (obj.constructor.prototype)
  2. Directement via le serveur interne de l’instance [[Prototype]]

Lorsque vous créez un objet avec un constructeur, JavaScript définit l’instance [[Prototype]] au prototype de ce constructeur. La plupart des moteurs JavaScript exposent ce lien comme obj.__proto__. Modifions donc le diagramme du prototype pour représenter cela.

Le diagramme montre maintenant p1 et p2 pointant les constructeurs vers le produit ET _proto_ vers la quantité

Comme vous pouvez le voir, p1.__proto__ fait référence au même objet que p1.constructor.prototypeet le __proto__ de p1 est identique au __proto__ de p2. Par conséquent, JavaScript renvoie true pour les comparaisons ci-dessous.

console.log(p1.quantity == p1.__proto__.quantity); 
console.log(p2.quantity == p2.__proto__.quantity); 
console.log(p1.constructor.prototype.quantity == p1.__proto__.quantity); 
console.log(p2.constructor.prototype.quantity == p2.__proto__.quantity); 
console.log(p1.__proto__ == p2.__proto__); 

Pour résumer, lorsque vous lisez une propriété d’un objet :

  • JavaScript lit la propriété dans l’objet lui-même.
  • Si JavaScript trouve la propriété, il lit la valeur.
  • Si JavaScript ne trouve pas la propriété, il accède au prototype de l’objet.
  • Si JavaScript trouve la propriété, il lit la valeur.
  • Si JavaScript ne trouve pas la propriété, il parcourt jusqu’au Object.prototype.
  • S’il ne trouve pas de propriété, il la lit comme indéfinie.

Le diagramme du prototype montre également qu’il existe plusieurs chemins pour atteindre le prototype d’un objet. Par exemple, les deux p1.constructor.prototype et p1.__proto__ conduire au même objet prototype de p1.

En rassemblant le tout, nous avons maintenant une fonction constructeur et deux objets créés à partir de celle-ci, comme indiqué ci-dessous :

function  Product(title, price) {
    this.title = title;
    this.price = price;
}

Product.prototype.quantity = 10; 

let p1 = new Product('Pen', 100);
let p2  = new Product('Pencil', 200);

Le code ci-dessus peut être traduit en un diagramme prototype comme indiqué ci-dessous.

Maintenant, la quantité pointe _proto_ et un objet pointe un prototype vers une nouvelle boîte

Vous pouvez maintenant facilement raisonner la question suivante en vous référant au diagramme du prototype :

console.log(p1.constructor === Product);
console.log(p2.constructor === Product); 

console.log(p1.quantity); 
console.log(p2.quantity); 
console.log(p1.hasOwnProperty('quantity'));
console.log(p2.hasOwnProperty('quantity')); 

console.log(p1.quantity == p1.constructor.prototype.quantity); 
console.log(p2.quantity == p2.constructor.prototype.quantity); 
console.log(p1.quantity)
console.log(p2.quantity)
console.log(p1.constructor.prototype.quantity); 
console.log(p2.constructor.prototype.quantity); 

console.log(p1.quantity == p1.__proto__.quantity); 
console.log(p2.quantity == p2.__proto__.quantity); 
console.log(p1.constructor.prototype.quantity == p1.__proto__.quantity); 
console.log(p2.constructor.prototype.quantity == p2.__proto__.quantity); 
console.log(p1.__proto__ == p2.__proto__); 

Opération d’écriture

Par défaut, JavaScript vous permet d’ajouter dynamiquement des propriétés à un objet. Par exemple, l’opération suivante fonctionne parfaitement :

var  Foo = {};
Foo.koo = 9;

En JavaScript, les opérations d’écriture ciblent toujours l’objet lui-même plutôt que sa chaîne de prototypes. Cela signifie que lorsque vous attribuez une nouvelle propriété, par exemple : p1.color = "red": la propriété est créée comme son propre propriété sur p1.

Autres instances créées à partir du même constructeur, telles que p2n’héritera pas de cette propriété car elle n’existe que sur p1 et non sur le prototype partagé.

let  p1 = new  Product('Pen', 100);
p1.color = "red";
let  p2 = new  Product('Pencil', 200);
console.log(p1.color); 
console.log(p2.color); 

Pour le p2 objet, la valeur de couleur n’est pas définie car aucun objet dans sa chaîne de prototypes ne définit une propriété de couleur.

En JavaScript, si un objet définit une propriété portant le même nom que celle qui existe sur son prototype, la propre propriété de l’objet est prioritaire. Ce comportement est connu sous le nom observation de propriété. Lorsque l’observation de propriété se produit, les recherches sur l’objet renverront la valeur de la propre propriété, masquant ainsi la propriété correspondante sur le prototype sans la modifier.

Product.prototype.quantity = 10;

let  p1 = new  Product('Pen', 100);
p1.color = "red";
let  p2 = new  Product('Pencil', 200);
p2.quantity = 56;
console.log(p1.color); 
console.log(p2.color); 
console.log(p1.quantity); 
console.log(p2.quantity); 

Maintenant p2 a sa propre propriété de quantité, donc lorsque vous accédez p2.quantityJavaScript le lit directement à partir du p2 objet au lieu du prototype. Le diagramme du prototype mis à jour illustre cela comme indiqué ci-dessous :

p2 affiche maintenant la quantité : 56

Ceci en prototype

Voyons maintenant comment this se comporte dans la chaîne de prototypes. Nous allons modifier le code de base comme indiqué ci-dessous :

function  Product(title, price) {
    this.title = title;
    this.price = price;
}

Product.prototype.quantity = 10; 
Product.prototype.log = function(){
    console.log(`${this.title} costs ${this.price} and quantity available : ${this.quantity}`);
}

Nous avons ajouté une fonction nommée log au prototype du produit et, à l’intérieur de celui-ci, nous utilisons le this mot-clé pour accéder aux propriétés de l’objet. Le log est ajoutée au prototype, afin que toutes les instances de Product puissent appeler cette méthode pour afficher leurs informations.

let  p1 = new  Product('Pen', 100);
let  p2 = new  Product('Pencil', 200);
p1.log();
p2.log();

Quand le log la méthode est appelée p1la valeur de this à l’intérieur de la méthode fait référence au p1 objet. De même, lorsqu’on l’appelle p2, this fait référence au p2 objet.

Si vous souhaitez définir un objet différent comme valeur, vous pouvez utiliser le Modèle d’appel indirect avec des méthodes comme callcomme indiqué ci-dessous.

p1.log.call(p2);

La valeur de this est non déterminé par l’endroit où une fonction est définiemais par comment on l’appelle.

  • p1.log() → À l’intérieur log, this fait référence à p1.
  • p2.log() → À l’intérieur log, this fait référence à p2.

C’est pourquoi la même méthode sur le prototype fonctionne pour les deux objets :this pointe toujours vers l’objet appelant.

Résumé

  • En JavaScript, chaque objet possède un lien interne vers un autre objet appelé son prototype. Ce maillon forme une chaîne, connue sous le nom de chaîne prototypequi est utilisé pour la recherche de propriétés et de méthodes.
  • Comme une fonction fléchée n’a pas d’objet prototype, elle ne peut pas être utilisée comme constructeur.
  • Si vous attribuez une propriété directement à une instance, elle ombres la propriété du prototype.
  • L’opération d’écriture (=) crée ou met toujours à jour son propres propriétés sur l’objet, pas sur le prototype.
  • Lorsque vous lisez une propriété, JavaScript recherche la propriété sur l’objet lui-même. S’il n’est pas trouvé, passez au prototype de l’objet et continuez à remonter la chaîne jusqu’à ce que Object.prototype. Si toujours introuvable, retournez undefined.
  • À l’aide du modèle d’appel indirect, vous pouvez transmettre explicitement la valeur de cet objet à la méthode créée sur l’objet prototype.

Tous les apprentissages ci-dessus peuvent être résumés dans le diagramme de chaîne prototype suivant.

Code et le schéma complet




Source link