2010-08-30 20 views

Odpowiedz

38

Cóż, to sposób, który można ponownie użyć logiki konstruktora Person powołuje go call lub apply, na przykład:

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 

Jeśli chcesz uniemożliwić wykonanie konstruktora Person gdy jest wywołana bez argumentów (jak w wierszu: Student.prototype = new Person();), można wykryć go, np:

function Person(gender) { 
    if (arguments.length == 0) return; // don't do anything 
    this.gender = gender; 
} 
+1

@CMS Dla drugiej części 'if (arguments.length == 0) return;', czy istnieje sposób obsługi konstruktorów, gdzie argumenty NIE są wymagane? W takiej sytuacji jestem zmuszony zadzwonić do konstruktora? –

+0

Próbowałem wiele różnych metod ('Object.create',' Person.prototype', funkcje temp ...), ale wszystkie z nich zawiodły lub mają błędy (niezdefiniowane właściwości, ukryte itp.). Dzięki za tę odpowiedź, w końcu taki, który naprawdę działa! – TheBronx

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


pełny kod:

<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

myślę, że to działa dobrze, jeśli chcesz zawsze „test” jak nazwa osoby, ale to nie jest to, co mam na myśli, gdy pytam nazywać go z Student konstruktor. – kgarske

9

Akceptowane odpowiedź wydaje się być niepoprawny . Na podstawie tego co Mozilla says about OO JavaScript, prawidłowy sposób, aby zrobić to:

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"); 

Jak można wyraźnie zobaczyć, Mozilla określa, że ​​jest to częsty błąd w obsłudze „new Person()”, aby utworzyć Student.prototype. Dlatego przyjęta odpowiedź jest myląca.

Rzeczywiście przetestowałem to w moim bieżącym projekcie i sposób Mozilli jest poprawny, podczas gdy powyższa odpowiedź nie działa.

0

We wszystkich innych komentarzach stworzyłem przykład, który działa dla mnie. Ponieważ nie wykorzystałem jawnie prototypu, mam nadzieję, że nie brakuje mi ważnej kwestii.

// 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()); 

prowadzi do tego wyjścia:

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]]] 
Powiązane problemy