我认识到这是一个重复的问题。我试图得到一个非常狭隘和具体的答案。
使用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定义执行的额外实例化。可以使用一些见解。
答案 0 :(得分:4)
在第二个版本中,Cat
和Animal
的原型是共享,这意味着当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
调用上定义其他属性 - 查看我链接到的文档。