I understand the issues with global scope and javascript variables and their general undesirability; and that you find them everywhere. The following (in a browser) is equivalent:
var foo = 3; // foo === 3, window.foo === 3
bazz = 10; // bazz === 10, window.bazz === 10
Declaring a variable with the var keyword in the global scope is the same as declaring it without a var anywhere in the code: your variable is assigned to the root (window) object.
One technique I see a lot (e.g. setting up google analytics) is this:
var _gaq = _gaq || [];
... and I follow the reasoning that if _gaq has been declared use that, if not create it as an array. It allows careless coding not to overwrite any values already assigned to the global variable _gaq.
What I don't understand is why this throws an error:
_gaq = _gaq || [];
They look equivalent to me: _gaq should take the value of _gaq or be initialised as an array. But it throws a reference error - my question is: why are they different?
You can never read variables which have not been declared, and that's what you are trying with the expression _gaq || [] in the last case.
In this case
 _gaq = _gaq || [];
_qaq has not been declared before and when the right hand side (_gaq || []) is evaluated, it throws the error.
Here is step by step explanation of what is going on in this case:
The assignment operator is described in section 11.13.1 of the specification:
The production
AssignmentExpression : LeftHandSideExpression = AssignmentExpressionis evaluated as follows:1. Let
lrefbe the result of evaluatingLeftHandSideExpression.
2. Letrrefbe the result of evaluatingAssignmentExpression.
...
LeftHandSideExpression is _gaq, the AssignmentExpression is _gqa || [].
So first _qaq is evaluated, which results in an unresolvable reference, since the variable _gaq is not declared. This evaluation does not throw an error.
Then _gqa || [] is evaluated. This is a LogicalORExpression and is described in section 11.11 as LogicalORExpression || LogicalANDExpression. In this case, LogicalORExpression, the left hand side, is _gaq and LogicalANDExpression, the right hand side, is [].
The expression is evaluated as follows:
1. Let
lrefbe the result of evaluatingLogicalORExpression.
2. LetlvalbeGetValue(lref).
...
We already know that lref will be an unsolvable reference because _gaq was not declared. So lets have a look what GetValue is doing (defined in section 8.7.1, V is the value passed to GetValue):
1. If
Type(V)is notReference, returnV.
2. Letbasebe the result of callingGetBase(V).
3. IfIsUnresolvableReference(V), throw aReferenceErrorexception.
...
As you can see, a ReferenceError error is thrown in the third step of this procedure, which in turn gets executed by evaluating the right hand side of the assignment, and this is where the error is thrown.
So, why does this not happen with var _gaq = _gaq || []; ?
This line:
var _gaq = _gaq || [];
is actually
var _gaq;
_gaq = _gaq || [];
because of something called hoisting [MDN]. That means when _gaq is evaluated, it will not result in an unresolvable reference, but a reference with value undefined.
(If the variable _gaq is already declared (and potentially has a value), then var _gaq won't have any effect.)
If you want to create _gaq globally from inside a function, do it explicitly by referring to window:
window._gaq = window._gaq || [];
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With