929 votes

__proto__ VS. prototype en JavaScript

Cette figure montre à nouveau que chaque objet a un prototype. Constructeur La fonction Foo a également son propre __proto__ qui est Function.prototype, et qui à son tour fait également référence via son __proto__ à la propriété l'objet.prototype. Ainsi, répétons-le, Foo.prototype est juste une propriété explicite de Foo qui fait référence au prototype des objets b et c. propriété de Foo qui fait référence au prototype des objets b et c.

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

Quelles sont les différences entre __proto__ y prototype ?

enter image description here

Ce chiffre est tiré de dmitrysoshnikov.com .

16 votes

5 votes

Je pense que l'approche descendante ou ascendante est une question de préférence. En fait, je préfère cette façon de faire, car je peux suivre le diagramme jusqu'à ce que je trouve l'origine d'un élément.

2 votes

J'aime comment JavaScript utilise l'héritage prototypique pour résoudre y.constructor en y.__proto__.constructor. J'aime aussi la façon dont Object.prototype se trouve au sommet de la chaîne d'héritage prototypique avec Object.prototype.__proto__ défini à null. J'aime aussi la façon dont le diagramme fait une visualisation conceptuelle en trois colonnes de la façon dont le programmeur pense aux objets comme 1. instances, 2. constructeurs, 3. prototypes que les constructeurs associent à ces instances lorsqu'ils sont instanciés via le mot-clé new.

904voto

zyklus Points 31683

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

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

288 votes

Ah ! Alors prototype n'est pas disponible sur les instances elles-mêmes (ou d'autres objets), mais seulement sur les fonctions de construction.

53 votes

@rvighne : prototype est uniquement disponible sur les fonctions puisqu'elles sont dérivées de Function , Function et Object mais pour tout le reste, ce n'est pas le cas. Cependant, __proto__ est disponible partout.

28 votes

Alors __proto__ est l'objet réel qui est sauvegardé et utilisé comme prototype alors que Myconstructure.prototype est juste un plan pour __proto__ qui est en fait l'objet réel sauvegardé et utilisé comme protoype. D'où myobject.prototype ne serait pas une propriété de l'objet réel parce qu'il s'agit juste d'une chose temporaire utilisée par la fonction de construction pour définir ce que l'objet doit faire. myobject.__proto__ devrait ressembler.

405voto

Imp Points 3576

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

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

Vous pouvez trouver instanceof en comparant les relations d'une fonction prototype d'un objet __proto__ 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;

Ici Point est une fonction constructeur, elle construit un objet (structure de données) de manière procédurale. myPoint est un objet construit par Point() donc Point.prototype est enregistré dans myPoint.__proto__ à ce moment-là.

2 votes

De même, si vous modifiez le __proto__ d'un objet, cela change l'objet sur lequel les recherches de prototypes sont effectuées. Par exemple, vous pouvez ajouter un objet de méthodes en tant que propriété de la fonction __proto__ pour avoir une sorte d'objet d'instance appelable.

2 votes

MonPoint.__proto__.constructor.prototype == Point.prototype

0 votes

@kzh lol qui m'a donné un drôle de résultat console.log(obj1.call) // [Function: call] obj1.call() // TypeError : obj1.call n'est pas une fonction. J'ai fait obj.__proto__ = Function.__proto__

149voto

sid_k_reddy Points 221

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

Par exemple :

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

Person.prototype est créée en interne une fois que vous avez déclaré la fonction ci-dessus. De nombreuses propriétés peuvent être ajoutées à la fonction Person.prototype qui sont partagées par 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 convient de noter que Person.prototype est un Object par défaut (il peut être modifié si nécessaire).

Chaque instance créée à l'aide de new Person() a un __proto__ qui pointe vers la propriété Person.prototype . C'est la chaîne que l'on traverse 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 age méthode de Person.prototype como person1.age , person2.age .

Dans l'image ci-dessus de votre question, vous pouvez voir que Foo est un Function Object et donc il a un __proto__ lien vers le Function.prototype qui est à son tour une instance de Object et dispose d'un __proto__ lien vers Object.prototype . Le lien proto se termine ici avec __proto__ dans le Object.prototype pointant vers null .

Tout objet peut avoir accès à toutes les propriétés de sa chaîne de proto liées par __proto__ et constitue 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 la fonction Object.getPrototypeOf(obj) .

Le code ci-dessous pour instanceof opérateur permet de mieux comprendre :

objet instanceof L'opérateur de classe retourne true lorsqu'un objet est une instance d'une Classe, plus précisément si Class.prototype se trouve dans la chaîne proto 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 vrai si l'objet est une instance de Class.

2 votes

Je me demandais pourquoi le prototype créé en interne en premier lieu ? Pourrait-on simplement attribuer des méthodes statiques à l'objet fonction lui-même, par ex. function f(a){this.a = a}; f.increment = function(){return ++this.a} ? Pourquoi cette méthode n'a-t-elle pas été préférée à l'ajout de méthodes à la base de données de l'UE ? prototype objet ? Cela fonctionnera si f.__proto__ = g où g est la classe de base.

0 votes

Peut-être prototype 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.

1 votes

En fait, ce serait un désastre parce que instanceof aurait pour conséquence ({}) instanceof Function === true car il n'y aurait aucun moyen de différencier les prototypes si l'option prototype est supprimée.

79voto

Kabir Sarin Points 2114

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

prototype est utilisé par constructor fonctions. Il aurait vraiment dû s'appeler quelque chose comme , "prototypeToInstall" puisque c'est ce que c'est.

y __proto__ est ce "prototype installé" sur un objet (qui a été créé/installé sur l'objet à partir de la dite constructor() fonction)

4 votes

Je l'ai upvoted, mais peut-être la raison du downvote était parce que la déclaration "prototype est utilisé par les fonctions constructor()" pourrait sonner comme si les fonctions non constructor n'ont pas, ce qui n'est pas le cas, cependant en plus de cela ce n'est pas notre focus maintenant aussi on peut noter que chaque fonction est potentiellement un constructeur si appelé avec new...

2 votes

Veuillez changer " constructor() en "fonctions de constructeur", car il pourrait y avoir confusion avec " __proto__.constructor() fonctions". Je considère que c'est important, car __proto__.constructor n'est pas réellement invoqué lorsqu'une fonction new est utilisé.

1 votes

L'affirmation selon laquelle " Le prototype est utilisé par les fonctions constructor() "Il ne raconte qu'une partie d'un fait important, mais d'une manière qui peut amener les lecteurs à penser qu'il s'agit de l'ensemble du fait. prototype est créé en interne pour chaque déclaration de fonction en Javascript, quelle que soit la manière dont cette fonction sera appelée à l'avenir - avec ou sans l'attribut nouveau mot-clé ; prototype d'une fonction déclarée pointe vers un objet littéral.

-1voto

Yogoo Points 46

Je comprends : __proto__ et prototype servent tous à la technique de la chaîne de prototypes. la différence est que les fonctions nommées avec un soulignement (comme __proto__) ne sont pas du tout destinées à être invoquées explicitement par les développeurs. en d'autres termes, elles sont juste destinées à certains mécanismes comme inherit etc. elles sont 'back-end'. mais les fonctions nommées sans soulignement sont conçues pour être invoquées explicitement, elles sont 'front-end'.

3 votes

Il y en a d'autres à __proto__ y prototype que la simple convention de dénomination. Ils peuvent ou non pointer vers le même objet. Voir la réponse de @zyklus.

1 votes

@demisx bien sûr, vous avez dit est juste, mais mon avis est la différence de nom exposé le contraste de la fonctionnalité.

0 votes

Il ne suffit pas de dire "selon votre compréhension", surtout lorsque d'autres bonnes réponses ont été fournies auparavant...

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