9

Ho giocato con Object.create nelle specifiche di EcmaScript 5 e sto cercando di creare una struttura di tipo a ereditarietà multipla.Object.create vs eredità prototipale diretta

Dire che ho un paio di funzioni: a, b, c. Con solo trattare con i prototipi, posso fare questo:

function a() {} 
a.prototype = { 
    fnA = function() {}, 
    propA = 500 
}; 

function b() {} 
b.prototype = a.prototype; 
b.prototype.fnB = function() {}; 
b.prototype.propB = 300; 

function c() {} 
c.prototype = b.prototype; 
c.prototype.fnC = function() {}; 
c.prototype.propC = 200; 

Ma usando Object.create, vorrei fare qualcosa di questo:

function a() {} 
a.prototype = { 
    fnA = function() {}, 
    propA = 500 
}; 

var b = Object.create(new a()); 
b.fnB = function() {}; 
b.propB = 300; 

var c = Object.create(b); 
c.fnC = function() {}; 
c.propC = 200; 

Credo di ottenere lo stesso risultato in entrambi i modi.

Questo sembra un po 'goffo, perché ottengo l'oggetto indietro invece di una funzione di costruzione. Mi sembra che fare la normale eredità prototipica sia meno intrusivo e abbia più senso per le applicazioni modulari che non hanno bisogno di trattamenti speciali per funzionare.

Mi sto perdendo qualcosa? C'è qualche vantaggio nel provare a creare Object.create con i costruttori? O è utile solo per copiare oggetti esistenti? Desidero solo accedere alle proprietà & funzioni associate al prototipo e non alle funzioni e alle proprietà aggiunte in seguito all'oggetto.

O che ne è di questo (o utilizzare una copia in profondità migliore, ma l'idea rimane la stessa)?

function A() {} 
A.prototype = { 
    fn: function() { 
     console.log(this.propA + 30); 
    }, 
    propA: 20 
}; 

function B() {} 
Object.keys(A.prototype).forEach(function (item) { 
    B.prototype[item] = A.prototype[item]; 
}); 
B.prototype.propA = 40; 

function C() {} 
Object.keys(B.prototype).forEach(function (item) { 
    C.prototype[item] = B.prototype[item]; 
}); 
C.prototype.fn = function() { 
    console.log(this.propA + 3); 
}; 


var a = new A(), 
    b = new B(), 
    c = new C(); 

a.fn(); 
b.fn(); 
c.fn(); 

risposta

4

In realtà non si ottiene lo stesso risultato in entrambe le direzioni. Considerate questa linea:

b.prototype = a.prototype; 

Che cosa questo sta facendo è l'impostazione b.prototype esattamente lo stesso riferimento oggetto come a.prototype. Se modifichi il primo oggetto (ad esempio aggiungendo un metodo fnB) cambierai anche il secondo oggetto. Sono la stessa cosa. Alla fine del tuo primo set di codice avrai tre prototipi che sono tutti esattamente uguali, con gli stessi metodi e proprietà.

L'intero punto dell'ereditarietà prototipale è che si definisce un oggetto "interessante" (ovvero, con tutto il comportamento desiderato) e quindi lo si clona con Object.create e si modificano i cloni in base alle proprie esigenze (in genere modificando le sue proprietà, non i suoi metodi).

Quindi supponiamo di avere un oggetto vipera:

var adder = {x: 0, y: 0}; 
adder.execute = function() { 
    return this.x + this.y; 
} 

quindi si crea un clone e impostarne le proprietà:

var myadder = Object.create(adder); 
myadder.x = 1; 
myadder.y = 2; 
console.log(myadder.execute()); // 3 

Ora, ovviamente, questo è un esempio stupido, ma è mostra che è possibile pensa all'eredità prototipale senza dover scrivere costruttori e prototipi espliciti su quei costruttori.

+0

destro, credo di sì. Ma cosa succede se ho copiato tutte le proprietà nel prototipo di a to b, poi ho aggiunto cose al prototipo, poi ho fatto lo stesso per c? Questo raggiungerebbe la stessa cosa? – tjameson

+2

Meglio usare 'Object.create'. Quindi, 'b.prototype = Object.create (a.prototype);' E quindi stiamo usando la soluzione migliore per rendere migliore la soluzione minore. – jmbucknall

+0

Posso fare un altro costruttore? Dite che faccio Object.create, posso fare 'function new() {} new.prototype = Object.create (b);' o qualcosa di simile? Voglio solo una funzione esportabile ... – tjameson

0

Se è necessario supportare i browser che non supportano Object.create() è possibile utilizzare questa funzione

L'oggetto

function object(o) { 
    function F() {} 
    F.prototype = o; 
    return new F(); 
} 
districa modello il costruttore di JavaScript, raggiungere la vera ereditarietà prototipale. Prende un vecchio oggetto come parametro e restituisce un nuovo oggetto vuoto che eredita da quello vecchio. Se tentiamo di ottenere un membro dal nuovo oggetto e manca quella chiave, il vecchio oggetto fornirà il membro.Gli oggetti ereditano dagli oggetti. Cosa potrebbe essere più orientato agli oggetti di questo?

Più può essere letto qui: Prototypal Inheritance in JavaScript

+0

Poiché Object.create prende un secondo parametro che non è possibile riempire poly si potrebbe voler lanciare un errore se qualcuno lo fornisce Solo così tu o qualcun altro che usa il tuo codice avresti un errore chiaro invece di un comportamento inaspettato: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create#Cross-browser_compatibility – HMR

Problemi correlati