2013-03-11 2 views
1

ne comprend pas:prototype

function Rabbit() { } 
Rabbit.prototype = { eats: true }; 
var rabbit = new Rabbit(); 
Rabbit.prototype = {}; 
alert(rabbit.eats); //true 

Et

function Rabbit() { } 
Rabbit.prototype = { eats: true }; 
var rabbit = new Rabbit(); 
Rabbit.prototype.eats = false; 
alert(rabbit.eats); // false 

Pourquoi?
Merci à tous pour votre aide, je comprends après: "Dans votre premier exemple, vous changez le prototype de Lapin pour qu'il pointe vers un objet complètement différent, alors maintenant Rabbit.prototype et le lapin. [[Proto]] ne pointent plus vers le même objet "(c) TJ Crowder

+2

Alors? qu'attendais-tu? –

Répondre

2

Parce que le prototype derrière l'instance rabbit est affecté (de Rabbit.prototype) lors de sa création par new Rabbit, et dans le premier exemple, vous remplacerRabbit.prototype avec un objet entièrement nouveau, qui n'a pas d'effet sur l'instance rabbit. Dans le deuxième exemple, vous modifiez l'objet existant, que Rabbit.prototype et le prototype derrière rabbit pointent vers, donc comme ils pointent vers le même objet, vous voyez le changement indépendamment de la référence que vous suivez.

Soit à pied par var rabbit = new Rabbit(); (en laissant quelques détails non pertinents):

  1. Un nouveau objet vide est créé. Le prototype sous-jacent, habituellement appelé [[Proto]], est défini sur Rabbit.prototype. (Je dis "habituellement appelé" parce que c'est ce que la spécification appelle.) Vous ne pouvez pas y accéder directement par ce nom Vous pouvez trouver ce que c'est pour un objet donné, cependant, dans un environnement ES5 via Object.getPrototypeOf. Les moteurs JavaScript le rendent également disponible via une propriété non standard actuellement appelée [dans le code] __proto__.)

  2. Ce nouvel objet est renvoyé et affecté à rabbit.

Maintenant, nous avons deux objets pointant vers l'objet prototype: Rabbit.prototype et rabbit.[[Proto]].

Dans votre premier exemple, vous modifiez Rabbit.prototype pour pointer vers un objet entièrement différent, différent. Alors maintenant Rabbit.prototype et rabbit.[[Proto]] ne pointent plus vers le même objet.

Dans votre deuxième exemple, vous modifiez simplement la valeur de la propriété eats de cet objet partagé, si naturellement que la modification est visible quelle que soit la référence à l'objet que vous suivez.

Il est essentiellement la même chose que ceci:

var a = {eats: true}; 
var b = a; 
a = {eats: false}; 
console.log(a.eats); // false 
console.log(b.eats); // true 

et

var a = {eats: true}; 
var b = a; 
a.eats = false; 
console.log(a.eats); // false 
console.log(b.eats); // false 
+0

Donc, en gros, même si le prototype est assigné à '.prototype' dans l'objet' rabbit', l'objet obtient ses propriétés de [[[proto]] '? Quel est le point de '.prototype' alors? – freakish

+0

@freakish: 'Rabbit.prototype' est juste une propriété sur l'objet fonction' Rabbit'. Ce n'est pas spécial, sauf que cette propriété est * utilisée * par l'expression 'new Rabbit'. Il n'y a aucun lien durable entre la propriété 'Rabbit.prototype' et la propriété' [[Proto]] 'sur' rabbit'. Ils arrivent juste (initialement) à pointer vers le même objet. –

+0

Oh, désolé, c'était un peu déroutant pour moi. Maintenant c'est clair, merci. :) – freakish

0

Dans le premier cas, l'objet construit reste lié à l'objet prototype d'origine, qui a bien sûr la propriété "eat". Dans le second cas, vous n'introduisez pas de nouveau prototype, donc la modification de la valeur de sa propriété "eats" est visible via l'instance.

1
Rabbit.prototype = { eats: true }; 

équivaut à

Rabbit.prototype = {}; 
Rabbit.prototype.eats = true; 

Et

Rabbit.prototype.eats = false; 

rend juste Rabbit.prototype.eatsfalse (annulant ainsi l'assignation précédente).

Et comme le moteur js, en cherchant une propriété, cherche celui de son prototype (et ainsi de suite) s'il ne le trouve pas localement, il fait Rabbit.eats évaluer à faux.

Questions connexes