5

我正在尝试创建一个Dog通过类的原型继承继承的新Animal类:

function Animal() {
  this.name = "animal";
  this.writeName = function() {
    document.write(this.name);
  }    
}

function Dog() {
  this.name = "dog";
  this.prototype = new Animal();
}

new Dog().writeName()

JS 小提琴

但是,我收到一个 Javascript 错误:Uncaught TypeError: Object #<Dog> has no method 'say'.

为什么?对象不应该Dog保留一个Animal对象作为原型吗?

4

3 回答 3

7
function Animal() {
  this.name = "animal";
  this.writeName = function() {
    document.write(this.name);
  }    
}

function Dog() {
  this.name = "dog";

}
Dog.prototype = new Animal();
dog = new Dog();
dog.writeName();

现在狗具有动物的所有特性。

jsfiddle

于 2012-06-30T01:29:49.760 回答
3

@ryan 的回答当然是正确的,但他并没有真正说出它有什么不同,初学者可能不清楚,所以......

您所犯的错误是将实例this.prototype = new Animal();分配给在当前实例Animal上命名的属性(由 引用),但在此上下文中命名的属性没有什么特别之处。prototypeDog thisprototype

prototype属性仅对函数对象具有魔力。当您SomeFunc使用new SomeFunc()该新对象的内部/隐藏的[[prototype]]创建一个新实例时,指针将引用SomeFunc.prototype. 该prototype名称在任何其他情况下都没有特殊意义。

于 2012-06-30T02:43:03.323 回答
2

“原型”属性只是一个常规属性。处理委托的真正 [[Proto]] 属性是隐藏的,并且在创建对象后无法直接操作(除了一些扩展:在 Firefox 中,它的__proto__属性)。

一个正确的 Javascript 继承示例,在精神上与您正在做的事情相似,将使用 Object.create 创建具有正确 [[Prototype]] 属性的狗:

function Animal() {
  this.name = "animal";
  this.writeName = function() {
    document.write(this.name);
  }    
}

function Dog() {
  var dog = Object.create(new Animal())
  dog.name = "dog";
  return dog;
}

(new Dog()).writeName()

一个更惯用的例子就像 ryan 的答案,虽然我建议使用Object.create而不是new Animal实例化狗原型,并且我会将动物方法放在单独的动物原型中,而不是像你正在做的那样手动将它们附加到构造函数中。

于 2012-06-30T01:29:05.850 回答