继承:构造函数没有运行"super"?

4

我使用JS几个月后遇到了这种情况。由于我的Java背景,我创建一个类并制作子类。

调用子类的构造函数不会调用父类的构造函数。好吧,我读过这种行为,似乎很正常,对吗?

请查看此jsfiddle示例以帮助我澄清:example

因此,为了使子类构造函数运行其每个父类构造函数,我添加了以下内容(请参见jsfiddle示例example

好吧,这样似乎更好了。现在,我想知道以下内容;有没有一种方法可以指定超类而不触发它的构造函数?

例如,以下内容运行Node()方法:

GameObject.prototype = new Node();
GameObject.prototype.constructor=GameObject;

(请参见更新的jsfiddle示例

我感觉我做错了什么。因为我的真实模型跨越7个子类,所以我的构造函数总共有21个调用(6 + 5 + 4 + 3 + 2 + 1 = 21)。

我是否做错了什么?谢谢你的时间!

4个回答

2

你并没有做错什么,这是你的代码预期的行为。然而,你可以使用类似于John Resig在"Simple JavaScript Inheritence"中描述的方法。另一个类似方法的讨论可以在stackoverflow上找到


调用父类的构造函数来设置继承是错误的。 - Ruan Mendes

1

我的理解是JavaScript并没有像C++、Java和C#等传统语言那样原生地实现类。我认为,您可以通过使用强制实施您在Java等语言中习惯的行为的JavaScript框架来获得所需的行为。

Moo Tools就是这样一个框架:http://mootools.net


1

一般来说,你做得很好。但是你的构造函数在其实例上创建属性,并且这些属性被分配给继承构造函数的原型。

例如,Subclass.prototype.animations 在原型上,由 Subclass 的所有后续实例共享。从你的代码中看,似乎你打算为每个实例创建这些 animations

如何解决这个问题?根本不要使用构造函数。使用对象字面量和 Object.create

var Node = {
    init: function () { this.animations = []; },
    doSomething: function () { console.log(this.animations); }
};

var GameObject = Object.create(Node);
GameObject.doSomethingElse = function () { this.init(); this.doSomething(); }

实例化时与继承相同

var gameObj = Object.create(GameObject);
gameObj.doSomethingElse();

应该不会比那更困难。

请参见将继承与模块模式结合使用


嘿,那听起来很不错,我喜欢这个单独拥有“init”方法的想法。谢谢! - Jem
那么...就不使用构造函数吗?这不是解决问题的好方法。正确的方法是使用一种不涉及调用父类构造函数来设置继承的不同技术。http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html - Ruan Mendes
此外,this.animations 没有设置在原型上,而是在对象本身上完成的。写操作始终在对象上进行,而不在原型上(除非您使用 Constructor.prototype.animations = [])。最后,建议使用 [] 是可以的,但更好的建议是使用 {},因为 OP 没有将其用作数组,而实际上是一个映射。 - Ruan Mendes
@JuanMendes,当他执行Redhead.prototype = new GameObject();时,animations成为Redhead原型的一个属性。我会编辑我的答案来表达我对构造函数(缺失)的看法。 - katspaugh
@Katspaugh 我明白了,它在原型上是因为它调用构造函数来设置继承,并且父类的实例就是附加到原型上的。抱歉,我应该意识到这一点... - Ruan Mendes
@JuanMendes,没问题。我也明白你所说的临时构造函数技术。可能会有用! - katspaugh

1

你不需要调用父类的构造函数来设置继承链。请参见http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

以下是错误的,它运行父类的构造函数只是为了设置原型链。

GameObject.prototype = new Node();
GameObject.prototype.constructor = GameObject;

更好的方法是使用代理构造函数,它可以在不实例化“超类”的情况下附加原型。
// Surrogate constructor
var TempCtor = function(){};
TempCtor.prototype = Node.prototype;
// Setup the prototype chain without side effects
GameObject.prototype = new tempCtor();
GameObject.prototype.constructor=GameObject;

你需要确保在子类中调用父构造函数。
function GameObject() {
    // Call the parent's constructor
    Node.call(this);
}

我已经更新了你的jsfiddle,提供了一个示例,展示了正确设置继承的方法http://jsfiddle.net/2caTD/5/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接