2013-04-05 15 views
6

Sto studiando il concetto di ereditarietà in Javascript, e il tutorial sto guardando usa questo codice:Inheritance entro Javascript

// define the Student class 
function Student() { 
    // Call the parent constructor 
    Person.call(this); 
} 

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

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

La mia domanda è, perché è necessario sia per chiamare il costruttore genitore , Person.call(this) e impostare il prototipo Student uguale a un nuovo oggetto Person (ad esempio Student.prototype = new Person();)?

+0

http://stackoverflow.com/questions/892595/javascript-prototypal-inheritance?rq=1 –

risposta

5

Ci sono due problemi separati da affrontare.

Il primo è assicurarsi che i nuovi oggetti Student ereditino dagli oggetti Person. Ecco perché fai Student.prototype = new Person(). Ciò rende uno Student oggetti Student e erediterà ciò che quell'oggetto eredita (da Person.prototype).

Il secondo consiste nell'applicare qualsiasi comportamento nel costruttore Person a qualsiasi nuovo oggetto Student. Ecco perché fai Person.call(this). Questo non è tecnicamente necessario se il costruttore Person non ha alcun codice che modifica il nuovo oggetto, ma è comunque una buona idea farlo nel caso in cui si aggiunga del codice a Person in seguito.


Nota a margine, quando si imposta l'eredità, è meglio fare:

Student.prototype = Object.create(Person.prototype) 

... e lo spessore Object.create se necessario. In questo modo non è effettivamente necessario richiamare il costruttore Person per ottenere un nuovo oggetto che erediti da Person.prototype. Di nuovo, a volte non è un problema, ma a volte ci sono effetti collaterali nel costruttore che non sono desiderati quando si imposta l'ereditarietà.

+0

Sono solo curioso ... qual è il motivo per impostare il costruttore del prototipo? 'Student.prototype.constructor = Studente;' – Polaris878

+2

+1 Per la correzione che rimuove 'new Person()' che potrebbe essere problematico nel caso in cui il costruttore genitore abbia parametri. Anche all'interno del costruttore, si potrebbero inviare anche argomenti. –

+1

@ Polaris878: è perché l'oggetto predefinito 'Student.prototype' ha una proprietà' .constructor' che punta alla funzione 'Studente' ... ma quell'oggetto viene sostituito, quindi se si desidera la proprietà' .constructor', deve essere aggiunto manualmente al nuovo oggetto. –

0

Dopo aver eseguito alcuni test, a mio avviso, il prototipo di un oggetto e le dichiarazioni di proprietà effettuate nell'ambito della sua funzione di definizione sono separati. Tuttavia, quando si costruisce un nuovo oggetto, il costruttore estrarrà le proprietà sia dalla funzione di definizione che dal prototipo dell'oggetto che si sta creando.

Per esempio,

function Person() 
{ 

    this.name = "james"; 
    this.age = "shfifty-five"; 


} 

console.log(Person.prototype.name); // prints "undefined", showing how declaring function Person() and Person.prototype are separate. 

Person.prototype.gender = "male"; 

var human = new Person(); 

console.log(human.name); // prints "james", showing how the object took properties from declaring function Person(). 
console.log(human.gender); // prints "male", showing how the object took properties from object prototype Person.prototype. 


function Student() 
{ 

    this.gpa = 4.00; 


} 



Student.prototype = new Person(); 

Student.prototype.constructor = Student; 


var myStudent = new Student(); 

console.log(myStudent.name); // prints "james" 
console.log(myStudent.gender); // prints "male" 
/*from above two lines, inheritance holds even though 1) Person() defining function was not called inside Student() defining function 
and 2) Person() defining function declares properties of Person object.*/ 
console.log(myStudent.gpa); // prints "4" 

Come si può vedere, in questo caso la persona funzione che definisce non altera le proprietà del suo oggetto. Ma non è ancora necessario chiamare la funzione Persona all'interno del costruttore di Student, perché il costruttore new Person() estrae le proprietà sia da Person.prototype sia dalla funzione di definizione function Person().

+1

Dipende ... Ogni nuovo oggetto 'Studente 'erediterà le proprietà dall'oggetto' Student.prototype'. Nel tuo esempio, quando esegui 'Student.prototype = new Person()', ci sono alcune proprietà che vengono aggiunte all'oggetto 'Person' che viene assegnato, quindi naturalmente queste saranno ereditate. Ma cosa succede se i valori assegnati nel costruttore 'Persona' non sono statici? Se non invochi 'Person' sui nuovi oggetti' Student', faranno sempre riferimento agli stessi valori di proprietà impostati sull'oggetto prototype. Se * hai * vuoi che i valori statici siano ereditati, devi metterli su 'Person.prototype'. –