2012-05-07 4 views
6

Ho creato un plugin jQuery per modificare la mia navigazione. Purtroppo devo accedere e modificare quasi tutti gli elementi figlio come <ul>, <li>, <a> e così via. Questi elementi sono quindi necessari da una a quattro volte.La memorizzazione di elementi selezionati/trovati in variabili aumenta le prestazioni?

Devo memorizzarli tutti in variabili o devo accedervi come $('.my-nav').find('li') o $('.my-nav').find('li') quando necessario?

Sembra proprio uno spreco di memoria avere 5 variabili per forse 25 righe di codice. Ma non so se questo è un compromesso accettabile per maggiori prestazioni.

ho creato un violino per illustrare cosa si intende: http://jsfiddle.net/Yj35Q/2/

+0

Grazie, ho corretto il violino. –

risposta

8

sempre buona norma memorizzare nella cache i nodi. È inoltre possibile eseguire il benchmark utilizzando http://jsperf.com/

Non è necessario preoccuparsi di quante variabili di spazio di archiviazione sono necessarie a meno che non si stia memorizzando un albero DOM massiccio o qualcosa del genere. Molto più rilevante la quantità di lavoro che il motore JS deve fare per localizzare i nodi.

EDIT
o, meglio ancora, è possibile trovare un banco di prova esistente che qualcun altro ha già creato
http://jsperf.com/ns-jq-cached/4

+0

Grazie, mostra chiaramente la differenza. –

2

All'interno della stessa funzione, io cache i risultati di una ricerca DOM in una variabile locale quindi non devo mai fare la stessa ricerca DOM più di una volta nella stessa funzione. Per la maggior parte delle funzioni questo non sarà necessario, ma è facile e sicuro inserire il risultato in una variabile locale solo per la durata della funzione, quindi penso che sia una buona abitudine.

NON memorizzerò i nodi DOM in variabili globali semplicemente perché cerco di evitare le variabili globali ed è raramente un problema di prestazioni recuperare il nodo DOM quando necessario per una particolare funzione. Un altro motivo per evitare di avere riferimenti DOM nelle variabili globali è che se un particolare nodo DOM viene rimosso dal DOM e si intende che esso sia garbage collection, se vi è un riferimento ad esso in una variabile globale, il nodo DOM non sarà raccolta dei rifiuti e potrebbe portare a una perdita di memoria.

Ci sono alcuni casi in cui sto ripetutamente guardando lo stesso nodo DOM (come su un timer) dove memorizzerò il nodo DOM in una variabile non globale in una chiusura di funzione e quindi useremo quella variabile localmente. Ma, trovo i casi in cui è necessario essere rari.

+0

+1. E fammi sapere cosa pensi del mio pigro selettore di jQuery che carica. –

+0

Grazie mille per la risposta. Come spesso, più risposte voglio accettare ma sfortunatamente solo una. fritzfromlondon è stato un po 'più veloce. –

+0

@JohnB. - La risposta di fritzfromlondon e la mia risposta sono risposte diverse con raccomandazioni diverse. Penserei che voteresti per quello che ha più senso per te o sembra più completo piuttosto che quello che è venuto pochi minuti prima dell'altro. Non mi oppongo a te scegliendo una risposta diversa dalla mia, solo che i tuoi criteri non dovrebbero essere quelli che vengono prima quando le risposte sono diverse. – jfriend00

3

È senz'altro consigliabile memorizzare nella cache gli elementi DOM, se appropriato, indipendentemente dal fatto che si utilizzi jQuery o meno.

Ma questa domanda mi ha fatto pensare che forse dovremmo avere un plugin per aiutare con questo. Ho cercato in giro e non riuscivo a trovarne uno.

Quindi ne ho scritto uno molto veloce. E 'un lazy loading jQuery selector ...

(function($){ 
    var cachedObjects = new Array(); 

    $.lazy = function(selector) { 
     if (typeof selector != "string" || arguments.length > 1) 
      return $.apply(this, arguments); 

     var o = cachedObjects[selector]; 
     if (o == undefined) 
     { 
      o = $(selector); 
      cachedObjects[selector] = o; 
     } 

     return o; 
    }; 
})(jQuery); 

usereste in questo modo ...

$.lazy('.my-nav').show(); 

fatemi sapere se ho trascurato nulla. Ma credo che sarebbe opportuno utilizzarlo ogni volta che gli elementi che stai selezionando sono statici e non vengono mai aggiunti o rimossi dinamicamente.

UPDATE

ho cambiato il codice per renderlo più efficiente. E ho aggiunto una riga a return $(selector) quando il selettore non è una stringa. Quindi la memorizzazione nella cache funzionerà solo quando il selettore è una stringa.

UPDATE # 2

Ora Sarà return $.apply(this, arguments) quando non sei semplicemente passando una stringa, per suggerimento di jfriend00.

+0

Un pensiero interessante. Quindi, invece di '$ (selector) .fadeOut()', si usa '$ .lazy (selector) .fadeOut()'. Ti suggerisco di assicurarti che il selettore sia una stringa e che potrebbe essere più efficiente quando non è già memorizzato nella cache non dovendo cercarlo di nuovo in 'cachedObjects' dopo averlo appena inserito. – jfriend00

+0

@ jfriend00 - Buoni pensieri. Farò questi cambiamenti più tardi, stasera. –

+0

Io suggerirei di cambiare 'se ritorno $ (selettore);' a (selettore typeof = "string"!): 'If (! Selettore typeof = "stringa" || arguments.length> 1) return $ .Applicare (questo, argomenti); 'quindi funziona per tutti gli argomenti jQuery accettabili. – jfriend00