2013-02-23 18 views
7

Sto imparando alcuni aspetti del Javascript orientato agli oggetti. Mi sono imbattuto in questo frammentoereditarietà Javascript: chiamare Object.create quando si imposta un prototipo

var Person = function(firstName, lastName) 
{ 
    this.lastName = lastName; 
    this.firstName = firstName; 
}; 

Object.defineProperties(Person.prototype, { 
    sayHi: { 
    value: function() { 
     return "Hi my name is " + this.firstName; 
    } 
    }, 
    fullName: { 
    get: function() { 
     return this.firstName + " " + this.lastName; 
    } 
    } 
}); 

var Employee = function(firstName, lastName, position) { 
    Person.call(this, firstName, lastName); 
    this.position = position; 
}; 

Employee.prototype = Object.create(Person.prototype); 

var john = new Employee("John", "Doe", "Dev"); 

E la mia domanda è: perché non utilizzare questo frammento Object.create (Person.prototype)? Non dovremmo semplicemente resettare il prototipo con:

Employee.prototype = Person.prototype; 
+2

Un grande [risposta] (http://stackoverflow.com/questions/15040955/javascript-oop-and-prototypes-with-multiple-level-inheritance?answertab=active# tab-top) a questo da oggi. – marekful

+0

wow. grazie per quello segnalibro per studio! :-) –

+0

[n.] (Http://stackoverflow.com/q/12500637/1048572) – Bergi

risposta

9

Facendo Employee.prototype = Person.prototype è come dire "dei dipendenti è persona" piuttosto che "dei dipendenti è una persona". Eventuali modifiche a entrambi i prototipi si rifletteranno nelle classi entrambe.

Ecco uno demonstration. Ovviamente non vogliamo che le nostre persone lavorino perché non hanno una posizione.

Quindi il modo giusto di impostare la catena di prototipi senza Object.create è:

Employee.prototype = new Person; 

Ma questo richiede un'istanza di un oggetto, che è un po 'eccentrico - soprattutto se non si vuole il costruttore della persona di essere chiamato. Tutte le istanze di Employee erediteranno proprietà "firstName" e "lastName" non definite, indipendentemente dal fatto che lo si desideri.

In questo caso non è un grosso problema: il costruttore Employee imposterà tali proprietà su se stesso che sostituiranno le proprietà ereditate da Person. Ma considera this example. Si potrebbe pensare che freeTime sia una proprietà a livello di istanza per Person che non verrà copiata perché non è sul prototipo. Inoltre, non abbiamo mai chiamato il Costruttore persona dall'Impiegato. Non così: freeTime era impostato sul prototipo Employee perché dovevamo istanziare un oggetto.

Quindi l'eredità migliore e più pulita che puoi fare è tramite Object.create. Se si desidera chiamare il costruttore della classe genitore, è possibile farlo esplicitamente dal costruttore della sottoclasse. Un'altra cosa bella è che Object.create ha un secondo argomento (opzionale) per definire le Proprietà. Così puoi anche fare questo:

Employee.prototype = Object.create(Person.prototype, { 
    work: { 
    value: function() { 
     return this.fullName+" is doing some "+this.position+" stuff"); 
    } 
    } 
}); 

Ovviamente, se devi supportare i browser legacy non puoi usare Object.create. L'alternativa è usare clone/estendere da librerie come underscore o lodash. O c'è questa piccola danza:

var subclass = function() { }; 
subclass.prototype = Person.prototype; 
Employee.prototype = new subclass; 
+0

Perché questo è il modo corretto? Voglio dire, che cosa succede se oggetto Persona ha proprietà/campi (firstName, lastName)? Il prototipo del dipendente dovrebbe avere accesso ad esso? E inoltre ho bisogno di fornire lastName e firstName perché la funzione di costruzione ha bisogno di loro. – dragonfly

+0

Aggiornato con una dimostrazione. –

+0

Penso che l'esempio qui riportato sia negativo. I * aspetterebbe che 'freeTime' venga copiato sull'oggetto figlio perché è impostato nel costruttore del genitore e si intende richiamarlo dal costruttore del figlio. – Jez

1

La mia ipotesi è che l'intento è quello di creare un nuovo oggetto piuttosto che un semplice riferimento da Persona.

//create a new object with its prototype assigned to Person.prototype 
Employee.prototype = Object.create(Person.prototype); 
Problemi correlati