web-dev-qa-db-fra.com

Pourquoi la propriété du prototype JavaScript n'est-elle pas définie sur les nouveaux objets?

Je suis assez nouveau dans le concept de prototype de JavaScript.

Considérant le code suivant:

var x = function func(){
}

x.prototype.log = function() {
  console.log("1");
}

var b = new x();

Si je comprends bien, b.log() devrait retourner 1 puisque x est son prototype. Mais pourquoi la propriété b.prototype N'est-elle pas définie?

b.prototype N'est-il pas censé renvoyer la référence à la fonction x?

52
Pascal Paradis

Seules les fonctions constructeur ont des prototypes. Puisque x est une fonction constructeur, x a un prototype.

b n'est pas une fonction constructeur. Par conséquent, il n'a pas de prototype.

Si vous souhaitez obtenir une référence à la fonction qui a construit b (dans ce cas, x), vous pouvez utiliser

b.constructor
69
Peter Olson

La propriété .prototype D'une fonction est juste là pour configurer l'héritage sur le nouvel objet lorsque la fonction est invoquée en tant que constructeur.

Lorsque le nouvel objet est créé, il obtient sa propriété interne [[Prototype]] définie sur l'objet vers lequel pointe la propriété .prototype De la fonction.

L'objet lui-même ne reçoit pas de propriété .prototype. Sa relation à l'objet est complètement interne.

C'est pourquoi cela fonctionne pour faire b.log(). Lorsque le moteur JS voit que l'objet b lui-même n'a pas de propriété log, il essaie de le rechercher sur l'objet interne [[Prototype]], où il le trouve avec succès.

Pour être clair, la propriété [[Prototype]] n'est pas directement accessible. C'est une propriété interne qui n'est mutable qu'indirectement via d'autres constructions fournies par le moteur JS.

22
the system

Avant de parcourir votre code, je veux m'assurer que certains concepts de prototype sont nécessaires pour comprendre le comportement de votre code.

  1. [[prototype]] Est une propriété masquée d'un objet JavaScript. Cette propriété masquée n'est rien d'autre qu'un lien vers Object.prototype (Si elle est créée par des littéraux d'objet). Il n'existe aucun moyen standard d'accéder à cette [[prototype]] propriété.
  2. Les fonctions en JavaScript sont des objets et ont donc également la propriété [[prototype]]. Ici, en cas de fonction, cette propriété cachée est un lien vers Function.prototype. Il n'y a pas non plus de moyen standard d'accéder à cette [[prototype]] propriété.
  3. En dehors de ce lien caché [[prototype]], Chaque fois qu'un objet fonction est créé, une propriété prototype est créée à l'intérieur, qui est distincte de la propriété cachée [[prototype]].

Venons-en maintenant à votre code:

var x = fonction func () {}

Lorsque cette ligne s'exécute, un objet fonction x est créé avec deux liens:

  • Function.prototype (non accessible),
  • x.prototype (accessible).

x.prototype.log = function () {console.log ("1"); }

comme nous savons maintenant que x est un objet fonction donc x.prototype est accessible, donc ici vous pouvez inclure la méthode log avec lui.

var b = nouveau x ();

b est un objet mais pas un objet fonction. Il a ce lien caché [[prototype]] mais il n'est pas accessible. donc quand vous essayez d'accéder comme b.prototype cela donne undefined comme résultat. Si vous voulez vérifier le prototype de b que vous pouvez voir (x.prototype).isPrototypeOf(b); renverra true. vous pouvez donc dire que le lien caché est référencé à x.prototype.

Voici quelques faits sur le prototype:

  1. Si l'objet O est créé avec O = new func(){} alors O [[prototype]] est Function.prototype.
  2. Si l'objet O est créé avec O = {} Alors O [[prototype]] est Object.prototype.
  3. Si l'objet O est créé avec O = Object.create(obj) alors O [[prototype]] est obj.
12
Anshul

Tous les objets ordinaires en JavaScript ont un emplacement de prototype interne (remarque: le prototype ici ne fait pas référence à la propriété prototype). La norme ECMAScript ( http://www.ecma-international.org/ecma-262/6.0/index.html ) spécifie que cet emplacement est appelé [[Prototype]]. Vous pouvez accéder à cet emplacement via la propriété __proto__.

__proto__ peut ne pas être disponible de manière fiable sur tous les navigateurs. __proto__ devient une propriété officielle dans ECMAScript 6

La propriété prototype est cependant une propriété sur une fonction constructeur qui définit ce qui deviendra la propriété __proto__ sur l'objet construit.

Vous pouvez accéder à la propriété prototype de certains types, par exemple, les principaux types JavaScript (Date, Array, etc.). Une fonction JavaScript (qui peut être considérée comme un constructeur) possède également une propriété prototype publique. Cependant, les instances d'une fonction n'ont pas de propriété prototype.

Dans votre cas, var b = new x();, b est une instance de la fonction x. Le b.prototype n'est donc pas défini. Cependant, b a un emplacement interne [[Prototype]]. Si vous affichez b.__proto__ dans Google Chrome par exemple, la version 63.0.3239.132 ou Firefox comme la version 43.0.4

console.log(b.__proto__);

Vous verrez son emplacement [[Prototype]] comme ci-dessous:

{log: ƒ, constructor: ƒ}

C'est ça.


Et juste pour votre référence, l'extrait de code entier est mis comme ci-dessous:

var x = function() {
};
x.prototype.log = function() {
  console.log("1");
}

var b = new x();
b.log();  // 1

console.log(b.prototype); // undefined
console.log(b.__proto__); // {log: ƒ, constructor: ƒ}
console.log(x.prototype); // {log: ƒ, constructor: ƒ}
12
Yuci

Parce que prototype est une propriété de fonctions (en fait, des constructeurs), car elle définit les propriétés/méthodes des objets de cette classe (celles qui ont été créées à partir du constructeur auquel appartient ce prototype). Jetez un oeil à ce lien

1
Danilo Valente