如何调用带参数的继承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();
),你可以检测到它,比如:
// 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>
我觉得这工作得很好,如果你总是想“测试”的人的名字,但是这不是我的意思,当我问到从叫它学生构造函数。 – 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]]]
@CMS对于第二部分'if(arguments.length == 0)return;',是否有办法处理不需要参数的构造函数?在那种情况下,我不得不调用构造函数吗? – 2012-12-13 14:14:06
我尝试了很多不同的方法('Object.create','Person.prototype',temp functions ...),但它们都失败或有错误(未定义的属性,模糊的属性等)。感谢这个答案,最后真的有用! – TheBronx 2013-10-11 09:55:47