以下原型继承之间的技术和语义差异是什么?

时间:2014-04-30 03:04:27

标签: javascript

我认识到这是一个重复的问题。我试图得到一个非常狭隘和具体的答案。

使用JavaScript原型继承模式时,我遇到了两个流行的模式。

鉴于

function Animal(type) {
  this.type = type;
}
Animal.prototype.makeNoise = function(noise) {
  console.log('the ' + this.type + ' goes ' + noise);
}

除了样式和最佳实践之外,这两个对象定义之间的技术和语义差异是什么:

function Dog() {
  Animal.call(this, 'dog');
}
Dog.prototype = new Animal();

function Cat() {
  Animal.call(this, 'cat');
}
Cat.prototype = Animal.prototype;

它们似乎都与this jsbin中演示的相同。我能说的最好的是,Cat获得了继承而没有Dog定义执行的额外实例化。可以使用一些见解。

1 个答案:

答案 0 :(得分:4)

在第二个版本中,CatAnimal的原型是共享,这意味着当Cat.prototype更改时,Animal.prototype(和它的所有继承者)也会受到影响。

看看这个例子:

Dog.prototype.bark = function() {
  console.log("Woof!");
};

Cat.prototype.meow = function() {
  console.log("Meow!");
};

'bark' in Animal.prototype; // => false
'bark' in Cat.prototype;    // => false
'meow' in Animal.prototype; // => true - Oops!
'meow' in Dog.prototype;    // => true - Oops!

所以,现在,我们的狗(以及所有其他潜在的动物)都知道如何喵喵叫。

然后,我会说,第一个策略通常更安全,因为它使每个类型的所有者都成为他们的原型。


在旁注中,我建议在为Dog / Cat创建原型时使用Object.create而不是构造函数:

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

这避免了Animal构造函数可能具有的任何不需要的逻辑,同时保留了相同的优点。您还可以直接在Object.create调用上定义其他属性 - 查看我链接到的文档。