2013-03-07 14 views
7

Gli oggetti JavaScript hanno il membro "prototype" per facilitare l'ereditarietà. Ma a quanto pare, possiamo vivere perfettamente bene, anche senza di esso, e mi chiedevo, quali sono i vantaggi di usarlo. Mi sono chiesto quali sono i pro e i contro.Perché utilizzare "prototype" per l'ereditarietà di javascript?

Per esempio, si consideri il seguente (qui jsfiddle):

function Base (name) { 

    this.name = name; 
    this.modules = []; 
    return this; 
} 

Base.prototype = 
{ 
    initModule: function() { 
     // init on all the modules. 
     for (var i = 0; i < this.modules.length; i++) 
      this.modules[i].initModule(); 
     console.log("base initModule"); 
    } 
}; 

function Derived(name) { 
     Base.call(this,name); // call base constructor with Derived context 
} 

Derived.prototype = Object.create(Base.prototype); 

Derived.prototype.initModule = function() { 
     console.log("d init module"); 
     // calling base class functionality 
     Base.prototype.initModule.call(this); 
    } 

var derived = new Derived("dname"); 
console.log(derived.name); 
derived.initModule(); 

Una domanda è, perché usare 'prototipo' a tutti? Possiamo anche fare qualcosa di simile Derived = Object.create(Base);

per esempio (jsfiddle):

Base = 
{ 
    initModule: function() { 
     // init on all the modules. 
     for (var i = 0; i < this.modules.length; i++) 
      this.modules[i].initModule(); 
     console.log("base initModule",this.name); 
    }, 
    init: function(name) { 
     this.name = name; 
     this.modules = []; 
    } 
}; 

Derived = Object.create(Base); 

Derived.initModule = function() { 
     console.log("d init module"); 
     // calling base class functionality 
     Base.initModule.call(this); 
    } 
Derived.init("dname"); 
console.log(Derived.name); 
Derived.initModule(); 
+3

Un professionista è la velocità: http://jsperf.com/prototype-vs-non-prototype/11 – StuR

+0

cosa succede se si dispone di un livello 4 sull'ereditarietà? dichiarerai un metodo newnewnewInitModule? – mpm

+0

@mpm hai ragione, è stato un errore, l'ho modificato via – Lior

risposta

3

Se non si utilizza il prototipo, i metodi vengono ridefiniti con ogni classe. Vale a dire, new Base; new Base; new Base creerà le sei funzioni nel secondo esempio. Questo richiede più tempo e spazio. Derived creerà anche le proprie funzioni.

Inoltre, non è possibile utilizzare il prototipo per modificare al volo i metodi di ciascuna istanza (o aggiungere nuovi metodi), che potrebbero essere potenzialmente utili, in particolare tra i moduli.

Tuttavia, questo non vuol dire che si dovrebbe sempre usare il prototipo per ogni metodo. Ogni situazione è diversa.

prototype consente inoltre di chiamare metodi in un contesto diverso senza creare un'istanza (come nel caso di Array.prototype.forEach.call su un oggetto di tipo array).

+0

grazie! le prestazioni sembrano essere il problema principale. Ma potresti approfondire "non puoi usare il prototipo per cambiare i metodi per ogni istanza al volo"? non sono sicuro che capisco – Lior

+0

@Lior cosa intendo dire che se si definisce il metodo 'Base.init', non è possibile sovrascriverlo con' Base.prototype.init' (compresi eventuali "figli" di esso). Utilizzerà il metodo one' Base.init' inizialmente definito, a meno che non si chiami esplicitamente l'altro dalla catena del prototipo –

1

in fondo è abbastanza semplice, l'Object.create è parte di ECMAScript 5, che è abbastanza nuovo. Il prototipo è stato utilizzato sin dall'inizio di javascript ed è supportato da tutti i browser.

Quindi, se è necessario il supporto per Internet Explorer 7 o 8, non dovresti affidarti a Crea. Vedere anche https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/create

(L'articolo suggerisce anche una polyfill, che utilizza prototipo ;-))

-2

Non è necessario il prototipo (che secondo me è una truffa) per OO.

considerare questo per eredità:

function SubClass() 
{ 
    var object = {}; 
    object.publicVar = 2; 
    object.publicMethod = function SubClassPubMeth() 
     { 
     return this.publicVar + 2; 
     }; 
    object.poly = function SubClassPoly() 
     { 
     return 'SubClassPoly'; 
     }; 
    return object; 
} 

function Class() 
{ 
    var object = new SubClass(); 
    object.classPublicVar = 3; 
    object.classPublicMethod = 
     function ClassMethod() 
     { 
      return this.publicVar + this.classPublicVar; 
     }; 
    object.poly = function ClassPoly() 
     { 
     return 'ClassPoly'; 
     }; 
    return object; 
} 

sembra adattarsi il disegno di legge per l'eredità.

Considera anche questo per nascondere informazioni:

funzione Class() { var oggetto = {}; object.x = 3; var privateVar = 3; function privateFunction (oggetto) { return object.x + privateVar; }

object.publicFunction = function() 
    { 
    var priv = privateFunction(this); 
    priv += privateVar; 
    privateVar = privateVar + 3; 
    return priv; 
    }; 
return object; 

}

sembra anche fare il trucco per nascondere le informazioni (AKA incapsulamento)

devo aggiungere altro.

+0

Se sei preoccupato per le prestazioni, allora hai bisogno di prototipi quando stai creando sottoclassi o quando crei nuove istanze dello stesso oggetto. – mpm

+0

Le cose che fai con Javascript non richiedono molta potenza di elaborazione. Se sei preoccupato, scrivi il codice usando Java (ad esempio). –

Problemi correlati