閱讀下面的文章後,我有一個問題: https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
在繼承示例中,Person構造函數不帶任何參數。如果我要添加一個並從Student構造函數中調用它,那麼這個示例看起來如何呢?
謝謝!
閱讀下面的文章後,我有一個問題: 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