Domanda

Io sto solo in JavaScript e sto cercando di avvolgere la mia testa intorno ereditarietà prototipale.Sembra che ci sono molteplici modi per ottenere lo stesso effetto, così ho voluto vedere se c'è qualche best practice o motivi per fare le cose in un modo o l'altro.Ecco di cosa sto parlando:

// Method 1
function Rabbit() {
    this.name = "Hoppy";

    this.hop = function() {
        console.log("I am hopping!");
    }
}

// Method 2
function Rabbit() {}

Rabbit.prototype = {
    name: "Hoppy",

    hop: function() {
        console.log("I am hopping!");
    }
}

// Method 3
function Rabbit() {
    this.name = "Hoppy";
}

Rabbit.prototype.hop = function() {
    console.log("I am hopping!");
}

// Testing code (each method tested with others commented out)
var rabbit = new Rabbit();
console.log("rabbit.name = " + rabbit.name);        
rabbit.hop();

Tutti questi sembrano avere lo stesso effetto singolarmente (a meno che mi manca qualcosa).Quindi è un metodo preferito rispetto all'altro?Come si fa a farlo?

È stato utile?

Soluzione

Quando si inserisce un metodo sul prototipo, Ogni oggetto di istanza condivide lo stesso riferimento al metodo. Se hai 10 istanze, c'è 1 copia del metodo.

Quando fai quello che hai fatto nell'esempio 1, ogni oggetto di istanza ha una sua versione dello stesso metodo, quindi se crei 10 dei tuoi oggetti, ci sono 10 copie del codice in esecuzione.

Utilizzando il prototipo funziona perché JavaScript ha macchinari per l'esecuzione della funzione associata con un'istanza, cioè imposta il this Proprietà per l'esecuzione della funzione.

Quindi l'uso del prototipo è altamente preferito poiché utilizza meno spazio (a meno che, naturalmente, non è quello che desideri).

Nel metodo 2, si sta impostando il prototipo impostandolo uguale a un oggetto letterale. Nota che qui stai impostando una proprietà, che penso che tu non intenda fare, poiché tutte le istanze otterranno la stessa proprietà.

Nel metodo 3, stai costruendo il prototipo di assegnazione alla volta.

Preferisco il metodo 3 per tutte le cose. cioè nel mio costruttore ho impostato i valori delle mie proprietà

myObj = function(p1){
   this.p1; // every instance will probably have its own value anyway.
}

myObj.prototype.method1 = function(){..} // all instances share the same method, but when invoked  **this** has the right scope.

Altri suggerimenti

Diamo un'occhiata ai tuoi esempi uno alla volta. Primo:

function Rabbit() {
    this.name = "Hoppy";

    this.hop = function() { //Every instance gets a copy of this method...
        console.log("I am hopping!");
    }
}
var rabbit = new Rabbit();

Il codice sopra funzionerà, come hai detto nella tua domanda. Creerà una nuova istanza di Rabbit classe. Ogni volta che crei un'istanza, una copia del hop Il metodo verrà memorizzato in memoria per quell'istanza.

Il secondo esempio sembrava così:

function Rabbit() {}

Rabbit.prototype = {
    name: "Hoppy",

    hop: function() { //Now every instance shares this method :)
        console.log("I am hopping!");
    }
}
var rabbit = new Rabbit();

Questa volta, ogni istanza di Rabbit condividerà una copia del hop metodo. È molto meglio in quanto utilizza meno memoria. Tuttavia, ogni Rabbit avrà lo stesso nome (supponendo che tu non omichi il name proprietà nel costruttore). Questo perché il metodo è ereditato da prototype. In JavaScript, quando si tenta di accedere a una proprietà di un oggetto, quella proprietà verrà prima cercata sull'oggetto stesso. Se non si trova lì, guardiamo il prototype (E così via, su la catena prototipo fino a raggiungere un oggetto di cui prototype la proprietà è null).

Il tuo terzo esempio è praticamente il modo in cui lo farei. I metodi condivisi tra le istanze dovrebbero essere dichiarati su prototype. Proprietà come name, che potresti voler impostare nel costruttore, può essere dichiarato su base per istanza:

function Rabbit(rabbitName) {
    this.name = rabbitName;
}
Rabbit.prototype.hop = function() {
    console.log("Hopping!");
}

Questo è un problema importante che è spesso frainteso.Dipende da cosa stai cercando di fare.In generale, hvgotcode risposta è a destra su.Qualsiasi oggetto che verrà creata un'istanza di frequente devono allegare metodi e proprietà per il prototipo.

Ma ci sono dei vantaggi a tutti gli altri in situazioni molto specifiche.Leggi questo, tra i commenti: http://net.tutsplus.com/tutorials/javascript-ajax/stop-nesting-functions-but-not-all-of-them/

Ci sono occasioni in cui il metodo 1 di cui sopra aiuta, il che consente un "privato" leggibile/scrivibile proprietà e metodi.Anche se questo spesso non vale la pena il sacrificio pesantemente oggetti istanziati, per gli oggetti istanziati solo una volta o poche volte, o senza molte interna assegnazioni di, oppure se sei un dev team ambiente con un sacco di diversi livelli di abilità e sensibilità, può essere utile.

Alcuni sviluppatori di incorporare un'altra strategia che tenta di colmare alcune mancanze degli altri.Che è:

var Obj = function() {
    var private_read_only = 'value';

    return {
        method1: function() {},
        method2: function() {}
    };
};
// option 4
var Rabbit {
    constructor: function () {
        this.name = "Hoppy";
        return this;
    },

    hop: function() {
        console.log("I am hopping!");
    }
};

var rabbit = Object.create(Rabbit).constructor();
console.log("rabbit.name = " + rabbit.name);        
rabbit.hop();

Quando si esegue l'OO prototipico new e le funzioni del costruttore sono completamente opzionali.

Come è già stato notato, se puoi condividere qualcosa attraverso il prototipo, fallo. I prototipi sono più efficienti per quanto riguarda la memoria e sono più economici in termini di tempo di istanza.

Tuttavia, un'alternativa perfettamente valida sarebbe

function Rabbit() {
    // for some value of extend https://gist.github.com/1441105
    var r = extend({}, Rabbit);
    r.name = "Hoppy";
    return r;
}

Qui le tue "istanze" estese con le proprietà del "prototipo". L'unico vantaggio di OO prototipico reale è che è un collegamento dal vivo, il che significa che le modifiche al prototipo si riflettono su tutte le istanze.

Esegui alcuni test delle prestazioni (dichiara circa 1 variabile di coniglio di 1 milione). Il primo metodo sarà il più tempo e la memoria.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top