In the following code snippet I declare a global variable and then check for its presence inside a function.
<script>
x = 5;
$(function() {
var x = x || 3;
console.log(x); // prints 3
});
</script>
This behaves differently:
<script>
x = 5;
$(function() {
var y = x || 3;
console.log(y); // prints 5
});
</script>
I expect that in the first example, the variable declaration in the inner scope will detect that x already exists in the global scope, and take its value. Why does the first example 3?
Specifically I recently wrote some code that checks var _gaq = _gaq || []
in a jQuery ready scope and was confused when nothing was getting pubbed to Analytics.
You're looking for x
in the wrong scope. Due to variable hoisting, var x
has actually defined a local x
variable with a value of undefined
before your x || 3
check happens:
var x = x || 3;
is actually:
var x = undefined;
x = x || 3;
Simply change it to look for x
on the window
object:
var x = window.x || 3;
The first example logs 3 because
any variable that is initialized inside a function using the var keyword will have a local scope. If a variable is initialized inside a function without var, it will have a global scope.
So in the first case, when the local x
is assigned, since it is uninitialized, it gets assigned 3.
While in the second case, x
refers to the global variable x
as there is no declaration of x
inside the function.
Instead, if you try this
<script>
x = 5;
$(function() {
x = x || 3;
console.log(x);
});
</script>
OR
<script>
x = 5;
$(function() {
var x = window.x || 3;
console.log(x);
});
</script>
you will get the expected result 5
.
Additionally, unlike C and its family (which has block-level scope), JavaScript has function-level scope. Blocks, such as if statements, do not create a new scope. Only functions create a new scope.
So if I were to write something like
#include <stdio.h>
int main() {
int x = 1;
printf("%d, ", x); // 1
if (1) {
int x = 2;
printf("%d, ", x); // 2
}
printf("%d\n", x); // 1
}
OUTPUT: 1,2,1
as compared to
var x = 1;
console.log(x); // 1
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
OUTPUT: 1,2,2
Go through this excellent blog post on JavaScript Scoping and Hoisting to understand it better.
The var x
in the function declares x to be local to the function, so in x || 3
x not the global x and thus is undefined since it hasn't been initialized.
In var y = x || 3;
x is the global x as there is no x local the function.