views:

129

answers:

6

Below javascript statements will cause error, if ga is not declared.

if (ga)
{
   alert(ga);
}

The error is:

ga is not defined

It looks undeclared variable cannot be recognized in bool expression. So, why below statement works?

var ga = ga || [];

To me, the ga is treated as bool value before "||". If it is false, expression after "||" is assigned to final ga.

+2  A: 

Edit: You need to use var ga; first or var ga = ga || [];, because its declare ga first and assign values into it.

You could try this

var x = 1, y = x + 1;
alert([x,y]) // 1,2

You may notice, when y is declare, x is already declared and already assigned 1 to it.

So, in your case, when ga || [] assigns, ga is already declared and its valid variable.

S.Mark
Oops, I forget the "var". The question is updated.
Morgan Cheng
yes, because, when you use `var` its declare first and assignment happen later on.
S.Mark
getting 2 downvotes ..., so could somebody please point out my answer is wrong? So I could correct it.
S.Mark
+4  A: 

null or defined are falsey values in javascript (implicitly evaluates to false.) the || operator returns the first value that does not evaluate to false.

var x = 0 || "" || null || "hello" || false; // x equals "hello"

On the other hand the && operator will return the first falsey value or the last value.

var y = "a string" && {"attr":"an object"} && false && ["array"]; 
// y equals false

var z = "a string" && {"attr":"an object"} && ["array"]; 
// z equals ["array"] 
Kenneth J
A: 

In the second statement ga is checked if it is defined and if true, is assigned to itself. Otherwise it's assigned an empty value.

iconiK
A: 

This works in the case with 'var' because the variable-stop in the scope resolution is created. Without the 'var' you just run off looking through the scope chains and you get told. If you really want to use a global variable:

// This is fine because assignment always sets a property value
// in this case (no 'var ga') it's the same as window.ga = window.ga || []
ga = window.ga || []

Or:

// Once again, only the lookup is affected with "running off"
// the lookup chain. It's not that the variable has no value --
// the problem is there IS NO VARIABLE.
if (!window.ga) {
  ga = []
}

Or even this:

// First line is the same as window.ga = window.ga,
// but now the property ga is guaranteed to exist on the window object --
// the VALUE of the property may (still) be undefined
ga = window.ga
ga = ga || []

Note that in both these cases I explicitly invoked ga as a property of the window (global) object.

You can read about the details here: Identifier Resolution, Execution Contexts and Scope Chains.

The placement of var within a scope does not matter. All of the following are the same:

var ga
ga = ga || []

var ga = ga || []

ga = ga || []
var ga
pst
+1  A: 

Possibly a less weird-looking option:

if (typeof ga !== 'undefined') 
{
   alert(ga);
}
MDCore
A: 

You are expecting b to be an array, probably you want to use an array method on b or read an index value from it.

var b= s.match(/\d+/) || [];
return b[0];

this returns the matched text or undefined-

without the empty array assignmentment, the second line would throw an error if there was no match.

kennebec