17 votes

Un nouvel objet en Javascript possède-t-il une propriété prototype ?

Il s'agit d'une question purement triviale à valeur académique :

Si je crée un nouvel objet, soit en faisant :

var o = { x:5, y:6 };

ou

var o = Object.create({ x:5, y:6 });

lorsque j'interroge le o.prototype propriété, j'obtiens undefined . Je pensais que tout objet nouvellement créé héritait automatiquement de l'ensemble de l'objet. Object.prototype prototype.

En outre, l'invocation de toString() (une méthode de Object.prototype ) sur cet objet fonctionne très bien, ce qui implique que o hérite de Object.prototype . Alors pourquoi j'ai undefined ?

19voto

pimvdb Points 66332

Il y a une différence entre les instances et leurs constructeurs.

Lors de la création d'un objet comme {a: 1} vous créez une instance du Object constructeur. Object.prototype est effectivement disponible, et toutes les fonctions à l'intérieur de ce prototype sont disponibles :

var o = {a: 1};
o.hasOwnProperty === Object.prototype.hasOwnProperty; // true

Mais Object.create fait quelque chose de différent. Il crée une instance (un objet), mais insère une chaîne de prototypes supplémentaire :

var o = {a: 1};
var p = Object.create(o);

La chaîne sera :

Object.prototype  -  o  -  p

Cela signifie que :

p.hasOwnProperty === Object.prototype.hasOwnProperty; // true
p.a === o.a; // true

Pour obtenir le prototype "sous" une instance, vous pouvez utiliser Object.getPrototypeOf :

var o = {a: 1};
var p = Object.create(o);

Object.getPrototypeOf(p) === o; // true
Object.getPrototypeOf(o) === Object.prototype; // true

(Auparavant, vous pouviez accéder au prototype d'une instance à l'aide de la commande o.__proto__ mais cela a été déprécié).

Notez que vous pourriez également accéder au prototype de la manière suivante :

o.constructor === Object; // true

Donc :

o.constructor.prototype === Object.prototype // true
o.constructor.prototype === Object.getPrototypeOf(o); // true

Cela échoue pour Object.create -car ils ne possèdent pas de constructeur (ou plutôt, leur constructeur est Object et pas ce que vous avez passé à Object.create car la fonction constructeur est absente).

4voto

Vahur Roosimaa Points 2232

Ce n'est pas une réponse directe, mais une connaissance que tous ceux qui traitent de l'héritage en Javascript devraient avoir.

L'héritage des prototypes en Javascript est un concept délicat. Jusqu'à présent, il était impossible de créer un objet vide (par vide, je veux dire dépourvu même des propriétés de la forme Object via le prototype). Cela signifie donc que la création d'un nouvel objet avait toujours un lien avec le prototype original de l'Object. Cependant, selon la spécification, la chaîne de prototype d'une instance d'objet n'est pas visible, mais certains fournisseurs ont décidé d'implémenter leurs propres propriétés d'objet propriétaires afin que vous puissiez la suivre, mais il est fortement recommandé de ne pas l'utiliser dans le code de production.

L'exemple de code suivant démontre seulement deux façons de créer une instance d'objet.

var someObject = {};
var otherObject = new Object();
var thirdObject = Object.create({});

Même si vous n'ajoutez pas manuellement les propriétés d'objet aux accolades vides, vous obtenez quand même une chaîne de prototypes ajoutée automatiquement. Il en va de même pour le deuxième exemple. Pour mieux visualiser, vous pouvez taper ces lignes dans la console de Chrome et ensuite entrer soit someObject , otherObject o thirdObject pour voir les détails. Chrome montre la chaîne de prototypes en ajoutant une propriété propriétaire __proto__ que vous pouvez développer pour voir ce qui est hérité et d'où ça vient. Si vous avez exécuté quelque chose comme

Object.prototype.sayHello = function() {
  alert('hello');
};

vous seriez en mesure de l'appeler sur toutes les instances, en exécutant otherObject.sayHello() .

Toutefois, grâce à un élément qui a été mis en œuvre assez récemment (et qui n'est donc pas pris en charge par tous les navigateurs), il est possible de créer une instance d'objet véritablement vide (qui n'hérite même pas de l'objet lui-même).

var emptyObject = Object.create(null);

Lorsque vous l'entrez dans la console de Chrome et que vous développez ensuite le fichier emptyObject pour voir sa chaîne de prototypes, vous pouvez voir qu'elle n'existe pas. Donc, même si vous avez implémenté le sayHello au prototype d'objet, il serait impossible d'appeler la fonction emptyObject.sayHello() depuis emptyObject n'hérite pas du prototype d'objet.

J'espère que cela vous aidera un peu à comprendre l'idée générale.

3voto

Ying Points 541

JavaScript possède deux types d'objets : les objets fonctionnels et les objets non fonctionnels. Conceptuellement, tous les objets ont un prototype ( PAS UNE PROPRIÉTÉ DE PROTOTYPE ). En interne, JavaScript nomme le prototype d'un objet comme suit [[Prototype]] .

Il existe deux approches pour obtenir le [[prototype]] de n'importe quel objet (y compris les objets non fonctionnels) : la fonction Objet.getPrototypeOf() et la méthode __proto__ propriété. Le site __proto__ est prise en charge par de nombreux navigateurs et par Node.js. Elle doit être normalisée dans ECMAScript 6.

Seule une fonction (un objet appelable) possède l'attribut propriété du prototype . Cette propriété prototype est une propriété régulière qui n'a pas de relation directe avec le [[prototype]] de la fonction elle-même. Lorsqu'elle est utilisée comme constructeur (après l'opérateur new), la propriété prototype de la fonction sera affectée au [[Prototype]] d'un objet nouvellement créé. Dans un objet sans fonction, la propriété prototype est indéfinie. Par exemple,

var objectOne = {x: 5}, objectTwo = Object.create({y: 6});

L'objetOne et l'objetTwo sont tous deux des objets non fonctionnels, ils n'ont donc pas d'objet propriété du prototype .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X