While I was reading about Javascript hoisting, I tried the following. I am not sure why the first one and second one output differently. Thanks in advance. (I am not even su
Hoisting of a var
does NOT hoist the assignment, just the declaration. So it's being parsed like this:
function findme(){
var me;
if(me){
me = 100;
console.log(me);
}
console.log(me);
}
When the if
statement runs, me
is decalred local to the function, but is undefined
(has no value). undefined
is falsy so your condition is never true.
This is why it's customary to always declare your local variables at the top of functions, because that's where they go anyway, if you like it or not.
I feel like the true answer to this question is often abstracted away by the term "hoist". Here is what is REALLY happening.
Every time a function is ran in JavaScript, a new execution context is created for that funciton which is pushed onto the execution stack. So in your second example you have the following code:
var me = 1;
function findme(){
if(me){
var me = 100;
console.log(me);
}
console.log(me);
}
findme();
// undefined
At the very beginning of the execution of this code (assuming this is the entirety of the JavaScript), the first thing to happen is that the JavaScript engine creates a global execution context. During it's creation it allocates the memory for all functions and variables within that context. Functions are allocated and initialized the way you may imagine, but variables are only allocated first (not properly initialized).
So after the creation of the global execution context in this example the function findme() would be allocated in memory in its entirety BUT the variable "me" would be allocated with an initial value of undefined. After the global execution context is created, the code is then ran. It finds var me = 1; and updates the "me" variable from undefined to 1. It really doesn't do anything with the function definition, but, then it finds a function invocation of "findme();".
At this point, we enter the findme() function. And really, the same thing happens all over again. An execution context is created for this function, which is pushed onto the global execution stack, and this becomes the running code. If you understood the first part of my discussion I think you will realize that the "console.log(me);" call after the "if" statement IS undefined. Why? Because when the findme() function execution context was being created it initially created the "me" variable because it saw within its context by the "var me = 100;" statement. However, "if" statements do not get dedicated execution contexts in terms of the global execution stack. Thus, when the "console.log(me);" OUTSIDE of the if is ran the me variable IS defined in the overarching context of the function. BUT you are trying to access a variable outside of its scope.
If you followed all of this, you now understand a major part of how the JavaScript engine works.
The declaration of thee local variable in the if
block in the second example is hoisted to the entire function.
Thus, me
in the function always refers to the local variable, not the global.
However, the value of the variable is not hoisted, so it's always undefined
and the if
is never entered.
Variable declarations get hoisted to the top of every function, but the value assignments stay where they are. So the second example is run like this:
var me = 1;
function findme () {
var me; // (typeof me === 'undefined') evaluates to true
if (me) { // evaluates to false, doesn't get executed
me = 100;
console.log(me);
}
console.log(me);
}
findme();