1

不能理解:

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

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

为什么?
感谢大家的帮助,我在“在您的第一个示例中,您将 Rabbit.prototype 更改为指向一个全新的、不同的对象。所以现在 Rabbit.prototype 和 rabbit.[[Proto]] 不再指向同一个对象”(c)TJ克劳德

4

3 回答 3

2

因为实例背后的原型是在通过创建时rabbit分配的(从Rabbit.prototypenew Rabbit,并且在第一个示例中,您替换 Rabbit.prototype为一个全新的对象,这对rabbit实例没有影响。在第二个示例中,您只需修改现有对象,它Rabbit.prototype和后面的原型rabbit都指向,因此由于它们指向同一个对象,因此无论您遵循哪个引用,您都会看到更改。

让我们来看看var rabbit = new Rabbit();(省略一些不相关的细节):

  1. 创建了一个新的空白对象。

  2. 它的底层原型,通常称为[[Proto]],设置为Rabbit.prototypeObject.getPrototypeOf(我说“通常称为”是因为规范是这样称呼它的。你不能直接用那个名字来访问它。不过,你可以在支持 ES5 的环境中通过 .Some JavaScript找出给定对象的含义。引擎还通过实际上称为 [in code] 的非标准属性使其可用__proto__。)

  3. 该新对象被返回并分配给rabbit.

现在,我们有两个对象指向原型对象:Rabbit.prototyperabbit.[[Proto]]

在您的第一个示例中,您更改Rabbit.prototype为指向一个全新的、不同的对象。所以现在Rabbit.prototyperabbit.[[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
于 2013-03-11T15:04:24.227 回答
1
Rabbit.prototype = { eats: true };

相当于

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

Rabbit.prototype.eats = false;

只是使Rabbit.prototype.eats false(从而使先前的分配无效)。

并且作为 js 引擎,在寻找一个属性时,如果它在本地找不到它,它会寻找它的原型之一(等等),它会使Rabbit.eats评估为 false。

于 2013-03-11T15:05:40.420 回答
0

在第一种情况下,构造的对象仍然链接到原始原型对象,当然它仍然具有“eats”属性。

在第二种情况下,您没有引入新原型,因此通过实例可以看到更改其“eats”属性的值。

于 2013-03-11T15:04:14.727 回答