Today, I got completely surprised when I saw that a global variable has undefined
value in certain case.
Example:
var value = 10;
function test() {
//A
console.log(value);
var value = 20;
//B
console.log(value);
}
test();
Gives output as
undefined
20
Here, why is the JavaScript engine considering global value as undefined
. I know that JavaScript is an interpreted language. How is it able to consider variables in the function?
Is that a pitfall from the JavaScript engine?
There is a global variable
value
, but when control enters thetest
function, anothervalue
variable is declared, which shadows the global one. Since variable declarations (but not assignments) in JavaScript are hoisted to the top of scope in which they are declared:Note that the same is true of function declarations, which means you can call a function before it appears to be defined in your code:
It's also worth noting that when you combine the two into a function expression, the variable will be
undefined
until the assignment takes place, so you can't call the function until that happens:This phenomenon is known as: JavaScript Variable Hoisting.
At no point are you accessing the global variable in your function; you're only ever accessing the local
value
variable.Your code is equivalent to the following:
Still surprised you're getting
undefined
?Explanation:
This is something that every JavaScript programmer bumps into sooner or later. Simply put, whatever variables you declare are always hoisted to the top of your local closure. So, even though you declared your variable after the first
console.log
call, it's still considered as if you had declared it before that.However, only the declaration part is being hoisted; the assignment, on the other hand, is not.
So, when you first called
console.log(value)
, you were referencing your locally declared variable, which has got nothing assigned to it yet; henceundefined
.Here's another example:
What do you think this will alert? No, don't just read on, think about it. What's the value of
test
?If you said anything other than
start
, you were wrong. The above code is equivalent to this:so that the global variable is never affected.
As you can see, no matter where you put your variable declaration, it is always hoisted to the top of your local closure.
Side note:
This also applies to functions.
Consider this piece of code:
which will give you a reference error:
This throws off a lot of developers, since this piece of code works fine:
The reason for this, as stated, is because the assignment part is not hoisted. So in the first example, when
test("Won't work!")
was run, thetest
variable has already been declared, but has yet to have the function assigned to it.In the second example, we're not using variable assignment. Rather, we're using proper function declaration syntax, which does get the function completely hoisted.
Ben Cherry has written an excellent article on this, appropriately titled JavaScript Scoping and Hoisting.
Read it. It'll give you the whole picture in full detail.
Variables in JavaScript always have function-wide scope. Even if they were defined in the middle of the function, they are visible before. Similar phenomena may be observed with function hoisting.
That being said, the first
console.log(value)
sees thevalue
variable (the inner one which shadows the outervalue
), but it has not yet been initialized. You can think of it as if all variable declarations were implicitly moved to the beginning of the function (not inner-most code block), while the definitions are left on the same place.See also
I was somewhat disappointed that the problem here is explained, but no one proposed a solution. If you want to access a global variable in function scope without the function making an undefined local var first, reference the var as
window.varName