Non è mai possibile leggere le variabili che non sono state dichiarate ed è ciò che si sta tentando con l'espressione _gaq || []
nell'ultimo caso.
In questo caso
_gaq = _gaq || [];
_qaq
non era stata dichiarata prima e quando si valuta il lato destro (_gaq || []
), si genera l'errore.
Ecco spiegazione passo passo di ciò che avviene in questo caso:
L'operatore di assegnazione è descritta nel section 11.13.1 della specifica:
The production AssignmentExpression : LeftHandSideExpression = AssignmentExpression
is evaluated as follows:
1. Let lref
be the result of evaluating LeftHandSideExpression
.
2. Let rref
be the result of evaluating AssignmentExpression
.
...
LeftHandSideExpression
è _gaq
, il AssignmentExpression
è _gqa || []
.
Quindi viene valutato il primo _qaq
, che risulta in un unresolvable reference, poiché la variabile _gaq
non è dichiarata. Questa valutazione non produce un errore.
Quindi viene valutato _gqa || []
. Questo è un LogicalORExpression
ed è descritto in section 11.11 come LogicalORExpression || LogicalANDExpression
.In questo caso, LogicalORExpression
, il lato sinistro, è _gaq
e LogicalANDExpression
, sul lato destro, è []
.
L'espressione è valutata come segue:
1. Let lref
be the result of evaluating LogicalORExpression
.
2. Let lval
be GetValue(lref)
.
...
sappiamo già che lref
sarà un riferimento irrisolvibile perché _gaq
non è stato dichiarato. Quindi, consente di avere uno sguardo che cosa GetValue
sta facendo (definito in section 8.7.1, V
è il valore passato a GetValue
):
1. If Type(V)
is not Reference
, return V
.
2. Let base
be the result of calling GetBase(V)
.
3. If IsUnresolvableReference(V)
, throw a ReferenceError
exception.
...
Come si può vedere, un errore di ReferenceError
è gettato nella terza fase di questa procedura, che a sua turn viene eseguito valutando il lato destro del compito, e qui è dove viene generato l'errore.
Quindi, perché non succede con var _gaq = _gaq || [];
?
Questa linea:
var _gaq = _gaq || [];
è in realtà
var _gaq;
_gaq = _gaq || [];
a causa di qualcosa che si chiama hoisting [MDN]. Ciò significa che quando viene valutato _gaq
, sarà non risultato in un riferimento irrisolvibile, ma un riferimento con valore undefined
.
(Se la variabile _gaq
è già dichiarato (e, potenzialmente, ha un valore), quindi var _gaq
non avrà alcun effetto.)
Se si desidera creare _gaq
a livello globale dall'interno di una funzione, fare si esplicitamente facendo riferimento a window
:
window._gaq = window._gaq || [];
Non sono esattamente equivalenti, differiscono nel comportamento quando si tenta di ['delete'] (http://perfectionkills.com/understanding-delete/). – Bergi
La migliore spiegazione di "incarichi non dichiarati" e perché sono diversi dagli incarichi globali ('foo = 0'! =' Var foo = 0' nell'ambito globale) Posso trovare è ** [su questo blog] (http : //perfectionkills.com/understanding-delete/) ** che mi ha aiutato a capire la differenza intrinseca. –