【问题标题】:Trying to understand inheritance in JavaScript -- what's going on here?试图理解 JavaScript 中的继承——这是怎么回事?
【发布时间】:2013-04-27 02:53:51
【问题描述】:

为什么这里说“动物”而不是“小猫”?

// create base class Animal
function Animal(animalType) {
    this.type = animalType;
    this.sayType = function () {
        alert(this.type);
    };
}

// create derived class Cat
function Cat(myName) {
    Animal.call(this, "cat"); // cat calls the Animal base class constructor

    this.name = myName;

    this.sayName = function () {
        alert(this.name);
    };
}

Cat.prototype = Object.create(Animal); // set Cat's prototype to Animal

// instantiate a new instance of Cat
var cat = new Cat("kitty");

cat.sayName();
cat.name = "lol";
cat.sayName();

http://jsfiddle.net/dgcoffman/MguUA/5/

【问题讨论】:

  • 您的sayType 和sayName 函数实际上并未使用原型继承因为它们不在原型上!您已将它们创建为实例本地属性。

标签: javascript inheritance prototype


【解决方案1】:
Object.create(Animal); // set Cat's prototype to Animal

是的,但是对于 Animal 构造函数(或者,准确地说:对于从该函数对象继承的新对象 - 检查 docs for Object.create)。这几乎不是你想要的 - 并解释了你说 "Animal" 的奇怪结果,因为那是 Animal function's name property。

相反,您想构建一个原型链,以便 cat 实例继承自 Cat.prototype,而 Cat.prototype 继承自 Animal.prototype(继承自 Object.prototype):

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

此外,对于原型继承,您应该在原型对象上使用 sayName 和 sayType 方法(并且仅一次):

Animal.prototype.sayType = function() {
    alert(this.type);
};
Cat.prototype.sayName = function() { // after creation of that object, of course
    alert(this.name);
};

【讨论】:

  • 好吧,我承认也许这就是他想要做的;因为根本没有提到动物原型,所以我没有想到。然而,这是一种可能。
  • 感谢您的回复。当我这样做时,我得到 Uncaught TypeError: Object # has no method 'sayName' jsfiddle.net/dgcoffman/MguUA/7 Nevermind,我在添加 sayName 函数后覆盖了 Cat 的原型,修复:jsfiddle.net/dgcoffman/MguUA/8
【解决方案2】:

你打电话给Object.create() 的方式与我打赌你认为的不同。试试这个改变:

Cat.prototype = Object.create(new Animal);

Object.create() 函数期望它的第一个参数是 object 用作返回对象的原型。当您传入函数名称“Animal”时,这意味着您希望原型对象是该函数对象,而不是函数构造的对象。

edit — Bergi 的回答涉及直接使用 Animal 原型可能更有意义,尽管从您发布的内容来看,并没有包含任何有趣的 Animal 原型对象。也许这在您的代码中的其他地方,或者稍后会添加。无论如何,如果它确实存在,最好按照他的回答做。

由于您的“Cat”构造函数直接从 Animal 构造函数中获取“sayType”属性,因此不清楚您要通过设置 Cat 原型来做什么。

【讨论】:

  • @Bergi 嗯?你让我在这里发疯:-)这让小提琴像我认为它应该工作的那样工作,但我承认我不确定为什么用“kitty”覆盖“name”不起作用。这也令人困惑,因为在“Cat”构造函数中设置原型是愚蠢的.call()。
  • 我比这里 99% 的人更了解 JS,但原型继承仍然让我很困惑:(
  • @Alnitak 哈哈,我知道;我发现除了一些简单的类型之外,我几乎从不使用继承。
  • 这使原型链加倍:-) stackoverflow.com/q/12592913/1048572 (很抱歉把你误认为@PointedEars :-)
  • 是的,总是从原型继承,而不是从实例。
猜你喜欢
  • 1970-01-01
  • 2011-08-25
  • 1970-01-01
  • 1970-01-01
  • 2017-07-20
  • 1970-01-01
  • 2018-10-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多