8

While I was reading about JavaScript hoisting, I tried the following. I am not sure why the first one and second one output differently. (I am not even sure that this is related to hoisting).

var me = 1;
function findme(){
   if(me){
    console.log( me );//output 1
    }
  console.log( me ); //output 1
}
findme();

However the following outputs undefined:

var me = 1;
function findme(){
 if(me){
    var me = 100;
    console.log(me); 
    }
  console.log(me); 
}
findme();
// undefined
5
  • The second internal var "hoists" me to the findme scope, so when the script is run after parsing, me in findme in the second example is "reserved" to the local, not global, me. Which is really window.me. Commented Jan 13, 2013 at 1:13
  • Because if (me) tests an undefined local variable reserved to that function scope. So the if never runs, because in that situation, window.me would reference your "other" global me in a way that is not ambiguous with me locally. It makes perfect sense if you lock onto that "hoisting" reserves a variable directly to it's local scope, but variables are set undefined until they are assigned directly. Functions hoisted, though, may be called as normal, if hoisted. Commented Jan 13, 2013 at 1:19
  • 1
    adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting Commented Jan 13, 2013 at 1:26
  • Thanks to all who replied to my questions. I feel so stupid because that's what I was reading whole day about the hoisting and I still didn't get it. Mmmm, I'm dumb. Commented Jan 13, 2013 at 1:29
  • @shin—the term "hoisting" is misleading jargon, it infers that the entire statement is moved to the top of the enclosing scope. What actually happens is that variable and function declarations are processed before any code is executed. So all declared variables are created and assigned a value of undefined, then the code is run (which may subsequently assign a different value). Commented Jun 11, 2015 at 23:35

4 Answers 4

8

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

2 Comments

It's brought to the top of findMe. This is why you always should declare your vars at the top of any function.
Very well explained.
3

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.

Comments

2

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.

1 Comment

Declared variables are initially assigned a value of undefined, they never have "no value". ;-)
0

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.

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.