2013-08-31 12 views
5

Ho uno sfondo Java e ultimamente sto sperimentando l'ereditarietà di JavaScript. Ho iniziato a scrivere alcuni oggetti e dopo aver letto alcuni esempi ho trovato lo stile del codice che mi si addice di più.Perché utilizzare Object.create per il prototipo quando si estende un oggetto?

Ecco quello che ho:

var Class = function() {}; 
Class.extend = function(p_constructor) { 
    var Superclass = this; 
    // the following line confuses me 
    p_constructor.prototype = Object.create(Superclass.prototype); 
    p_constructor.prototype.constructor = p_constructor; 
    p_constructor.extend = Superclass.extend; 
    return p_constructor; 
}; 

Così ora quando voglio definire un oggetto che si estende Classe I digitate:

var Person = Class.extend(function(p_firstName, p_lastName) { 
    this.firstName = p_firstName; 
    this.lastName = p_lastName; 
}); 

e la seguente sarà vero:

var p = new Person('john', 'smith'); 
p instanceof Person; // true 
p instanceof Class; // true 

Ho solo problemi a capire cos'è l'ef differenza cace tra le seguenti righe nella funzione Class.extend:

/* 1) */ p_constructor.prototype = new Superclass(); 
/* 2) */ p_constructor.prototype = Superclass.prototype; 
/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 
/* 4) */ p_constructor.prototype = Object.create(Superclass); 

mi rendo conto che utilizzando la linea 1 non è molto saggio se alcuni costruttori di super gettano errori, ma che cosa è esattamente la differenza tra le linee 2, 3 e 4?

risposta

6

Per rispondere alla mia domanda:

/* 1) */ p_constructor.prototype = new Superclass(); 

Come ho detto, non è molto saggio usare questo perché crea effettivamente l'intero oggetto superclasse. L'intero punto dell'ereditarietà prototipale consiste nel condividere gli oggetti prototipo in modo da poter evitare definizioni ridondanti di funzioni (e talvolta oggetti).

/* 2) */ p_constructor.prototype = Superclass.prototype; 

Questo sarebbe bene se si potesse essere sicuri che il prototipo del costruttore non sarebbe mai stato modificato da terzi. Supponiamo che qualcuno che usa la tua classe voglia aggiungere funzionalità aggiuntive al suo prototipo. Cambiare il prototipo del p_constructor influenzerebbe direttamente il prototipo della superclasse e potrebbe introdurre errori nel comportamento della superclasse. Così la prossima linea di codice è usato al posto:

/* 3) */ p_constructor.prototype = Object.create(Superclass.prototype); 

Questo crea un nuovo oggetto (esempio) il cui prototipo (in realtà la variabile __proto__) è impostato su prototipo superclasse. Qualsiasi modifica a p_constructor.prototype ora non modifica il comportamento della Superclasse.

/* 4) */ p_constructor.prototype = Object.create(Superclass); 

La linea superiore funziona, ma non ha senso perché stabilisce solo il prototipo al costruttore superclasse.

Inoltre, la seguente riga è stato confuso per me così:

p_constructor.prototype.constructor = p_constructor; 

Non fa alcuna differenza nel comportamento del p_constructor, fa solo il riferimento al costruttore disponibile in oggetto istanziato. Un trucco è quello di aggiungere la superclasse al prototipo così:

p_constructor.prototype.superclass = Superclass; 

E poi il seguente pezzo di codice avrebbe funzionato:

function Constructor(p_params) { 
    // call constructor of the superclass 
    this.superclass(p_params); 
} 
+0

fredda che hai risposto alla tua domanda qui.Nell'ultimo blocco di codice, considera il contesto della funzione di costruzione della superclasse quando la chiami in questo modo; Penso che quello che vuoi fare sia 'this.superclass.apply (this, arguments);' - quindi, se il costruttore del super va 'this.sumthin = ...', il valore è collegato all'istanza della sottoclasse. – dalgard

+0

I valori della superclasse sarebbero stati comunque associati all'istanza corrente della sottoclasse, perché è chiamata da 'this', quindi il contesto sarà in realtà la stessa nuova istanza della sottoclasse. – jeremija

+0

Oh, hai ragione. Penso di vedere questo pattern per accedere al super più spesso: 'subclass.prototype.super = superclass.prototype' (possibilmente con l'aggiunta di' subclass.super = superclass'). Forse saresti interessato a guardare [la mia soluzione] (https://gist.github.com/dalgard/9169923) a queste cose (vedi esempio nei commenti). – dalgard

Problemi correlati