JavaScript Variable Scope and Hoisting Explained

January 31 Last Year

In this post, we will learn JavaScript’s variable scope and hoisting and all the idiosyncrasies of both.

It is imperative that we understand how variable scope and variable hoisting work in JavaScript. These concepts might seem straightforward, but they are not. There are some important subtleties that we must understand, if we want to succeed in JavaScript development.

Variable Scope
A variable’s scope is the context in which the variable exists. It specifies from where you can access a variable and whether you have access to the variable in that context.

Variables have either a local scope or a global scope.

Local Variables (Function-level scope)
Unlike most programming languages, JavaScript does not have block-level scope (variables scoped to surrounding curly brackets); instead, JavaScript has function-level scope. Variables declared within a function are local variables and are only accessible within that function or by functions inside that function. See my post on Closures for more on accessing variables in outer functions from inner functions.

Demonstration of Function-Level Scope

var name = "Richard";

function showName () {
	var name = "Jack"; // local variable; only accessible in this showName function
	console.log (name); // Jack
}
console.log (name); // Richard: the global variable

No Block-Level Scope

var name = "Richard";
// the blocks in this if statement do not create a local context for the name variable
if (name) {
	name = "Jack"; // this name is the global name variable and it is being changed to "Jack" here
	console.log (name); // Jack: still the global variable
}

// Here, the name variable is the same global name variable, but it was changed in the if statement
console.log (name); // Jack
  • If You Don’t Declare Your Local Variables, Trouble is Nigh
    Always declare your local variables before you use them. In fact, you should use JSHint to check your code for syntax errors and style guides. Here is the trouble with not declaring local variables:
    


    // If you don't declare your local variables with the var keyword, they are part of the global scope
    var name = "Michael Jackson";
    
    function showCelebrityName () {
    	console.log (name);
    }
    
    function showOrdinaryPersonName () {	
    	name = "Johnny Evers";
    	console.log (name);
    }
    showCelebrityName (); // Michael Jackson
    
    // name is not a local variable, it simply changes the global name variable
    showOrdinaryPersonName (); // Johnny Evers
    
    // The global variable is now Johnny Evers, not the celebrity name anymore
    showCelebrityName (); // Johnny Evers
    
    // The solution is to declare your local variable with the var keyword
    function showOrdinaryPersonName () {	
    	var name = "Johnny Evers"; // Now name is always a local variable and it will not overwrite the global variable
    	console.log (name);
    }
  • Local Variables Have Priority Over Global Variables in Functions
    If you declare a global variable and a local variable with the same name, the local variable will have priority when you attempt to use the variable inside a function (local scope):

    var name = "Paul";
    
    function users () {
    	// Here, the name variable is local and it takes precedence over the same name variable in the global scope
    var name = "Jack";
    
    // The search for name starts right here inside the function before it attempts to look outside the function in the global scope
    console.log (name); 
    }
    
    users (); // Jack

Global Variables
All variables declared outside a function are in the global scope. In the browser, which is what we are concerned with as front-end developers, the global context or scope is the window object (or the entire HTML document).

  • Any variable declared or initialized outside a function is a global variable, and it is therefore available to the entire application. For example:
    // To declare a global variable, you could do any of the following:
    var myName = "Richard";
    
    // or even
    firstName = "Richard";
    
    // or 
    var name; //
    name;
    </pre>
    
    It is important to note that all global variables are attached to the window object. So, all the global variables we just declared can be accessed on the window object like this:
    
    console.log(window.myName); // Richard;
    
     // or
    console.log("myName" in window); // true
    console.log("firstName" in window); // true
    </pre>
    
  • If a variable is initialized (assigned a value) without first being declared with the var keyword, it is automatically added to the global context and it is thus a global variable:
    function showAge () {
    	// Age is a global variable because it was not declared with the var keyword inside this function
    	age = 90;
    	console.log(age);// 
    }
    
    showAge (); // 90
    
    // Age is in the global context, so it is available here, too
    console.log(age); // 90

    Demonstration of variables that are in the Global scope even as they seem otherwise:

    // Both firstName variables are in the global scope, even though the second one is surrounded by a block {}. 
    var firstName = "Richard";
    {
    var firstName = "Bob";
    }
    
    // To reiterate: JavaScript does not have block-level scope
    
    // The second declaration of firstName simply re-declares and overwrites the first one
    console.log (firstName); // Bob

    Another example

    for (var i = 1; i <= 10; i++) {
    	console.log (i); // outputs 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
    };
    
    // The variable i is a global variable and it is accessible in the following function with the last value it was assigned above 
    function aNumber () {
    console.log(i);
    }
    
    // The variable i in the aNumber function below is the global variable i that was changed in the for loop above. Its last value was 11, set just before the for loop exited:
    aNumber ();  // 11
    
  • setTimeout Variables are Executed in the Global Scope
    Note that all functions in setTimeout are executed in the global scope. This is a tricky bit; consider this:

     // The use of the "this" object inside the setTimeout function refers to the Window object, not to myObj
    
    var highValue = 200;
    var constantVal = 2;
    var myObj = {
    	highValue: 20,
    	constantVal: 5,
    	calculateIt: function () {
     setTimeout (function  () {
    	console.log(this.constantVal * this.highValue);
    }, 2000);
    	}
    }
    
    // The "this" object in the setTimeout function used the global highValue and constantVal variables, because the reference to "this" in the setTimeout function refers to the global window object, not to the myObj object as we might expect.
    
    myObj.calculateIt(); // 400
    // This is an important point to remember.
  • Do not Pollute the Global Scope
    If you want to become a JavaScript master, which you certainly want to do (otherwise you will be watching Honey Boo Boo right now), you have to know that it is important to avoid creating many variables in the global scope, such as this:

    // These two variables are in the global scope and they shouldn't be here
    var firstName, lastName;
    
    function fullName () {
    	console.log ("Full Name: " + firstName + " " + lastName );
    }

    This is the improved code and the proper way to avoid polluting the global scope

    // Declare the variables inside the function where they are local variables
    
    function fullName () {
    	var firstName = "Michael", lastName = "Jackson";
    
    	console.log ("Full Name: " + firstName + " " + lastName );
    }

    In this last example, the function fullName is also in the global scope.


Variable Hoisting
All variable declarations are hoisted (lifted and declared) to the top of the function, if defined in a function, or the top of the global context, if outside a function.

It is important to know that only variable declarations are hoisted to the top, not variable initialization or assignments (when the variable is assigned a value).

Variable Hoisting Example:

function showName () {
console.log ("First Name: " + name);
var name = "Ford";
console.log ("Last Name: " + name);
}

showName (); 
// First Name: undefined
// Last Name: Ford

// The reason undefined prints first is because the local variable name was hoisted to the top of the function
// Which means it is this local variable that get calls the first time.
// This is how the code is actually processed by the JavaScript engine:

function showName () {
	var name; // name is hoisted (note that is undefined at this point, since the assignment happens below)
console.log ("First Name: " + name); // First Name: undefined

name = "Ford"; // name is assigned a value

// now name is Ford
console.log ("Last Name: " + name); // Last Name: Ford
}

Function Declaration Overrides Variable Declaration When Hoisted
Both function declaration and variable declarations are hoisted to the top of the containing scope. And function declaration takes precedence over variable declarations (but not over variable assignment). As is noted above, variable assignment is not hoisted, and neither is function assignment. As a reminder, this is a function assignment: var myFunction = function () {}.
Here is a basic example to demonstrate:

 // Both the variable and the function are named myName
var myName;

function myName () {
console.log ("Rich");
}

// The function declaration overrides the variable name
console.log(typeof myName); // function
 // But in this example, the variable assignment overrides the function declaration
var myName = "Richard"; // This is the variable assignment (initialization) that overrides the function declaration.

function myName () {
console.log ("Rich");
}

console.log(typeof myName); // string 

It is important to note that function expressions, such as the example below, are not hoisted.

var myName = function () {
console.log ("Rich");
} 

In strict mode, it is an error if you assign a variable a value without first declaring the variable. It is very good practice to always declare your variables.

Thanks for your time; please come back soon. Email me here: javascriptissexy at gmail email, or use the contact form.

61 Comments

  1. Rameş Aliyev

    In for loop, when i create “i” with “var”, why it becomes global? I try it and see it, its no make sense, is it a bug of js?

    Here is live example
    http://jsbin.com/azawaj/1/edit

    • Hello Rames,

      If you are referring to the example below, i is a global variable because it was not defined in a function, and it is therefore part of the global scope. Even if the variable i were declared and initialized in the for loop, it would still be a global variable because JavaScript does not have block-level scope, so the block (curly brackets) from the for loop do not create a local scope.

      Here is the code:
      ______________________
      for (var i = 1; i <= 10; i++) {
      console.log (i); // outputs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
      };

      // i is a the global variable and it is accessible here with the last value it was assigned above
      function aNumber () {
      console.log(i); // 11
      }
      aNumber (); // 10
      ______________________

      The code is valid, just copy and paste it and run it in your browser’s console.

  2. “Its always good to read tips as you share with regard to blog placing. As I just now started placing comments with regard to blog plus facing challenge of loads of rejections. I believe that your suggestion will be helpful personally. I will allow you to know if perhaps its improve me too. “

  3. Vetri

    What do you mean by this?

    It is important to note that function expressions, such as the example below, are not hoisted.

    var myName = function () {
    console.log (“Rich”);
    }

    but I can see this hoisted.

    • @Vetri The function expression, var myName = function () {console.log (“Rich”);}, is not actually hoisted. Instead, if you initialize it after the var myName = “Rich” initialization, the myName variable is assigned a new value, which is the function.

      It looks like this when the code is executed:
      var myName;
      myName = “Rich”;

      // Then it is assigned a new value, the function
      myName = function () {console.log (“Rich”);}

  4. Ramon Royo

    Hi Richard,

    thank you for the article, I wasn’t aware of the scope for ‘this’ inside timeouts and intervals.
    I just wanted to point out a small problem in one of the examples, the variable names in the following example, should be surrounded by double quotes, as now they’re checked as properties inside window:

    console.log(myName in window);
    console.log(firstName in window);

    Should be:

    console.log(“myName” in window); // true
    console.log(“firstName” in window); // true

  5. Sean

    Great Post!! Quick Question Richard.. So basically theres no need to declare variables outside of a function if i can declare them within a function.. basically in what case would I need to declare variables outside a function when its easier to use them inside a function as below… it seems like local variables are easier to work with then global…

    function myFunction () {
    var a = “foo”
    }

    function newFunction () {
    var a = “boo”
    }
    myfunction()
    newFunction()
    why would i want to declare a variable outside a function and I can make one inside a function via local scope and use them later???
    Thanks!!!!

    • So basically theres no need to declare variables outside of a function if i can declare them within a function.

      You are correct. It is best to just use local variables, unless you need a global variable.

      basically in what case would I need to declare variables outside a function when its easier to use them inside a function as below

      There are times when you do need global variables, for example, when you want any function in your application to have access to the variable. Keep in mind your other functions wouldn’t have access to your local variables, so if you want other functions to access a variable, you would have to declare it as a global variable or pass it via the parameter to a function.

      There are many times when you are building a large application where you will have one or more global variables.

  6. Sean

    Great!! thanks for that, closures and hoisting are a bit confusing but after reading this it totaly makes sense…im on my journey reading and learning from this site along with Nicholas Zakas Professional Book … back to reading & coding :)

  7. In your example for hoisting, you say that the variable assignment will override the function declaration — well, in the Firefox (20) console it does not. Is that a browser bug? I see it works in Chrome.

    thanks

    • Good question and good research, whaleshark.

      You are correct that the overriding is working as expected in Chrome, while it is not in Firefox. The reason is that in Firefox, the second use of “myName” is a reassignment, so essentially, Firefox is assigning a new value to the myName variable. It is assigning the function to it.

      This is how the code is executed in Firefox:

      
      // A new myName global variable is created in Firefox and assigned the value "Richard"
      var myName = "Richard";
      
      /* The same global myName variable is now assigned a new value. The first myName String assignment is literally destroyed (because Stings are immutable—they cannot be changed) and a new myName global variable is created and assigned the value of the following function: */
      myName = function () {
      console.log ("Rich");
      }
      

      Now, you might be wondering why it is not executed the same way by both browsers. Welcome to land of Browsers gone rogue. All the browsers have similar but different implementation for many os JavaScript’s API, so you have to watch out for these kinds of side effects, which is why using the same global variable in this manner is not a good idea to begin with.

  8. A N Sinha

    Hi Richard,

    Thanks your very much :)

    JavaScript Variable Scope :
    ====================
    for (var i = 1; i <= 10; i++) {
    console.log (i); // outputs 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10;
    };
    function aNumber () {
    console.log(i); // 11
    }
    aNumber ();
    =================
    I REALLY SURPRISE
    var i is define inside the for loop it treated as a global variable.

    I have test the code in firebug, its treated as a global variable…..

    that's great…

    thanks your very much :)

    A.N. Sinha :)

    • Chachaching

      The behavior you are seeing right now on JavaScript is a new change in JavaScript. The variable scope used to be the same as other languages, but I also noticed the same thing a while back that there is no longer a variable scope WITHIN a function. In other words, once you start using/assigning a new variable inside a function, the variable will live through out the function scope regardless there are other sub scopes inside the function. I am still trying to find out whether this is a bug or intention of JavaScript (and it is definitely unconventional idea for all other computer languages).

      • Chachaching

        One more note, a variable you declared outside any function but inside the script tag will be GLOBAL regardless where you declare it and with or without ‘var’ keyword in front. To me, this idea is silly and it will break any variable scope idea.

      • Good observation, Chachaching.

        Modern browsers add different implementations for how to hand variable scope and when to garbage collect said variables.

        There was a vibrant discussion on this issue on Hacker News a few months back. If I find the link, I will post it.

  9. Mike

    Great site! Your articles are perfect for experienced Javascript developers who want to round out their knowledge and get into the fine details. Thanks!

  10. Eddie Romeiro

    Hi there. Great post and site. In regards to hoisting, there was a little confusion (at least for me) in your explanation about function hoisting. It should be made clear that function declarations get fully hoisted to the top, while function expressions behave like variables. Maybe even add that function declarations get hoisted and turn into an expression at the top. Just my opinion.

    • Hi Eddie,
      Your opinion is actually the fact: function declarations are indeed hoisted while function expressions are not.

      I did note this in the article, maybe you missed it. Here is the quote from the article:

      Both function declaration and variable declarations are hoisted to the top of the containing scope. And function declaration takes precedence over variable declarations (but not over variable assignment). As is noted above, variable assignment is not hoisted, and neither is function assignment. As a reminder, this is a function assignment: var myFunction = function () {}.

  11. abeing

    Hi, great article!
    I did this:
    function doSomething(){
    function formatSomething(element){
    return “”+element.text+””;
    }

    anObject({ format: formatSomething });
    anotherObject({format: formatSomething });
    }

    a function within a function, which I find very useful, because it worked and I had the function at the place where I need it.
    But is this good coding style?

    • a function within a function, which I find very useful, because it worked and I had the function at the place where I need it.
      But is this good coding style?

      If your question is whether a function inside a function (better known as a closure) is a good coding style, then the answer is a definite yes.

      Closures are used a lot by advanced JavaScript coders, and probably by most JavaScript coders in general. And sometimes it is even tough to avoid using a closure, so feel free to use closures liberally.

      I actually wrote an article on just closures—see the archive.

  12. Foysal Mamun

    thanks nice post.

  13. Deepak

    what happens when i am not used var for delectation. just used name; instated of var name.?

  14. Gulsen

    Hi Richard,

    Thanks for the great article.

    In your example with the celebrity name and ordinary person name, the first call to showCelebrityName() function, it logs “Michael Jackson”, and the second time “Johnny Evers”. Since the ShowOrdinaryPersonName is defined before the first showCelebrityName() call, does that mean that the name variable is changed to “Johnny Evers” once the ShowOrdinaryPersonName() is called but not when it is defined? Just to make sure I understand it correctly…

    Thanks,
    Gulsen

  15. Vipul

    Hi Richard,

    Thanks for the great article.
    I am new to Javascript, learnt new things from your posts. Actually i am focusing as a Javascript developer as my carrier path. Hope it will help me.

    Thanks,
    Vipul

  16. Alisa

    Hello,
    In gratitude for your informative article, I offer you some proofreading corrections…
    “Jhonny Evers”
    “global scape”
    “Variable Hosting”

    Cheers!

  17. Eric Oliveira

    You are a master of the didactics, your articles are simply amazing! Thank you for this excellent work!

  18. yougen

    Hi,
    “the variable assignment overrides the function declaration” example is not exactly accurate.
    function declaration is always precedence variable declaration. What happens is Execution Context has creation stage and code execution stage. Hoisting happens in creation stage. More info here: http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/

    I modify the code as following:

    console.log(typeof myName); // function , NOT string
    var myName = “Richard”;

    function myName () {
    console.log (“Rich”);
    }

    • Yougen,

      The variable assignment always overrides the function declaration. The reason it shows as function in your example code is because first the variables are hoisted (both the function and variable). Since they haven’t been assigned a value yet, the function declaration takes precedence, as I noted in the article. Because function declaration takes precedence over variable declaration.

      But then in the execution context when variable assignment occurs, the variable is assign the value “Richard” and it takes precedence over the function declaration. If the function were a function expression of this form: var myName = function () {}, then it would have had precedence over the variable assignment. But because only the variable is assigned a value, it takes precedence.

      Here is proof:

      
      console.log("Before: " + typeof myName); // Before: function
      var myName = "Richard";
      
      function myName () {
      console.log ("Rich");
      }
      
      console.log("After: " + typeof myName); // After: string
      
  19. Fon

    Hey Richard, thanks for you blog! It’s an amazing learning material.

    I want to share with everybody here about my experience of running the example code. At the beginning, I try to run the code with jsFiddle, however, the result sometimes will different. And I am confused. But after I try to just create a html file and run the code within the script tag. The result is correct.

    So, I think jsFiddle will change the behavior of scope for some reasons. Richard, do you know anything about this?
    This’s an example about “setTimeout Variables are Executed in the Global Scope”, the output of “console.log(this.constantVal * this.highValue);” is NaN

    http://jsfiddle.net/fangunxs/tUHPY/

    • The reason it did not work was because you use the “this” keyword inside the settimeout function, and the settimeout function changes the scope; it is run from the global scope.

      Read on post on JavaScript’s this for more:
      Understand JavaScript’s “this” With Clarity, and Master It

      Here is the fix for the NaN issue with your code:

      
      var highValue = 200;
      var constantVal = 2;
      var myObj = {
      	highValue: 20,
      	constantVal: 5,
      	calculateIt: function () {
              var self = this;
       setTimeout (function  () {
           
      	console.log(self.constantVal * self.highValue);
      }, 2000);
      	}
      }
      
  20. matt

    function showName () {
    setTimeout(function(){console.log (“First Name: ” + name)},0);
    var name = “Ford”;
    console.log (“Last Name: ” + name);
    }

  21. Johnzilla

    Hi. Great article. I found it very helpful for the most part but I do have a two lingering questions.

    1) In your first variable hoisting example, you say in a comment that “The reason undefined prints first is because the local variable name was hoisted to the top of the function.”
    I understand why this is clearly indicative of the variable assignment *not* being hoisted, but not how this is at all indicative that the declaration *is* being hoisted.

    2) With regard to functions, In one place you say that the format “var myFunction = function () {}” is called function assignment, but a bit further down you say that this is called function expression.
    I see that both of these are something different from function declaration, which is written as “function myFunction () {}” but not whether there is a difference between function assignment and function expression.

    Thank you and I look forward to reading more of your articles.

    • 1. All variable and function declarations are hoisted: this is simply a fundamental concept in JavaScript.

      2. Ah ha. That is a good catch.
      This, “var myFunction = function () {}”, is indeed both a function expression and a function assignment. Technically, it is called a function expression. So keep that in mind always, because you will encounter and use that kind of expression a lot.

      Now, whenever you assign a value to a variable, the execution is called a variable assignment. For example, var city = “New York”, is a variable assignment. Similarly the expression, var cityFunc = function () {}, is also a variable assignment. But because it is an assignment of a function to the variable, we call it a function assignment.

  22. Sivaram

    Hi Richard,

    I am starting to read your tutorial..its very very nice..
    its amazing when u explain everything…

  23. Shaikhul

    Function Declaration Overrides Variable Declaration When Hoisted – OK

    But variable assignment overrides the function declaration – not OK.

    ex.
    var hoistMe = ‘hoistme’;
    function hoistMe () {};
    typeof hoistMe; // “function”

  24. Shaikhul

    ah sorry ‘But variable assignment overrides the function declaration’ is ok while running all the statement together. but if i run each statement in chrome console one by one it doesn’t override. Any explanation for this ?

  25. haind

    Hi Richard. I’m just read your article. What I’m confused is I test some code with html file and command line of Firebug:
    console.log(typeof myName);
    var myName = “Richard”;

    I show me 2 different results. ‘undefined’ for html file and ‘string’ for command line. I think it ‘s kind of weird. Maybe you can explain for me?

  26. Dydrax

    what about get a value from local variable and stored in global variable

    in example i use a js library canvas like easeljs
    there is a lot of function there

    function main(){
    var text=["A","B","C"];
    var object;i=0;
    object.on("click",function(A){i++});//assume when click the i is increase
    console.log(text[i]);//still A why ?
    }

  27. saima

    One of the best articles on the subject.. Many thanks

  28. Very very nice explanation ..
    thanks : )

  29. sagar

    I am a server side programmer and ignored JavaScript for last 13-14 years. With frameworks like AngularJS and dojo , JS has got lot of recognition.
    I tried my hands on these frameworks recently and was damn scared with JS syntax.
    Thanks a lot bro, you saved me from turning my back forever to JS.
    You deserve a big HUG.

  30. Undefined

    I often find myself directed to this website via google after searching for further reading on various topics. Your explanations are clear and concise unlike some folks who feel the need to use verbose language when explaining various JavaScript concepts. Thanks for taking the time to help educate others.

  31. Vinayak

    Hi Richard,
    Thank you very much for the post.. you cleared many things for me with very good examples and neat explanations.

Trackbacks for this post

  1. 16 JavaScript Concepts You Must Know Well | JavaScript is Sexy
  2. JavaScript Closures in Lovely Detail | JavaScript is Sexy
  3. Learn Node.js Completely and with Confidence | JavaScript is Sexy
  4. Learn Backbone.js Completely | JavaScript is Sexy
  5. 12 Simple (Yet Powerful) JavaScript Tips | JavaScript is Sexy
  6. Simple Yet Powerful JavaScript Tips | Hackya.com
  7. Frontend Interview Practice | Hi, I'm Lillian.

Leave a Comment