2010-08-30 118 views

回答

38

好了,一種方式,你可以重新使用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

0
// 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

9

接受的答案似乎是不正確。基於什麼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的方式正確,但以上答案無效。

0

通過所有其他評論,我創建了一個適用於我的示例。由於我沒有明確使用原型,我希望我不會錯過重要的一點。

// 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]]]