如何在JavaScript中按顺序调用祖先构造函数?

时间:2016-08-11 20:41:11

标签: javascript oop constructor

我正在尝试用Javascript学习OOP,到目前为止我的主要灵感来自以下网站:http://phrogz.net/js/classes/OOPinJS2.html

我面临的问题是我有一个类,它有一个父类,它又有一个父类,而且我无法找到一种聪明的方法来通过构造函数链传递参数到顶级父母。

我能够将它传递到一个级别,但随后我的代码将进入无限递归循环。

以下代码概述了问题:

// Define inheritance function:

Function.prototype.inheritsFrom = function( parentClassOrObject ){   
  this.prototype = new parentClassOrObject;
  this.prototype.constructor = this;
  this.prototype.parent = parentClassOrObject.prototype;  
} 

// Define objects (classes) and inheritance structure:

function Human(name){
  this.name         = name;
}

function Criminal(name,crime){
  this.parent.constructor.call(this, name);
  this.crime        = crime;  
}
Criminal.inheritsFrom(Human); 

function Prisoner(name,crime,centence){
  this.parent.constructor.call(this, name, crime);
  this.centence     = centence;
}
Prisoner.inheritsFrom(Criminal); 

// Create instances:

h  = new Human('Anne')               // > Human {name: "Anne"}    
c  = new Criminal('Jack','theft')    // > Criminal {name: "Jack", crime: "theft"}    
p  = new Prisoner('Jon','murder',21) // > Error

// > Error description: Uncaught RangeError: Maximum call stack size exceeded(…)

显然,囚犯成功地调用了父构造函数,即犯罪构造函数。但是当犯罪构造函数调用父构造函数然后"这个"仍然引用相同的Prisoner对象,因此父构造函数再次调用将是Criminal构造函数(而不是预期的Human构造函数),因此形成无限递归循环。

是否有一种简单(最好是性感)的方式来解决问题?或者可能是实现继承的更好方法?

1 个答案:

答案 0 :(得分:0)

根据@SLaks的帖子和Sebastian Porto的优秀plain-English guide to Javascript prototypes,我设置了下面草拟的解决方案。

如果此解决方案中缺少任何内容,请告知我们。 :)

理想情况下,我认为如果可以在构造函数中设置继承会很好,但这似乎不可行......所以这个解决方案似乎和它一样好。 :)

inherits = function(child, parent) {
  child.parent       = parent;
  child.prototype    = Object.create(parent.prototype, {
    constructor: {
      value: child, 
      enumerable: false,
      writable: true,
      configurable: true
    }
  });  
  console.log('Inheritance set: ' + child.name + '.parent = ' + parent.name);  
};

function Human(name){
  this.name         = name;  
}

function Criminal(name,crime){
  Human.call(this, name);
  this.crime        = crime;
}inherits(Criminal,Human);  

function Prisoner(name,crime,centence){  
  Criminal.call(this, name, crime);
  this.centence     = centence;
}inherits(Prisoner,Criminal);

h  = new Human('Anne')                   // > Human {name: "Anne"}
c  = new Criminal('Jack','theft')        // > Criminal {name: "Jack", crime: "theft"}
p1 = new Prisoner('John','murder',21);   // > Prisoner successfully created!
p2 = new Prisoner('Peter','robbery',7);  // > Prisoner successfully created!