2013-07-04 16 views
11

Quali sono le differenze funzionali tra i seguenti due prototipi di Javascript e quali sono i vantaggi nella scelta dell'uno rispetto all'altro?Definizione di un prototipo di Javascript

Opzione 1:

Person.prototype.sayName = function(name) { 
    alert(name); 
} 

Opzione 2:

Person.prototype = { 
    sayName: function(name) { 
     alert(name); 
    } 
} 

Ho ragione nel ritenere che Opzione 2 risultati in cestinare alcune funzioni che sono implicitamente legati al prototipo ?

+0

Vedere anche [Qual è la differenza tra queste dichiarazioni di prototipo?] (Http://stackoverflow.com/questions/16773061/what-is-the-difference-between-these-prototype-declaration) – Bergi

risposta

5

Sono corretto nel presupporre che l'Opzione 2 risultati nel cestinare alcune funzioni che sono implicitamente legate al prototipo?

Sì, esattamente. Sebbene l'unica proprietà implicitamente legata sia la proprietà constructor, di cui raramente hai bisogno.

Quali sono le differenze funzionali?

L'opzione 1 sta semplicemente estendendo il prototipo esistente.Se ci sono già istanze Person che ereditano dall'oggetto prototipo, saranno in grado di utilizzare anche il metodo sayName. Con l'opzione 2, il nuovo prototipo verrà utilizzato solo per oggetti istanziati dopo la sovrascrittura.

Ci sono dei vantaggi nello scegliere l'uno rispetto all'altro?

Questi dovrebbero essere auto-esplicativi ora. L'opzione 1 (estensione) è considerata più pulita, ed è un must se stai modificando prototipi stranieri/sconosciuti/nativi. Cercate di evitare l'opzione 2.

Se ti piace ancora la sintassi letterale oggetto meglio, si dovrebbe considerare l'utilizzo di Object.assign di estendere il prototipo esistente:

Object.assign(Person.prototype, { 
    sayName: function(name) { 
     alert(name); 
    } 
}); 

Potrebbe essere necessario polyfill Object.assign per gli ambienti di pre-ES6. In alternativa, $.extend o _.extend funzionano altrettanto bene. Sicuramente anche la tua libreria preferita ha una funzione di supporto per questo.

+0

perché mai l'opzione 1 dovrebbe essere considerata più pulita. sembra che l'opzione 2 sia il modo di iniziare con una lavagna pulita per così dire. –

+1

@AlexMills: Perché non è necessario sapere quali proprietà esistono già sul prototipo che altrimenti si sovrascriverà e non le romperà (indipendentemente da dove viene chiamato il codice). È più semplice, meno soggetto a errori e compatibile con i forwards. Ovviamente, se si crea un prototipo di un oggetto da zero, si può anche usare il letterale dell'oggetto, ma anche allora la maggior parte delle persone dimentica la proprietà standard 'constructor'. – Bergi

2

Il primo è buono per una o due funzioni extra, ma definire un prototipo totalmente nuovo con molte funzioni sarebbe molto ripetitivo. D'altra parte, facendo il secondo distruggerebbe tutte le definizioni esistenti per il prototipo come lei ha menzionato.

In pratica, ho usato il primo per definire funzioni aggiuntive in Array e Math, ecc., Un po 'come le categorie in Objective-C. Quest'ultimo uso come una "definizione di classe".

+1

Capisco che quando aggiungendo su una libreria di codice esistente (come Math) non si vorrebbe cancellare completamente il prototipo, ma quando si crea una nuova libreria da zero, c'è qualche ragione per cui non dovrei cancellare il prototipo? In altre parole, quando creo un nuovo prototipo, ha già delle funzioni ad esso associate o è solo un segnaposto vuoto? –

+1

@RichardKeller Sovrascrivere il prototipo della funzione con quello di Object in modo da non poter usare 'new this.constructor()' per creare una nuova istanza di 'this': http://phrogz.net/JS/classes/OOPinJS2 .html – HMR

+1

Sei abbastanza sicuro con i nuovi prototipi. Ho provato a sperimentare nella console di Google Chrome e non riesco a distruggere nulla di importante. Vedi questo [collegamento] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto). – isaach1000

3

Il secondo sovrascrive person.prototype con l'oggetto.

Metodo uno:

Object.toString=function(){ 
    return "Object to string"; 
} 
var Person = function(){ 
}; 
Person.toString=function(){ 
    return "Person to string"; 
} 
Person.prototype.sayName=function(){} 
console.log(Person.prototype.constructor.toString());// "Person to string" 

Metodo due:

Object.toString=function(){ 
    return "Object to string"; 
} 
var Person = function(){ 
}; 
Person.toString=function(){ 
    return "Person to string"; 
} 
Person.prototype = { 
    sayName:function(){} 
} 
console.log(Person.prototype.constructor.toString());// "Object to string" 
0

in parole semplici la differenza è in Person.prototype.sayName tutto ciò che fai è quello di aggiungere una funzione al prototype. solo aggiungendo nuove funzionalità.

Nel secondo Person.prototype = {} qui si sta creando un nuovo oggetto intero e lo si assegna a prototype. Quindi stai creando un nuovo oggetto o sovrascrivi lo prototype con un nuovo oggetto.

Il primo metodo è buono per aggiungere molte funzioni come desiderate su richiesta. È possibile aggiungerli uno alla volta, quindi ritengo utile quando il programma è semplice e gli oggetti dell'applicazione non condividono molte funzioni o oggetti tra loro.

Il secondo metodo è buono se gli oggetti dell'applicazione condividono alcuni oggetti (o un gruppo di funzioni come @isaach detto in Math functions).

1

Qualsiasi istanza esistente del costruttore continuerà a puntare al vecchio oggetto prototipo. Qualsiasi nuova istanza creata punterà al nuovo oggetto prototipo.


I vantaggi di opzione 1 sopra l'opzione 2 sono semplicemente che non c'è bisogno di ristabilire la proprietà constructor e si salva un livello di rientro che è enorme per me.

Per salvare la ripetizione, ho solo assegnare la proprietà a una variabile locale:

var method = Person.prototype; 

method.getAge = function() { 
    return this.age; 
}; 

method.getName = function() { 
    return this.name; 
}; 

scelte anche comuni sono fn (jQuery) e p, che sono anche più breve di method.

Problemi correlati