为什么在原型中定义的方法会在对象本身中显示?

时间:2016-02-22 12:14:59

标签: javascript prototype

原型继承学习者的标准示例:

function Animal(name) {
    this.name = name;
    this.speed = 0;
}

Animal.prototype.stop = function() {
    this.speed = 0;
};

Animal.prototype.run = function(speed) {
    this.speed += speed;
};

function Rabbit(name) {
    this.name = name;
    this.speed = 0;
}

Rabbit.prototype = Object.create(Animal.prototype);
Rabbit.prototype.constructor = Rabbit;

Rabbit.prototype.jump = function() {
    this.speed++;
};

var rabbit = new Rabbit('Bunny');

查看Google Chrome调试器,我可以看到以下图片: Prototype JS inheritance

令我困惑的是:

  1. Rabbit的原型设置为Animal
  2. jump()方法是在Rabbit的原型上定义的 - 而不是Rabbit本身。
  3. Google Chrome浏览器会在jump()
  4. 中显示Rabbit

    这似乎是合理的,因为我不希望jump()成为Animal的一部分,而是非逻辑的,因为我在jump()的实例上定义了Animal。 是否对prototype属性中的对象有一些特殊处理,例如“设置对象,在原型中定义为__proto__,但是将所有其他方法定义移动到子对象中”?或者我弄错了?

2 个答案:

答案 0 :(得分:1)

回答你的问题:

1)Rabbit的原型设置为Animal:
您可以使用以下代码表明:

Rabbit.prototype = Object.create(Animal.prototype);

Object.create()创建一个新对象,原型作为第一个参数 它用于创建Animal和Rabbit之间的原型链。

2)在Rabbit的原型上定义了jump()方法 - 而不是在Rabbit本身上。

之所以发生这种情况,是因为您将此方法完全添加到原型中,但Rabbit实例上的不是

Rabbit.prototype.jump = function() {
    this.speed++;
};

3)Google Chrome将jump()显示为Rabbit的一部分。
是的,jump()方法是Rabbit的一部分:继承自Rabbit.prototype。

4)这似乎是合理的,因为我不希望jump()成为Animal的一部分,但是非逻辑,因为我在Animal的实例上定义了jump()
你在Animal的一个实例上定义jump()(一个新的实例,因为使用了Object.create(),但仍然保留了Animal原型),这将成为Rabbit的原型。

5)“设置对象,在原型中定义为 proto ,但将所有其他方法定义移动到子对象中”
当实例从原型对象继承属性和方法时,它会在运行时自动发生。

可能令人困惑的一件事是Google控制台显示的原因:__proto__: Rabbit__proto__: Animal。实际上它显示了构造函数名称,它与原型对象链接。

答案 1 :(得分:-1)

你只是使用Rabbit的实例来获取原型 - 但是Animal有一个对同一原型的引用 - 实质上,Rabbit扩展了Animal(反之亦然)。因此,如果您更改Rabbit的原型,您也可以更改Animal的原型。

您可以定义兔子本身的跳跃,而不是原型。或者,您可以将Rabbit的原型设置为新的Animal对象并进行修改。