2015-04-26 21 views
5

Qual è la differenza tra queste 2 implementazioni dell'ereditarietà prototipale e considerando che stiamo lavorando con 2 diversi "prototipi" (la proprietà prototipo che è solo sulle funzioni e il prototipo interno) e in che modo queste implementazioni differiscono nel loro prototipo ricerca a catena? Inoltre, la prima implementazione (utilizzando la proprietà prototype) si basa sul nostro utilizzo dell'operatore new?Qual è la differenza tra queste 2 implementazioni dell'ereditarietà prototipale?

Assegnazione di proprietà da funzioni prototype e con il new esercente:

function foo() {} 

foo.prototype.output = function(){ 
    console.log('inherits from Function.prototype property'); 
}; 

bar = new foo(); 
bar.output(); 

memorizzazione di una funzione in un oggetto letterale e utilizzando il metodo Object.create():

var foo = { 
    output: function(){ 
    console.log('inherits from the internal prototype'); 
    } 
}; 

var bar = Object.create(foo); 
bar.output(); 
+0

Una differenza è che 'Object.create' è più recente, e non è supportato in IE8 e sotto – keune

+0

non vedo prototipale ** ** eredità nei tuoi esempi. – hindmost

+0

@hindmost puoi elaborare per favore? – shmuli

risposta

3

La differenza principale è nel modo in cui viene utilizzato, e i pericoli associati.

Il primo obbliga a utilizzare new quando si desidera creare un nuovo oggetto. La sintassi è abbastanza brutta (SomeConstructor.prototype.method) e presenta un importante difetto: chiamare un costruttore che aggiunge proprietà (this.name = nameParam ...) senza new applicherà la costruzione all'oggetto globale. Il comportamento del costruttore è strano (crea un nuovo oggetto che delega a SomeConstructor.prototype, quindi applica il costruttore al nuovo oggetto, quindi se il costruttore restituisce qualcosa sostituisce l'oggetto con qualcosa). Inoltre, nel tuo esempio, lo stesso foo non è utilizzabile, devi creare un nuovo oggetto per poter accedere alle sue funzionalità.

Il secondo, Object.create, non ti obbliga a utilizzare qualsiasi stranezza sintotossica. Non hai il rischio di inquinamento globale. L'oggetto foo ha funzionalità che possono essere già utilizzate senza creare un nuovo oggetto e bar prenderà semplicemente in prestito queste funzionalità. Questo tipo di schema può anche semplificare l'implementazione delle fabbriche (senza sostituire new ovunque) e i pool di oggetti, se necessario.

Eric Eliott talks about it very well e Kyle Simpson wrote a whole book sulla delega prototipo!

Ora, ecco come la ricerca avviene:

  • con il costruttore, la ricerca viene effettuata su Constructor.prototype (non il attuale prototipo interno del costruttore, ma la sua proprietà prototype Se lo trovate confusione. , congratulazioni, sei umano). Ulteriori proprietà sono impostate nella funzione di costruzione. foo non è utilizzato per la ricerca, foo.prototype (di nuovo, non lo stesso di foo.__proto__ che punta a Funzione) è quello utilizzato per esso.
  • Con Object.create la ricerca viene eseguita sull'oggetto stesso (foo). Nessuna proprietànon prototipo sull'oggetto.

C'è very funny diagrams on this page of Kyle Simpson's book che spiega la cosa ulteriormente.

Altro su new in questa domanda: Is JavaScript's "new" keyword considered harmful?

+1

La modalità rigorosa risolve il problema dell'inquinamento globale. – jdphenix

+0

@Kyll cosa differisce per quanto riguarda la "ricerca"? Queste implementazioni utilizzano 2 diversi oggetti 'prototipo', no? – shmuli

+0

Lasciami modificare quello! –

-1

Il primo esempio - foo, è una funzione.

Il secondo esempio: foo è un oggetto.

nel secondo esempio, la barra diventa una nuova istanza senza un costruttore. Vedere - https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/create, per aggiungere il costruttore.

Come nota a margine, è prassi comune che i costruttori debbano iniziare con una lettera maiuscola.

1

OK, prima di tutto, nel caso non lo sapeste, Object.create si basa sul seguente schema proposto da Douglas Crockford (leggi here):

function create (proto) { 
    function f() {} 
    f.prototype = proto; 
    return new f(); 
} 

Ora, si deve essere consapevoli che la il codice sopra riportato non produce lo stesso risultato se si passa null come parametro.
L'algoritmo ECMAScript per la creazione di nuovi oggetti (ulteriori informazioni here) indica che se il prototipo di una funzione è impostato su null (o qualsiasi non oggetto), quando si sta tentando di utilizzare la sintassi new f(), l'oggetto appena creato erediterà da Object.prototype.
Se si utilizza Object.create(null), l'oggetto appena creato avrà il suo [[Prototype]] set di membri interni alla null, il che significa che la catena di prototipi si fermerà lì (il vostro oggetto non ottenere hasOwnProperty e altre cose da Object.prototype come oggetto normale sarebbe).

var o1 = create(null); 
var o2 = Object.create(null); 
Object.getPrototypeOf(o1) === Object.prototype // true 
Object.getPrototypeOf(o2) === Object.prototype // false 
Object.getPrototypeOf(o2) === null // true 
Problemi correlati