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):
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__
.)
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
Alors? qu'attendais-tu? –