如何调用带参数的继承JavaScript构造函数?

问题描述:

问候,如何调用带参数的继承JavaScript构造函数?

阅读下面的文章后,我有一个问题: https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript

在继承示例中,Person构造函数不带任何参数。如果我要添加一个并从Student构造函数中调用它,那么这个示例看起来如何呢?

谢谢!

好了,一种方式,你可以重新使用Person构造的逻辑与call或调用它例如:apply,例如:

function Person(gender) { 
    this.gender = gender; 
} 

function Student(gender) { 
    Person.apply(this, arguments); 
} 
Student.prototype = new Person(); // make Student inherit from a Person object 
Student.prototype.constructor = Student; // fix constructor property 

var foo = new Student('male'); 
foo.gender;    // "male" 
foo instanceof Student; // true 
foo instanceof Person; // true 

如果你想防止Person构造函数的执行被调用时不带参数(如在线路:Student.prototype = new Person();),你可以检测到它,比如:

​​3210
+1

@CMS对于第二部分'if(arguments.length == 0)return;',是否有办法处理不需要参数的构造函数?在那种情况下,我不得不调用构造函数吗? – 2012-12-13 14:14:06

+0

我尝试了很多不同的方法('Object.create','Person.prototype',temp functions ...),但它们都失败或有错误(未定义的属性,模糊的属性等)。感谢这个答案,最后真的有用! – TheBronx 2013-10-11 09:55:47

// define the Person Class 
function Person(name) { 
    this.personname = name; 
} 

Person.prototype.walk = function(){}; 
Person.prototype.sayHello = function(){ 
    alert (this.personname); 
}; 

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/constructor


的完整代码:

<script> 
// define the Person Class 
function Person(name) { 
    this.personname = name; 
} 

Person.prototype.walk = function(){}; 
Person.prototype.sayHello = function(){ 
    alert (this.personname); 
}; 

// define the Student class 
function Student() {} 

// inherit Person 
Student.prototype = new Person("test"); 

// correct the constructor pointer because it points to Person 
Student.prototype.constructor = Student; 

// replace the sayHello method 
Student.prototype.sayHello = function(){ 
    alert('hi, I am a student and my name is \'' + this.personname + '\''); 
} 

// add sayGoodBye method 
Student.prototype.sayGoodBye = function(){ 
    alert('goodBye'); 
} 

var student1 = new Student(); 
student1.sayHello(); 
student1.sayGoodBye(); 
</script> 
+1

我觉得这工作得很好,如果你总是想“测试”的人的名字,但是这不是我的意思,当我问到从叫它学生构造函数。 – kgarske 2010-08-30 16:10:11

接受的答案似乎是不正确。基于什么Mozilla says about OO JavaScript,正确的方式来做到这一点是:

var Person = function(firstName) { 
    this.firstName = firstName; 
}; 

function Student(firstName, subject) { 
    // Call the parent constructor, making sure (using Function#call) 
    // that "this" is set correctly during the call 
    Person.call(this, firstName); 

    // Initialize our Student-specific properties 
    this.subject = subject; 
}; 

// Create a Student.prototype object that inherits from Person.prototype. 
// Note: A common error here is to use "new Person()" to create the 
// Student.prototype. That's incorrect for several reasons, not least 
// that we don't have anything to give Person for the "firstName" 
// argument. The correct place to call Person is above, where we call 
// it from Student. 
Student.prototype = Object.create(Person.prototype); // See note below 

// Set the "constructor" property to refer to Student 
Student.prototype.constructor = Student; 

// Example usage: 
var student1 = new Student("Janet", "Applied Physics"); 

正如你可以清楚地看到,Mozilla的规定,它是用“新的Person()”创建Student.prototype一个常见的错误。因此,接受的答案是误导性的。

我已经在我正在进行的项目中对此进行了实际测试,Mozilla的方式正确,但以上答案无效。

通过所有其他评论,我创建了一个适用于我的示例。由于我没有明确使用原型,我希望我不会错过重要的一点。

// variable for tracking instantiations and checking the uniqueness of the objects 
var instances = 0; 

var Generic = function() { 
    this.instanceId = ++instances; 
    this.toString = function() {return 'Generic [iid='+ this.instanceId +']'}; 
    console.log('constructor-invoke: Generic ('+ this.instanceId +')'); 
}; 

var SpecificName = function(inName) { 
    Generic.call(this); 
    this.getName = function() { return inName; };  
    var superToString = this.toString.bind(this); // binds the inner function 'this' to this SpecificName instance 
    this.toString = function() { 
     return 'SpecificName [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']' 
    } 
    console.log('constructor-invoke: SpecificName ('+ this.instanceId +')'); 
}; 

var SpecificNames = function(inFirstName, inLastName) { 
    SpecificName.call(this, inLastName +', '+ inFirstName); 
    var superToString = this.toString.bind(this); 
    this.toString = function() { 
     return 'SpecificNames [iid='+ this.instanceId +', name='+ this.getName() +', super.toString='+ superToString() +']' 
    } 
    console.log('constructor-invoke: SpecificNames ('+ this.instanceId +')'); 
}; 

var g = new Generic(); 
var sn = new SpecificName('Run Forest Run'); 
var sns = new SpecificNames('Forest','Gump'); 

console.log('g: '+ g.toString()); 
console.log('sn: '+ sn.toString()); 
console.log('sns: '+ sns.toString()); 

导致这个输出:

constructor-invoke: Generic (1) 
constructor-invoke: Generic (2) 
constructor-invoke: SpecificName (2) 
constructor-invoke: Generic (3) 
constructor-invoke: SpecificName (3) 
constructor-invoke: SpecificNames (3) 
g: Generic [iid=1] 
sn: SpecificName [iid=2, name=Run Forest Run, super.toString=Generic [iid=2]] 
sns: SpecificNames [iid=3, name=Gump, Forest, super.toString=SpecificName [iid=3, name=Gump, Forest, super.toString=Generic [iid=3]]]