因为实例背后的原型是在通过创建时rabbit
分配的(从Rabbit.prototype
)new Rabbit
,并且在第一个示例中,您替换 Rabbit.prototype
为一个全新的对象,这对rabbit
实例没有影响。在第二个示例中,您只需修改现有对象,它Rabbit.prototype
和后面的原型rabbit
都指向,因此由于它们指向同一个对象,因此无论您遵循哪个引用,您都会看到更改。
让我们来看看var rabbit = new Rabbit();
(省略一些不相关的细节):
创建了一个新的空白对象。
它的底层原型,通常称为[[Proto]]
,设置为Rabbit.prototype
。Object.getPrototypeOf
(我说“通常称为”是因为规范是这样称呼它的。你不能直接用那个名字来访问它。不过,你可以在支持 ES5 的环境中通过 .Some JavaScript找出给定对象的含义。引擎还通过实际上称为 [in code] 的非标准属性使其可用__proto__
。)
该新对象被返回并分配给rabbit
.
现在,我们有两个对象指向原型对象:Rabbit.prototype
和rabbit.[[Proto]]
。
在您的第一个示例中,您更改Rabbit.prototype
为指向一个全新的、不同的对象。所以现在Rabbit.prototype
和rabbit.[[Proto]]
不再指向同一个对象。
在您的第二个示例中,您只需更改该共享对象的eats
属性的值,因此无论您遵循哪个对对象的引用,该更改自然是可见的。
基本上和这个是一样的:
var a = {eats: true};
var b = a;
a = {eats: false};
console.log(a.eats); // false
console.log(b.eats); // true
和
var a = {eats: true};
var b = a;
a.eats = false;
console.log(a.eats); // false
console.log(b.eats); // false