__proto__ VS. prototype en JavaScript

785

Cette figure montre à nouveau que chaque objet a un prototype. La fonction constructeur Foo a également la sienne __proto__qui est Function.prototype, et qui à son tour fait également référence via sa __proto__propriété au Object.prototype. Ainsi, répétez, Foo.prototype n'est qu'une propriété explicite de Foo qui se réfère au prototype des objets b et c.

var b = new Foo(20);
var c = new Foo(30);

Quelles sont les différences entre __proto__et prototype?

entrez la description de l'image ici

Le chiffre a été tiré de dmitrysoshnikov.com .

0x90
la source
5
Je pense que le haut ou le bas est une question de préférence. En fait, je le préfère de cette façon, donc je peux retracer le diagramme jusqu'à ce que je trouve d'où vient quelque chose.
Mike Lippert
1
J'aime la façon dont JavaScript utilise l'héritage prototypique pour résoudre y.constructor en y .__ proto __. Constructeur. J'aime aussi la façon dont Object.prototype se situe en haut de la chaîne d'héritage prototypique avec Object.prototype .__ proto__ défini sur null. J'aime aussi la façon dont le diagramme fait une visualisation conceptuelle en trois colonnes de la façon dont le programmeur considère les objets comme 1. instances, 2. constructeurs, 3. prototypes que les constructeurs associent à ces instances lorsqu'ils sont instanciés via le nouveau mot clé.
John Sonderson
Le diagramme prend un sens immédiat après avoir regardé quelque chose comme youtube.com/watch?v=_JJgSbuj5VI , btw
mlvljr
Et maintenant, comme j'ai lu les réponses, sentez-vous obligé de vraiment recommander la vidéo ci-dessus, car elle a en effet une explication cristalline (et non WTFy) de ce qui se passe :)
mlvljr

Réponses:

766

__proto__est l'objet réel utilisé dans la chaîne de recherche pour résoudre les méthodes, etc. prototypeest l'objet utilisé pour créer __proto__lorsque vous créez un objet avec new:

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;
Mark Kahn
la source
239
Ah! N'est donc prototypepas disponible sur les instances elles-mêmes (ou sur d'autres objets), mais uniquement sur les fonctions constructeur.
rvighne
43
@rvighne: prototypeest disponible uniquement sur les fonctions puisqu'elles sont dérivées de Function, Functionet , Objectmais dans tout ce que ce n'est pas. Cependant, __proto__est disponible partout.
Tarik
19
Il en __proto__est de même de l'objet réel qui est enregistré et utilisé comme prototype alors que ce Myconstructure.prototypen'est qu'un plan pour __proto__lequel, en fait, l'objet réel est enregistré et utilisé comme protoype. Par conséquent, ce myobject.prototypene serait pas une propriété de l'objet réel parce que c'est juste une chose temporaire utilisée par la fonction constructeur pour décrire à quoi myobject.__proto__devrait ressembler.
Alex_Nabu
9
Est-il juste de dire que la __proto__propriété d'un objet est un pointeur sur la prototypepropriété de la fonction constructeur de l' objet? ie foo .__ proto__ === foo.constructor.prototype
Niko Bellic
10
@Alex_Nabu Pas tout à fait. newCar.__proto__ EST Car.prototype , pas une instance de Car.prototype. Alors Car.protoype qu'EST une instance d'un object. Car.prototypen'est pas quelque chose qui donne newCardes propriétés ou de la structure, simplement IS suivant objectdans newCar« la chaîne de prototype. Car.prototypen'est pas temporaire object. C'est le objectqui est défini comme la valeur de la __proto__propriété de tout nouveau objects fait en utilisant Carcomme a constructor. Si vous voulez penser à quoi que ce soit comme un plan object, pensez Carà un plan pour les voitures neuves object.
seangwright
336

prototypeest une propriété d'un objet Function. C'est le prototype des objets construits par cette fonction.

__proto__est la propriété interne d'un objet, pointant vers son prototype. Les normes actuelles fournissent une Object.getPrototypeOf(O)méthode équivalente , bien que la norme de facto __proto__soit plus rapide.

Vous pouvez trouver des instanceofrelations en comparant une fonction prototypeà la __proto__chaîne d' un objet , et vous pouvez rompre ces relations en changeant prototype.

function Point(x, y) {
    this.x = x;
    this.y = y;
}

var myPoint = new Point();

// the following are all true
myPoint.__proto__ == Point.prototype
myPoint.__proto__.__proto__ == Object.prototype
myPoint instanceof Point;
myPoint instanceof Object;

Voici Pointune fonction constructeur, elle construit un objet (structure de données) de façon procédurale. myPointest un objet construit par Point()donc Point.prototypeenregistré myPoint.__proto__à ce moment-là.

Lutin
la source
2
De plus, si vous modifiez la __proto__propriété d'un objet, cela modifie l'objet sur lequel les recherches de prototype sont effectuées. Par exemple, vous pouvez ajouter un objet de méthodes en tant que fonction __proto__pour avoir une sorte d'objet d'instance appelable.
kzh
myPoint .__ proto __. constructor.prototype == Point.prototype
Francisco
@kzh lol qui m'a donné un résultat amusant console.log(obj1.call) // [Function: call] obj1.call()// TypeError: obj1.call n'est pas une fonction. Je l'ai faitobj.__proto__ = Function.__proto__
abhisekp
myFn.__proto__ = {foo: 'bar'}
kzh
Je pense que j'ai votre point.
ComicScrip
120

La propriété prototype est créée lorsqu'une fonction est déclarée.

Par exemple:

 function Person(dob){
    this.dob = dob
 }; 

Person.prototypela propriété est créée en interne une fois que vous déclarez la fonction ci-dessus. De nombreuses propriétés peuvent être ajoutées au Person.prototype qui sont partagées par les instances Person créées à l'aide de new Person ().

// adds a new method age to the Person.prototype Object.
Person.prototype.age = function(){return date-dob}; 

Il est intéressant de noter que Person.prototypeest unObject littéral par défaut (il peut être modifié selon les besoins).

Chaque instance créée à l'aide de new Person()possède une __proto__propriété qui pointe vers le Person.prototype. Il s'agit de la chaîne utilisée pour parcourir pour trouver une propriété d'un objet particulier.

var person1 = new Person(somedate);
var person2 = new Person(somedate);

crée 2 instances de Person, ces 2 objets peuvent appeler la ageméthode Person.prototypeas person1.age,person2.age .

Dans l'image ci-dessus de votre question, vous pouvez voir que Fooc'est un Function Objectet donc il a un __proto__lien vers le Function.prototypequi à son tour est une instance deObject et a un __proto__lien vers Object.prototype. Le lien proto se termine ici avec __proto__le Object.prototypepointage vers null.

Tout objet peut avoir accès à toutes les propriétés de sa chaîne __proto__de prototypes liées par , formant ainsi la base de l'héritage prototypique.

__proto__ n'est pas un moyen standard d'accéder à la chaîne de prototypes, l'approche standard mais similaire consiste à utiliser Object.getPrototypeOf(obj) .

Code ci-dessous pour instanceof opérateur donne une meilleure compréhension:

L' instanceofopérateur de classe d' objet renvoietrue lorsqu'un objet est une instance d'une classe, plus précisément s'il Class.prototypese trouve dans la chaîne de prototypes de cet objet, alors l'objet est une instance de cette classe.

function instanceOf(Func){
  var obj = this;
  while(obj !== null){
    if(Object.getPrototypeOf(obj) === Func.prototype)
      return true;
    obj = Object.getPrototypeOf(obj);
  }
  return false;
}      

La méthode ci-dessus peut être appelée comme: instanceOf.call(object, Class)qui renvoie true si l'objet est une instance de Class.

sid_k_reddy
la source
2
Je me demandais pourquoi l' prototypeobjet a été créé en interne en premier lieu? Pourrait-on simplement attribuer des méthodes statiques à l'objet fonction lui-même. par exemple function f(a){this.a = a}; f.increment = function(){return ++this.a}? Pourquoi n'a-t-on pas choisi cette méthode plutôt que d'ajouter les méthodes à l' prototypeobjet? Cela fonctionnera si f.__proto__ = goù g est la classe de base.
abhisekp
Peut-être que l' prototypeobjet a été choisi pour le partage car seules les propriétés exclusives du constructeur de fonction peuvent être stockées dans l'objet constructeur de fonction.
abhisekp
1
En fait, ce serait un gâchis car instanceofil en résulterait ({}) instanceof Function === truequ'il n'y aurait aucun moyen de différencier les prototypes si la prototypepropriété était supprimée.
abhisekp
@abhisekp Que voulez-vous dire par ceci: "Cela fonctionnera si f .__ proto__ = g où g est la classe de base." Je ne sais pas si cela a une signification que je ne comprends pas, mais si vous deviez ajouter les propriétés et les méthodes de cette manière, alors lorsque vous utilisiez le newmot - clé pour créer une instance, les propriétés et les méthodes ne seraient pas copiées plus de.
doubleOrt
67

Une belle façon d'y penser est ...

prototypeest utilisé par les constructor()fonctions. Cela aurait vraiment dû être appelé quelque chose comme,"prototypeToInstall" , puisque c'est ce que c'est.

et __proto__est ce "prototype installé" sur un objet (qui a été créé / installé sur l'objet à partir de ladite constructor()fonction)

Sarink
la source
2
Je l'ai voté, mais peut-être que la raison du vote négatif était parce que la déclaration «le prototype est utilisé par les fonctions constructeur ()» peut sembler comme si les fonctions non constructrices n'en avaient pas, ce qui n'est pas le cas, mais en plus, ce n'est pas notre objectif maintenant on peut noter que chaque fonction est potentiellement un constructeur si elle est appelée avec new ...
yoel halb
2
Veuillez changer " constructor()fonctions" en "fonctions constructeur", car il pourrait y avoir confusion avec " __proto__.constructor()fonctions". Je considère cela important, car le constructeur __proto __. N'est pas réellement invoqué lorsqu'un newmot clé est utilisé.
Alexander Gonchiy
1
L'affirmation selon laquelle "le prototype est utilisé par les fonctions constructor () " ne raconte qu'une partie d'un fait important mais le dit d'une manière qui amène probablement les lecteurs à penser que c'est le fait entier. le prototype est créé en interne pour chaque déclaration de fonction en Javascript, quelle que soit la façon dont cette fonction sera appelée à l'avenir - avec ou sans le nouveau mot-clé; prototype d'une fonction déclarée pointe vers un objet littéral.
Yiling
62

Pour expliquer, créons une fonction

 function a (name) {
  this.name = name;
 }

Lorsque JavaScript exécute ce code, il ajoute une prototypepropriété à a, la prototypepropriété est un objet avec deux propriétés:

  1. constructor
  2. __proto__

Alors quand on fait

a.prototype il revient

     constructor: a  // function definition
    __proto__: Object

Maintenant, comme vous pouvez le voir, constructorrien que la fonction aelle-même et __proto__pointe vers le niveau racineObject de JavaScript.

Voyons ce qui se passe lorsque nous utilisons une afonction avec newun mot clé.

var b = new a ('JavaScript');

Lorsque JavaScript exécute ce code, il fait 4 choses:

  1. Il crée un nouvel objet, un objet vide // {}
  2. Elle crée __proto__sur bet fait pointer a.prototypedoncb.__proto__ === a.prototype
  3. Il s'exécute a.prototype.constructor(qui est la définition de la fonction a) avec le nouvel objet créé (créé à l'étape # 1) comme contexte (ceci), d'où la namepropriété passée en tant que 'JavaScript' (qui est ajoutée àthis ) est ajoutée à l'objet nouvellement créé.
  4. Il retourne l'objet nouvellement créé dans (créé à l'étape # 1) afin que var bsoit assigné à l'objet nouvellement créé.

Maintenant, si nous ajoutons a.prototype.car = "BMW"et faisons b.car , la sortie "BMW" apparaît.

cela est dû au fait que lorsque JavaScript a exécuté ce code, il a recherché une carpropriété b, il n'a pas trouvé JavaScript utilisé b.__proto__(qui a été fait pour pointer vers 'a.prototype' à l'étape # 2) et trouve une carpropriété, donc retournez "BMW".

Manishz90
la source
2
1. constructorne revient pas a()! Il revient a. 2. __proto__renvoie Object.prototype, pas l'objet racine en Javascript.
doubleOrt
1
C'est une excellente réponse!
john-raymon
+1 c'est la meilleure réponse pour expliquer quel prototype EST réellement (un objet avec deux propriétés) et comment Javascript exécute chaque morceau de code. Cette information est étonnamment difficile à trouver.
java-addict301
53

Prototype VS. __proto__ VS. [[Prototype]]

Lors de la création d'une fonction, un objet de propriété appelé prototype est créé automatiquement (vous ne l'avez pas créé vous-même) et est attaché à l'objet fonction (le constructor).
Remarque : Ce nouvel objet prototype pointe également vers, ou a un lien interne-privé vers, l'objet JavaScript natif.

Exemple:

function Foo () {
    this.name = 'John Doe';
}

// Foo has an object property called prototype.
// prototype was created automatically when we declared the function Foo.
Foo.hasOwnProperty('prototype'); // true

// Now, we can assign properties and methods to it:
Foo.prototype.myName = function () {
    return 'My name is ' + this.name;
}

Si vous créez un nouvel objet en Fooutilisant le newmot - clé, vous créez essentiellement (entre autres choses) un nouvel objet qui a un lien interne ou privé vers le Fooprototype de la fonction dont nous avons discuté précédemment:

var b = new Foo();

b.[[Prototype]] === Foo.prototype  // true


Le lien privé vers l'objet de cette fonction appelé prototype à double crochets ou simplement [[Prototype]]. De nombreux navigateurs nous fournissent un lien public vers celui-ci qui s'appelle __proto__!

Pour être plus précis, il __proto__s'agit en fait d'une fonction getter qui appartient à l'objet JavaScript natif. Il renvoie le lien prototype interne-privé de la thisliaison (retourne le [[Prototype]]de b):

b.__proto__ === Foo.prototype // true

Il convient de noter qu'à partir de ECMAScript5, vous pouvez également utiliser la méthode getPrototypeOf pour obtenir la liaison privée interne:

Object.getPrototypeOf(b) === b.__proto__ // true


NOTE: cette réponse n'a pas l' intention de couvrir tout le processus de création de nouveaux objets ou de nouveaux constructeurs, mais pour aider à mieux comprendre ce qui est __proto__, prototypeet [[Prototype]]et comment cela fonctionne.

Lior Elrom
la source
2
@Taurus, cliquez sur l'en-tête, cela mène au document de spécifications ECMAScript. Consultez la section 9 (Comportements des objets ordinaires et exotiques) qui l'expliquent plus en détail.
Lior Elrom
Je pense qu'il y a une erreur ici: _ un nouvel objet qui a un lien interne ou privé avec le prototype de la fonction Foo_ Voulez-vous dire: un nouvel objet qui a un lien interne ou privé avec le prototype de la fonction Foo ?
Koray Tugay
1
Merci @KorayTugay! Oui, je l'ai mal orthographié :) +1
Lior Elrom
31

Pour être un peu clair en plus des bonnes réponses ci-dessus:

function Person(name){
    this.name = name
 }; 

var eve = new Person("Eve");

eve.__proto__ == Person.prototype //true

eve.prototype  //undefined

Les instances ont __proto__ , les classes ont un prototype .

serkan
la source
12

En JavaScript, une fonction peut être utilisée comme constructeur. Cela signifie que nous pouvons en créer des objets à l'aide du nouveau mot-clé. Chaque fonction constructeur est livrée avec un objet intégré chaîné avec eux. Cet objet intégré est appelé un prototype.Instances of a constructor function use __proto__ to access the prototype property of its constructor function.

diagramme prototype

  1. Tout d' abord nous avons créé un constructeur: function Foo(){}. Pour être clair, Foo n'est qu'une autre fonction. Mais nous pouvons en créer un objet avec le nouveau mot-clé. C'est pourquoi nous l'appelons la fonction constructeur

  2. Chaque fonction a une propriété unique qui est appelée la propriété prototype. Ainsi, la fonction Constructor Fooa une propriété prototype qui pointe vers son prototype, qui est Foo.prototype(voir image).

  3. Les fonctions de constructeur sont elles-mêmes une fonction qui est une instance d'un constructeur de système appelé le constructeur [[Function]]. On peut donc dire que function Fooc'est construit par un constructeur [[Function]]. Ainsi, __proto__de notre Foo functionvolonté pointera vers le prototype de son constructeur, qui est Function.prototype.

  4. Function.prototypeest lui-même n'est rien d'autre qu'un objet qui est construit à partir d'un autre constructeur de système appelé [[Object]]. Donc, [[Object]]c'est le constructeur de Function.prototype. Donc, nous pouvons dire Function.prototypeest une instance de [[Object]]. Donc __proto__de Function.prototypepoints à Object.prototype.

  5. Object.prototypeest le dernier homme debout dans la chaîne prototype. Je veux dire qu'il n'a pas été construit. C'est déjà là dans le système. Donc, ses __proto__points null.

  6. Nous arrivons maintenant à des exemples de Foo. Lorsque nous créons une instance à l'aide new Foo(), cela crée un nouvel objet qui est une instance de Foo. Cela signifie que Fooc'est le constructeur de ces instances. Ici, nous avons créé deux instances (x et y). __proto__de x et y pointe donc vers Foo.prototype.

AL-zami
la source
Juste pour être clair: les instances n'ont pas de propriété .prototype? Seul le constructeur fonctionne bien? ... Donc une différence entre une instance et sa fonction constructeur est: les fonctions constructeurs ont à la fois 1. proto 2. .prototype object tandis que les instances n'ont que .__ proto__ property ... correct?
Shaz
@Shaz tu as raison. les instances utilisent leur proto pour accéder à la propriété prototype de leur fonction constructeur.
AL-zami
Mais pourquoi pourquoi est-ce quand vous écrivez: var car = Object.create (Vehicle); vous obtiendrez la voiture .__ proto__ = Véhicule MAIS vous obtenez également une propriété car.prototype qui pointe vers Vehicle.prototype?
Shaz
@shaz pouvez-vous fournir un jsfiddle pour que je puisse visualiser la situation?
AL-zami
1
ici car.prototype est une propriété héritée. la voiture hérite de la propriété «prototype» de la fonction du véhicule. donc car.prototype === vehicle.prototype. La propriété "prototype" est une propriété sur un véhicule. la voiture peut y accéder via sa chaîne de prototypes. J'espère que cela clarifiera votre confusion
AL-zami
8

Sommaire:

La __proto__propriété d'un objet est une propriété qui correspond à la prototypefonction constructeur de l'objet. En d'autres termes:

instance.__proto__ === constructor.prototype // true

Ceci est utilisé pour former la prototypechaîne d'un objet. La prototypechaîne est un mécanisme de recherche de propriétés sur un objet. Si la propriété d'un objet est accessible, JavaScript va d'abord regarder l'objet lui-même. Si la propriété n'y est pas trouvée, elle grimpera jusqu'àprotochain ce qu'elle soit trouvée (ou non)

Exemple:

function Person (name, city) {
  this.name = name;
}

Person.prototype.age = 25;

const willem = new Person('Willem');

console.log(willem.__proto__ === Person.prototype); // the __proto__ property on the instance refers to the prototype of the constructor

console.log(willem.age); // 25 doesn't find it at willem object but is present at prototype
console.log(willem.__proto__.age); // now we are directly accessing the prototype of the Person function 

Notre premier journal se traduit par true, car, comme mentionné, la __proto__propriété de l'instance créée par le constructeur fait référence à la propriétéprototype propriété du constructeur. N'oubliez pas qu'en JavaScript, les fonctions sont également des objets. Les objets peuvent avoir des propriétés, et une propriété par défaut de n'importe quelle fonction est une propriété nommée prototype.

Ensuite, lorsque cette fonction est utilisée comme fonction constructeur, l'objet instancié à partir d'elle recevra une propriété appelée __proto__. Et cette __proto__propriété fait référence à la prototypepropriété de la fonction constructeur (qui, par défaut, chaque fonction a).

Pourquoi est-ce utile?

JavaScript possède un mécanisme lors de la recherche de propriétés sur Objectslesquelles est appelé «héritage prototypique» , voici ce qu'il fait essentiellement:

  • Tout d'abord, il est vérifié si la propriété se trouve sur l'objet lui-même. Si c'est le cas, cette propriété est retournée.
  • Si la propriété ne se trouve pas sur l'objet lui-même, il «grimpera sur le protocole». Il examine essentiellement l'objet auquel fait référence la __proto__propriété. Là, il vérifie si la propriété est disponible sur l'objet référencé par __proto__.
  • Si la propriété n'est pas située sur l' __proto__objet, elle grimpera jusqu'à la __proto__chaîne, jusqu'à l' Objectobjet.
  • S'il ne trouve pas la propriété n'importe où sur l'objet et sa prototypechaîne, il reviendra undefined.

Par exemple:

function Person (name) {
  this.name = name;
}

let mySelf = new Person('Willem');

console.log(mySelf.__proto__ === Person.prototype);

console.log(mySelf.__proto__.__proto__ === Object.prototype);

Willem van der Veen
la source
7

Il se trouve que j'apprends un prototype de You Don't Know JS: this & Object Prototypes , qui est un livre merveilleux pour comprendre la conception en dessous et clarifier tant d'idées fausses (c'est pourquoi j'essaie d'éviter d'utiliser l'héritage et des choses comme instanceof).

Mais j'ai la même question que les personnes posées ici. Plusieurs réponses sont vraiment utiles et instructives. J'aimerais aussi partager mes compréhensions.


Qu'est-ce qu'un prototype?

Les objets en JavaScript ont une propriété interne, notée dans la spécification comme [[Prototype]], qui est simplement une référence à un autre objet. Presque tous les objets reçoivent une valeur nonnull valeur pour cette propriété, au moment de leur création.

Comment obtenir le prototype d'un objet?

via __proto__ouObject.getPrototypeOf

var a = { name: "wendi" };
a.__proto__ === Object.prototype // true
Object.getPrototypeOf(a) === Object.prototype // true

function Foo() {};
var b = new Foo();
b.__proto__ === Foo.prototype
b.__proto__.__proto__ === Object.prototype

C'est quoi prototype?

prototypeest un objet créé automatiquement en tant que propriété spéciale d'une fonction , qui est utilisé pour établir la chaîne de délégation (héritage), également appelée chaîne prototype.

Lorsque nous créons une fonction a, elle prototypeest automatiquement créée en tant que propriété spéciale sur aet enregistre le code de fonction en tant que constructoron prototype.

function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true

J'adorerais considérer cette propriété comme l'endroit où stocker les propriétés (y compris les méthodes) d'un objet fonction. C'est aussi la raison pour laquelle les fonctions utilitaires dans JS sont définies comme Array.prototype.forEach(),Function.prototype.bind() ,Object.prototype.toString().

Pourquoi mettre en valeur la propriété d'une fonction ?

{}.prototype // undefined;
(function(){}).prototype // Object {constructor: function}

// The example above shows object does not have the prototype property.
// But we have Object.prototype, which implies an interesting fact that
typeof Object === "function"
var obj = new Object();

Ainsi, Arary, Function, Objectsont toutes les fonctions. Je dois admettre que cela rafraîchit mon impression sur JS. Je sais que les fonctions sont des citoyens de première classe dans JS, mais il semble qu'il soit construit sur des fonctions.

Quelle est la différence entre __proto__etprototype ?

__proto__une référence fonctionne sur chaque objet pour faire référence à son[[Prototype]] propriété.

prototypeest un objet créé automatiquement en tant que propriété spéciale d'une fonction , qui est utilisé pour stocker les propriétés (y compris les méthodes) d'un objet fonction.

Avec ces deux, nous pourrions cartographier mentalement la chaîne prototype. Comme cette image illustre:

function Foo() {}
var b = new Foo();

b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true
ifyouseewendy
la source
7

 Prototype JavaScript vs __prototype__

'use strict'
function A() {}
var a = new A();
class B extends A {}
var b = new B();
console.log('====='); // =====
console.log(B.__proto__ === A); // true
console.log(B.prototype.__proto__ === A.prototype); // true
console.log(b.__proto__ === B.prototype); // true
console.log(a.__proto__ === A.prototype); // true
console.log(A.__proto__ === Function.__proto__); // true
console.log(Object.__proto__ === Function.__proto__); // true
console.log(Object.prototype === Function.__proto__.__proto__); // true
console.log(Object.prototype.__proto__ === null); // true

En JavaScript, chaque objet (la fonction est aussi un objet!) A une __proto__propriété, la propriété fait référence à son prototype.

Lorsque nous utilisons l' newopérateur avec un constructeur pour créer un nouvel objet, la __proto__propriété du nouvel objet sera définie avec la prototypepropriété du constructeur , puis le constructeur sera appelé par le nouvel objet, dans ce processus "ceci" sera une référence au nouvel objet dans la portée du constructeur, retourne finalement le nouvel objet.

Le prototype du constructeur est la __proto__propriété, la prototypepropriété du constructeur est le travail avec l' newopérateur.

Le constructeur doit être une fonction, mais la fonction n'est pas toujours constructeur même si elle a une prototypepropriété.

La chaîne de prototype est en fait la __proto__propriété de l'objet pour référencer son prototype, et la __proto__propriété du prototype pour référencer le prototype du prototype, et ainsi de suite, jusqu'à référencer la __proto__propriété du prototype de l' objet qui fait référence à null.

Par exemple:

console.log(a.constructor === A); // true
// "a" don't have constructor,
// so it reference to A.prototype by its ``__proto__`` property,
// and found constructor is reference to A

[[Prototype]]et la __proto__propriété est en fait la même chose.

Nous pouvons utiliser la méthode getPrototypeOf d'Object pour obtenir le prototype de quelque chose.

console.log(Object.getPrototypeOf(a) === a.__proto__); // true

Toute fonction que nous avons écrite peut être utilisée pour créer un objet avec l' newopérateur, donc n'importe laquelle de ces fonctions peut être un constructeur.

林奕 忠
la source
6

Une autre bonne façon de le comprendre:

var foo = {}

/* 
foo.constructor is Object, so foo.constructor.prototype is actually 
Object.prototype; Object.prototype in return is what foo.__proto__ links to. 
*/
console.log(foo.constructor.prototype === foo.__proto__);
// this proves what the above comment proclaims: Both statements evaluate to true.
console.log(foo.__proto__ === Object.prototype);
console.log(foo.constructor.prototype === Object.prototype);

Ce n'est qu'après IE11 __proto__est pris en charge. Avant cette version, comme IE9, vous pouviez utiliser le constructorpour obtenir le __proto__.

Yad Smood
la source
Seulement que je l'écrirais dans l'autre sens: foo .__ proto__ === foo.constructor.prototype
epeleg
6

prototype

prototype est une propriété d'une fonction. C'est le plan pour créer des objets en utilisant cette fonction (constructeur) avec un nouveau mot-clé.

__proto__est utilisé dans la chaîne de recherche pour résoudre les méthodes et les propriétés. lorsqu'un objet est créé (en utilisant la fonction constructeur avec un nouveau mot-clé), __proto__est défini sur (Constructeur) Function.prototype

function Robot(name) {
    this.name = name;
}
var robot = new Robot();

// the following are true   
robot.__proto__ == Robot.prototype
robot.__proto__.__proto__ == Object.prototype

Voici mon explication (imaginaire) pour effacer la confusion:

Imaginez qu'il existe une classe imaginaire (blueprint / coockie cutter) associée à la fonction. Cette classe imaginaire est utilisée pour instancier des objets. prototypeest le mécanisme d'extention (méthode d'extention en C # ou Swift Extension) pour ajouter des choses à cette classe imaginaire.

function Robot(name) {
    this.name = name;
}

Ce qui précède peut être imaginé comme:

// imaginary class
class Robot extends Object{

    static prototype = Robot.class  
    // Robot.prototype is the way to add things to Robot class
    // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype

    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

} 

Donc,

var robot = new Robot();

robot.__proto__ == Robot.prototype
robot.prototype == undefined
robot.__proto__.__proto__ == Object.prototype

Ajoutons maintenant une méthode au prototypeRobot:

Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y};
// Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)

Ce qui précède peut être imaginé comme une extension de la classe Robot:

// Swift way of extention
extension Robot{
    function move(x, y){    
        Robot.position.x = x; Robot.position.y = y
    }
}

Lequel, à son tour,

// imaginary class
class Robot{

    static prototype = Robot.class // Robot.prototype way to extend Robot class
    var __proto__;

    var name = "";

    // constructor
    function Robot(name) {

        this.__proto__ = prototype;
        prototype = undefined;

        this.name = name;
    }

    // added by prototype (as like C# extension method)
    function move(x, y){ 
        Robot.position.x = x; Robot.position.y = y
    };
}
Hassan Tareq
la source
en pensant toujours à des noms __proto__et à des prototypes plus cohérents . peut-être prototype et héritage?
Dmitry
Je dirais, prototypeet les __proto__deux devraient être évités. Nous avons des cours maintenant et j'aime OOP.
Hassan Tareq
le problème est que la classe est relativement nouvelle et qu'elle n'est pas prise en charge par des moteurs vraiment pratiques comme Microsoft JScript (agréable d'avoir quand on travaille sur C et a besoin d'un moteur de script rapide et sale qui est toujours là), et nashorn javascript (qui vient avec tous de nouvelles installations Java sous jjs et est une bonne façon de mettre Java dans un environnement dynamique pur où vous n'avez pas besoin de recompiler constamment les choses). Le truc, c'est que si la classe était du sucre, ce ne serait pas un problème, mais ce n'est pas le cas, il offre des choses qui sont impossibles sans eux dans les anciennes versions de js. Comme étendre "Function".
Dmitry
Finalement, nous obtiendrons un soutien. Je suis développeur backend, donc je n'ai pas de problèmes, je code rarement en js.
Hassan Tareq
et hériter des membres statiques de manière à ce que l'ajout de nouveaux membres / suppression de membres statiques du parent soit remarqué par l'enfant (ce que je ne peux pas penser à un moyen de faire sur JScript, qui n'offre pas Object.assign / __ proto __ / getPrototypeOf, donc vous devez bricoler avec le prototype Object. root pour le simuler)
Dmitry
4

Pour le dire simplement:

> var a = 1
undefined
> a.__proto__
[Number: 0]
> Number.prototype
[Number: 0]
> Number.prototype === a.__proto__
true

Cela vous permet d'attacher des propriétés à X.prototype APRÈS que les objets de type X aient été instanciés, et ils auront toujours accès à ces nouvelles propriétés via la référence __proto__ que le moteur Javascript utilise pour remonter la chaîne de prototype.

Andreas Bergström
la source
4

Prototype ou Object.prototype est une propriété d'un objet littéral. Il représente l' objet prototype d'objet que vous pouvez remplacer pour ajouter davantage de propriétés ou de méthodes le long de la chaîne du prototype.

__proto__ est une propriété d'accesseur (fonction get et set) qui expose le prototype interne d'un objet par lequel il est accédé.

Références:

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype
  2. http://www.w3schools.com/js/js_object_prototypes.asp

  3. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto

akodevs
la source
Object.prototypen'est pas une propriété d'un objet littéral, essayer d'imprimer des {}.prototyperetours indéfinis; cependant, il est accessible via {}.__proto__, qui revient Object.prototype.
doubleOrt
3

Je sais, je suis en retard mais permettez-moi d'essayer de le simplifier.

Disons qu'il y a une fonction

    function Foo(message){

         this.message = message ; 
     };

     console.log(Foo.prototype);

La fonction Foo aura un objet prototype lié. Ainsi, chaque fois que nous créons une fonction en JavaScript, elle a toujours un objet prototype qui lui est lié.

Maintenant, allons-y et créons deux objets en utilisant la fonction Foo.

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);
  1. Nous avons maintenant deux objets, l'objet a et l'objet b. Les deux sont créés à l'aide du constructeur Foo. Gardez à l'esprit que le constructeur n'est qu'un mot ici.
  2. Les objets a et b ont tous deux une copie de la propriété de message.
  3. Ces deux objets a et b sont liés à l'objet prototype du constructeur Foo.
  4. Sur les objets a et b, nous pouvons accéder au prototype Foo en utilisant la propriété proto dans tous les navigateurs et dans IE, nous pouvons utiliser Object.getPrototypeOf (a) ou Object.getPrototypeOf (b)

Maintenant, Foo.prototype, a. proto , et b. proto all désigne le même objet.

    b.__proto__ === Object.getPrototypeOf(a);
    a.__proto__ ===  Foo.prototype;
    a.constructor.prototype  === a.__proto__;

tout ce qui précède reviendrait vrai.

Comme nous le savons, en JavaScript, les propriétés peuvent être ajoutées dynamiquement. Nous pouvons ajouter une propriété à l'objet

    Foo.prototype.Greet = function(){

         console.log(this.message);
    }
    a.Greet();//a
    b.Greet();//b
    a.constructor.prototype.Greet();//undefined 

Comme vous le voyez, nous avons ajouté la méthode Greet () dans Foo.prototype mais elle est accessible dans a et b ou tout autre objet construit à l'aide de Foo.

Lors de l'exécution de a.Greet (), JavaScript recherchera d'abord Greet dans l'objet a de la liste des propriétés. En ne trouvant pas, il montera en chaîne proto de a. Depuis un. proto et Foo.prototype est le même objet, JavaScript trouvera la méthode Greet () et l'exécutera.

J'espère que maintenant le prototype et le proto sont un peu simplifiés.

Mode débogage
la source
3

Exemple explicatif:

function Dog(){}
Dog.prototype.bark = "woof"

let myPuppie = new Dog()

maintenant, myPupppie a une __proto__propriété qui pointe vers Dog.prototype.

> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}

mais myPuppie n'a PAS de propriété prototype.

> myPuppie.prototype
>> undefined

Ainsi, __proto__de mypuppie est la référence à la propriété .prototype de la fonction constructeur qui a été utilisée pour instancier cet objet (et l'objet myPuppie actuel a une relation "délégués à" à cet __proto__objet), tandis que la propriété .prototype de myPuppie est simplement absente (puisque nous ne l'avons pas réglé).

Bonne explication par MPJ ​​ici: proto vs prototype - Création d'objets en JavaScript

Nitin Jadhav
la source
3

Je me suis fait un petit dessin qui représente l'extrait de code suivant:

var Cat = function() {}
var tom = new Cat()

Comprendre __proto__ et prototype

J'ai une formation OO classique, il était donc utile de représenter la hiérarchie de cette manière. Pour vous aider à lire ce diagramme, traitez les rectangles de l'image comme des objets JavaScript. Et oui, les fonctions sont aussi des objets. ;)

Les objets en JavaScript ont des propriétés et ne __proto__sont que l'un d'entre eux.

L'idée derrière cette propriété est de pointer vers l'objet ancêtre dans la hiérarchie (héritage).

L'objet racine en JavaScript est Object.prototypeet tous les autres objets sont des descendants de celui-ci. La __proto__propriété de l'objet racine est null, qui représente la fin de la chaîne d'héritage.

Vous remarquerez que prototypec'est une propriété des fonctions. Catest une fonction, mais aussi Functionet Objectsont des fonctions (natives). tomn'est pas une fonction, il n'a donc pas cette propriété.

L'idée derrière cette propriété est de pointer vers un objet qui sera utilisé dans la construction, c'est-à-dire lorsque vous appelez l' newopérateur sur cette fonction.

Notez que les objets prototypes (rectangles jaunes) ont une autre propriété appelée constructorqui pointe vers l'objet fonction respectif. Pour des raisons de brièveté, cela n'a pas été illustré.

En effet, lorsque nous créons l' tomobjet avec new Cat(), l'objet créé aura la __proto__propriété définie sur l' prototypeobjet de la fonction constructeur.

Au final, jouons un peu avec ce schéma. Les affirmations suivantes sont vraies:

  • tom.__proto__La propriété pointe vers le même objet que Cat.prototype.

  • Cat.__proto__pointe vers l' Function.prototypeobjet, tout comme Function.__proto__et Object.__proto__faire.

  • Cat.prototype.__proto__et tom.__proto__.__proto__pointez sur le même objet et qui est Object.prototype.

À votre santé!

theshinylight
la source
Très bien expliqué!
StackOverflow UI
@theshinylight, tom.__proto__et Cat.prototypesont strictement égaux, donc, tom.__proto__ === Cat.prototype et Cat.prototype === tom.__proto__sont vrais. Alors, qu'entendez-vous par la flèche sur l'image ??
aXuser264
La flèche noire (si vous vous y référez) n'a pas de signification particulière, autre que la propriété de l'objet. Il en prototypeest de même de la propriété de l' Catobjet (d'après votre question).
theshinylight
2

DÉFINITIONS

(le numéro entre parenthèses () est un «lien» vers le code écrit ci-dessous)

prototype- un objet qui se compose de:
=> fonctions (3) de ce particulier ConstructorFunction.prototype(5) qui sont accessibles par chaque objet (4) créé ou à créer via cette fonction constructeur (1)
=> la fonction constructeur elle-même (1 )
=> __proto__de cet objet particulier (objet prototype)

__proto__(dandor proto?) - un lien ENTRE tout objet (2) créé par une fonction constructeur particulière (1) ET les propriétés de l'objet prototype (5) de ce constructeur QUI permet à chaque objet créé (2) d'avoir accès aux fonctions du prototype et méthodes (4) ( __proto__est par défaut inclus dans chaque objet unique dans JS)

CLARIFICATION DU CODE

1.

    function Person (name, age) {
        this.name = name;
        this.age = age;} 

2.

    var John = new Person(‘John’, 37);
    // John is an object

3.

    Person.prototype.getOlder = function() {
        this.age++;
    }
    // getOlder is a key that has a value of the function

4.

    John.getOlder();

5.

    Person.prototype;
Eduard
la source
1

Je vais essayer une explication de 4e année:

Les choses sont très simples. A prototypeest un exemple de la façon dont quelque chose doit être construit. Donc:

  • Je suis un functionet je construis de nouveaux objets similaires à monprototype

  • Je suis un objectet j'ai été construit en utilisant mon __proto__comme exemple

preuve :

function Foo() { }

var bar = new Foo()

// `bar` is constructed from how Foo knows to construct objects
bar.__proto__ === Foo.prototype // => true

// bar is an instance - it does not know how to create objects
bar.prototype // => undefined
vladCovaliov
la source
1
Non, ni prototypeni ni ne __proto__sont utilisés à tout moment comme modèle ou ainsi pour créer un objet. C'est un mythe introduit par la classsyntaxe floue et ses prédécesseurs. Comme le dit le message de réponse, il est juste utilisé pour la chaîne de recherche et en cas d' prototypeidentification constructorutilisé avec new(qui fait partie de ce mécanisme prétendant être chic qui déroute de nombreux utilisateurs, dont moi).
Christof Kälin
Le premier point devrait être "Je suis une fonction et je construis de nouveaux objets qui se délégueront à mon prototype"
Nitin Jadhav
1

Chaque fonction que vous créez a une propriété appelée prototype, et elle commence sa vie en tant qu'objet vide. Cette propriété n'est d'aucune utilité tant que vous n'utilisez pas cette fonction comme fonction constructeur, c'est-à-dire avec le mot-clé 'new'.

Cela est souvent confondu avec la __proto__propriété d'un objet. Certains peuvent devenir confus et sauf que la prototypepropriété d'un objet peut leur donner le proto d'un objet. Mais ce n'est pas le cas. prototypeest utilisé pour obtenir __proto__un objet créé à partir d'un constructeur de fonction.

Dans l'exemple ci-dessus:

function Person(name){
    this.name = name
}; 

var eve = new Person("Eve");

console.log(eve.__proto__ == Person.prototype) // true
// this is exactly what prototype does, made Person.prototype equal to eve.__proto__

J'espère que ça a du sens.

Malkeet Singh
la source
1
prototypen'est pas utilisé pour créer l' __proto__objet d'un. __proto__, lorsqu'il est accédé, fournit simplement une référence à l' prototypeobjet.
doubleOrt
1

Qu'en est-il de l'utilisation __proto__pour les méthodes statiques?

function Foo(name){
  this.name = name
  Foo.__proto__.collection.push(this)
  Foo.__proto__.count++

}

Foo.__proto__.count=0
Foo.__proto__.collection=[]

var bar = new Foo('bar')
var baz = new Foo('baz')

Foo.count;//2
Foo.collection // [{...}, {...}]
bar.count // undefined
Barrard
la source
C'est exactement pourquoi une réponse à " __proto__VS. prototypeen JavaScript" ?
Andreas
est-ce bon ou qu'en est-il de Foo.collection.push (this) Foo.count ++
Selva Ganapathi
1

(function(){ 
      let a = function(){console.log(this.b)};
      a.prototype.b = 1;
      a.__proto__.b = 2;
      let q = new a();
      console.log(a.b);
      console.log(q.b) 
    })()

Essayez ce code pour comprendre

Timur
la source
1

Un seul objet est utilisé pour le chaînage protypal. Cet objet a évidemment un nom et une valeur: __proto__c'est son nom, et prototypec'est sa valeur. C'est tout.

pour le rendre encore plus facile à saisir, regardez le diagramme en haut de ce post (Diagramme de dmitry soshnikov), vous ne trouverez jamais de __proto__points vers autre chose prototypeque sa valeur.

L'essentiel est le suivant: __proto__c'est le nom qui fait référence à l'objet prototypique, et prototypec'est l'objet prototypique réel.

C'est comme dire:

let x = {name: 'john'};

xest le nom de l'objet (pointeur) et {name: 'john'}l'objet réel (valeur de données).

REMARQUE: ceci est juste un indice massivement simplifié sur la façon dont ils sont liés à un niveau élevé.

Mise à jour: Voici un exemple javascript concret simple pour une meilleure illustration:

let x = new String("testing") // Or any other javascript object you want to create

Object.getPrototypeOf(x) === x.__proto__; // true

Cela signifie que lorsque Object.getPrototypeOf(x)nous obtient la valeur réelle x(qui est son prototype), est exactement ce que __proto__de xpointe. Par conséquent __proto__pointe en effet vers le prototype de x. Ainsi __proto__référence x(pointeur de x), et prototypeest la valeur de x(son prototype).

J'espère que c'est un peu clair maintenant.

Fouad Boukredine
la source
1

Il s'agit d'une question très importante pour tous ceux qui souhaitent comprendre l'héritage prototypique. D'après ce que je comprends, le prototype est attribué par défaut quand un objet est créé avec new à partir d'une fonction car Function a un objet prototype par définition:

function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]

Lorsque nous créons un objet ordinaire sans nouveau, c'est-à-dire explicitement à partir d'une fonction, il n'a pas de prototype mais il a un proto vide auquel on peut attribuer un prototype.

var foo={
  check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); //  TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo

Nous pouvons utiliser Object.create pour lier explicitement un objet.

// we can create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.fooprops= "We checking prototypes";
console.log(bar.__proto__); // "foo"
console.log(bar.fooprops); // "We checking prototypes"
console.log(bar.check); // 10 is delegated to `foo`
tksilicon
la source
0

__proto__est la base à construire prototypeet une fonction constructeur par exemple: function human(){}has prototypequi est partagée via __proto__dans la nouvelle instance de la fonction constructeur. Une lecture plus détaillée ici

Jyoti Duhan
la source
@Derick Daniel: je ne sais pas pourquoi vous avez voté contre, mais la modification que vous avez faite n'était pas celle que j'essayais de transmettre. Modifié plus loin pour plus de dégagement :).
Jyoti Duhan
Jyoti, je n'ai pas voté contre votre réponse, quelqu'un d'autre l'a fait, je l'ai juste éditée :)
Freelancer
0

Comme cela a été dit à juste titre

__proto__est l'objet réel utilisé dans la chaîne de recherche pour résoudre les méthodes, etc. prototype est l'objet utilisé pour créer __proto__lorsque vous créez un objet avec new:

( new Foo ).__proto__ === Foo.prototype;
( new Foo ).prototype === undefined;

Nous pouvons en outre noter que la __proto__propriété d'un objet créé à l'aide du constructeur de fonction pointe vers l'emplacement de mémoire pointé par la propriété prototype de ce constructeur respectif.

Si nous modifions l'emplacement mémoire du prototype de la fonction constructeur, l' __proto__objet dérivé continuera de pointer vers l'espace d'adressage d'origine. Par conséquent, pour rendre la propriété commune disponible dans la chaîne d'héritage, ajoutez toujours la propriété au prototype de fonction constructeur , au lieu de la réinitialiser (ce qui changerait son adresse mémoire).

Prenons l'exemple suivant:

function Human(){
    this.speed = 25;
}

var himansh = new Human();

Human.prototype.showSpeed = function(){
    return this.speed;
}

himansh.__proto__ === Human.prototype;  //true
himansh.showSpeed();    //25

//now re-initialzing the Human.prototype aka changing its memory location
Human.prototype = {lhs: 2, rhs:3}

//himansh.__proto__ will still continue to point towards the same original memory location. 

himansh.__proto__ === Human.prototype;  //false
himansh.showSpeed();    //25
Himansh
la source
-1

ma compréhension est: __proto__ et prototype sont tous servis pour la technique de chaîne de prototype. la différence est que les fonctions nommées avec un trait de soulignement (comme __proto__) ne sont pas du tout destinées aux développeurs invoqués explicitement. en d'autres termes, ils ne sont que pour certains mécanismes comme l'héritage, etc. ils sont «back-end». mais les fonctions nommées sans trait de soulignement sont conçues pour être invoquées explicitement, elles sont «frontales».

Beicai
la source
3
Il y a plus que __proto__et prototypeseulement la convention de dénomination. Ils peuvent ou non pointer vers le même objet. Voir la réponse @zyklus.
demisx
1
@demisx bien sûr, vous avez dit que c'était vrai, mais mon avis est que la différence de nom a exposé le contraste de la fonctionnalité.
Beicai
Il ne suffit pas de dire "selon votre compréhension", surtout lorsque d'autres bonnes réponses ont été fournies auparavant ...
ProfNandaa
-3

!!! C'EST LA MEILLEURE EXPLICATION AU MONDE !!!!!

var q = {}
var prototype = {prop: 11}

q.prop // undefined
q.__proto__ = prototype
q.prop // 11

dans les constructeurs de fonctions, le moteur javascript appelle cela q.__proto__ = prototypeautomatiquement lorsque nous écrivons new Class, et dans l' __proto__ensemble d'accessoiresClass.prototype

function Class(){}
Class.prototype = {prop: 999} // set prototype as we need, before call new

var q = new Class() // q.__proto__ = Class.prototype
q.prop // 999

Prendre plaisir %)

Maxmaxmaximus
la source