JavaScript类继承无限循环

JavaScript类继承无限循环,javascript,Javascript,我有以下资料: function Person() { console.log('person'); } function Player() { this.personConstructor(); } Player.prototype = Person.prototype; Player.prototype.constructor = Player; Player.prototype.personConstructor = Person.prototype.constructor;

我有以下资料:

function Person() {
  console.log('person');
}

function Player() {
  this.personConstructor();
}

Player.prototype = Person.prototype;
Player.prototype.constructor = Player;
Player.prototype.personConstructor = Person.prototype.constructor;

new Player();

其目的是从
Person
继承到
Player
中,然后让新的子类调用父类的原始构造函数。但是,这会导致无限循环。我做错了什么?为什么会发生循环?

这一行就是你的问题:

Player.prototype = Person.prototype;
您希望
Player
的原型继承自
Person
的原型,但使它们相等。目前,您的代码使
Player
Person
原型引用相等,因此对
Player.prototype
的任何更改也会影响
Person.prototype
(有效地使它们无法区分)

您正在寻找:

Player.prototype = Object.create(Person.prototype);
使用给定原型实例化新对象,而不实际调用构造函数(与常规的
newperson()
调用不同)。这允许您获得继承
Person
原型的新对象,然后您可以根据
播放器的具体情况对其进行修改

编辑:正如Siddarth在评论中建议的那样,更好的解决方案是通过以下方式设置
构造函数

这样,新创建的原型将使其
构造函数
属性变得不可配置、不可枚举和不可写。这可以防止您在以后通过赋值(例如
Player.prototype.constructor=Foo
)意外更改它,并且它不会显示在
对象.keys
for.
循环中。通常情况下,这并不重要,但这是一个很好的做法

function Person(args) {
  console.log('person');
  args=args||{};
  this.name=args.name||"no name";
}

function Player(args) {
//  this.personConstructor();
// I prefer 
  Person.call(this,args);
}

Player.prototype = Object.create(Person.prototype);
Player.prototype.constructor = Player;

console.log(new Player());
console.log(new Player({name:"Jon"}));
最好是将父构造函数与以下内容一起重用

Person.call(this,args);
因为如果你使用类似于
this.parent()…
的东西,当你继承3层时,你会得到一个无限循环


更多关于原型和构造函数的信息。

Player.prototype=Person.prototype应该是
Player.prototype=Object.create(Person.prototype)…这是因为当您将
Player.prototype
作为对
Person.prototype
的引用,然后将
Player
分配给
Player.prototype.constructor
时,实际上是将其分配给了
Person.prototype.constructor
。因此,
personConstructor
实际上是对
Player
的引用,而不是
Person
,因此创建了无限调用循环。
this.personConstructor()
工作正常,不需要
。如果要传递相同的
this
,则调用
。然而,
Person.call(this,args)
确实是一个更通用的解决方案,它不需要额外的
Player.prototype.personConstructor
定义。@MattiasBuelens正确,我更改了答案。我将创建该对象。创建(Person.prototype,{constructor:{value:Player}}),别忘了在子构造函数中调用父构造函数。@Siddharth哦,对了,您可以将一组属性描述符传递给
对象。创建
。我个人更喜欢使用经典赋值或类似于
.extend
的方法来向原型添加属性。虽然属性描述符可能更好,但您的解决方案可以防止原型的
构造函数
稍后(意外)被更改。谢谢你的提示!
Person.call(this,args);