4

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.

3 Answers 3

3

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;
Sign up to request clarification or add additional context in comments.

1 Comment

I should also mention that it's for this reason that I separate my variable initialization from assignment. I know that it's a little verbose to write var foo; foo = bar;, but it makes this particular issue stand out more noticeably.
1

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.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.