2012-01-30 10 views
7

Fuori solo curiosità intellettuale, perché javascript accettaJavascript: z = z || [] genera un errore quando non si utilizza VAR - perché?

var z = z || []; 

per inizializzare z (come z può definito inizialmente)

ma senza var, si genera un errore (nello spazio globale)

z = z || []; 

(se z è precedentemente indefinito)

Nello spazio globale non è necessario utilizzare VAR anche se ottengo potrebbe b e cattiva pratica

Prima di dire che questo è un duplicato di domande come

What is the purpose of the var keyword and when to use it (or omit it)?

nota la dichiarazione che "Se siete in ambito globale, allora non c'è alcuna differenza."

Ovviamente questo non è vero al 100%, dato il mio esempio di lavoro.

Si tratta di una stranezza o di una logica legittima?


l'aggiunta di una sintesi della risposta come ho imparato:

Grazie a Tim (vedi sotto) la chiave della mia incomprensione non era rendendo conto questo (fondamentale di JavaScript)

var z; non fa assolutamente nulla se esiste già z

Ecco come questa espressione sembra avere entrambi i modi, se si assume erroneamente che "var z" inizializza sempre.

Partendo da sinistra, "var z" si limita semplicemente a garantire che z sia definito, ma in realtà non influenza alcun valore esistente se già esiste. Quindi a destra, se esiste già z, viene utilizzato, in caso contrario, la variabile è stata appena dichiarata (ma vuota) in modo che non venga utilizzata ma non genererà un errore.

Questo è un eccellente articolo su questo tipo di scoping e sollevamento problema in Javascript: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

Molte grazie per MiniTech e tutti coloro che hanno contribuito anche!

+2

Come regola generale: copiare il messaggio di errore effettivo è normalmente più utile della semplice scrittura "genera un errore". –

risposta

6

z = z || [] genererà qualsiasi ambito (globale o meno) in cui non è presente z nella catena dell'ambito. Il motivo è che l'espressione tenta innanzitutto di recuperare il valore di una variabile esistente denominata z sul lato destro, che è un errore quando non esiste nessuno.

Il motivo var z = z || [] non genera un errore è che la variabile z viene creato (se non è già presente) prima dell'esecuzione della espressione, un effetto comunemente noto come sollevamento.

D'altra parte, l'assegnazione di un valore a un identificatore non risolto (ad esempio z = 2) funzionerà senza errori in qualsiasi ambito (eccetto che nella modalità rigorosa ECMAScript 5, che lo vieta e lo solleva). Se l'identificatore non può essere risolto, verrà aggiunto come una proprietà dell'oggetto finale nella catena dell'ambito, che è l'oggetto globale, dando quindi l'impressione di creare una variabile globale.

+0

Ah penso di averlo capito. Quindi "var z" viene fatto prima sul lato sinistro, come se si stesse istruendo "crea una nuova z", ma poi cerca una "vecchia z" sul lato destro. In questo ordine, "z" è stato appena inizializzato a sinistra, quindi la "z" sul lato destro non è indefinita, sebbene sia vuota. Senza la var, "z" a destra non è solo vuoto, non è definito. Hmm okay - se "var z" lo definisce come nuovo a sinistra, come fa questo codice a conservare i valori esistenti allora? Sembra che abbia entrambi i modi, inizializza a sinistra per la destra, ma può anche mantenere il valore a destra. –

+0

@ck_: Sì, penso che ce l'abbia, anche se la terminologia richiede un po 'di attenzione perché 'undefined' è un valore reale in JavaScript ed è in effetti il ​​valore predefinito assegnato a una variabile (ad esempio,' var x; ' crea una variabile chiamata 'x' con un valore iniziale di' undefined', che è distinto da un 'x' inesistente che non è mai stato dichiarato). Vado per "non dichiarato" o "inesistente". –

+0

@ck_: Riguardo alla conservazione dei valori esistenti, 'var z;' non fa assolutamente nulla se 'z' esiste già, qualunque sia il suo valore. –

10

L'effetto è corretto. var dichiarerà sempre i suoi "operandi" immediatamente, mentre quando non lo dichiari, lo script tenta di utilizzare una variabile non definita e genera un errore.

Se si è in ambito globale, è possibile assegnare a una variabile inesistente e avrà lo stesso effetto di dichiararlo, cattiva pratica come potrebbe essere. Naturalmente, nel tuo caso, è indefinito.Detto questo, anche se può essere per curiosità intellettuale, si sarebbe mai scrivere

var z = z || []; 

perché non ha senso farlo. Piuttosto, si potrebbe fare:

if(!window.z) { 
    window.z = []; 
} 

. Infatti, quando dichiaro le cose nell'ambito globale (che non è mai ;)) uso invece window.something perché rende più chiaro il mio intento.

+0

** quando non lo dichiari, lo script tenta di utilizzare una variabile non definita ** - aspetta stai dicendo z = z accesses z ma var z = z no? La seconda z è ancora in ambito globale come la prima se è al di fuori di una funzione. (perplesso) –

+1

@ck_: la differenza è che l'uso di 'var' fa sì che la variabile' z' venga creata prima che vengano eseguite le istruzioni. –

4

È possibile assegnare a una variabile non dichiarata z = 123; tuttavia non si può tentare di leggerne uno che è ciò che fa z = z || [].

Problemi correlati