JavaScript Hoisting

If we execute below Javascript code, what will the browser console display:

var temp = 'outside global';
function foo(){
    var temp = 'inside function';

The console will log undefined.
Function-level scope. Functions create new scopes in Javascript, blocks like if statements and for loops do not create a new scope. A variable declaration simply tells the interpreter that a variable exists. By default it initializes the variable to undefined.
In Javascript, variable declarations are “hoisted” to the top of the current scope. Variable assignments, however, are not.
The declaration (but not the assignment) of temp gets hoisted to the top of foo(). So our code gets interpreted as though it were:

var temp = 'outside global';
function foo(){
    var temp;
    temp = 'inside function';

So we have a new variable temp inside of foo() that is initialized to undefined, which is what it holds when we hit our log statement.

In JavaScript, a variable can be declared after it has been used. In other words; a variable can be used before it has been declared. JavaScript only hoists declarations, not initialization. Because variable declarations (and declarations in general) are processed before any code is executed, declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it’s declared. This behavior is called “hoisting”, as it appears that the variable declaration is moved to the top of the function or global code.

Why hoisting?

The JS code interpretation performed in two passes. During the first pass, the interpreter / compilation processes variable and function declarations. The second pass is actually code execution step. The interpreter processes function expressions and undeclared variables. JS engine actually will compile your JavaScript code before it interprets it. Part of the compilation phase was to find and associate all declarations with their appropriate scopes (lexical scope). So, the best way to think about things is that all declarations, both variables and functions, are processed first, before any part of your code is executed. So, one way of thinking, sort of metaphorically, about this process, is that variable and function declarations are “moved” from where they appear in the flow of the code to the top of the code. This gives rise to the name hoisting. Only the declarations themselves are hoisted, while any assignments or other executable logic are left in place. If hoisting were to re-arrange the executable logic of our code, that could wreak havoc.

For one thing, JavaScript engines don’t get the luxury (like other language compilers) of having plenty of time to optimize, because JavaScript compilation doesn’t happen in a build step ahead of time, as with other languages. For JavaScript, the compilation that occurs happens, in many cases, mere microseconds (or less!) before the code is executed. To ensure the fastest performance, JS engines use all kinds of tricks that are well beyond the scope of this blog.

var a =2;

Encountering var a, Compiler asks Scope to see if a variable a already exists for that particular scope collection. If so, Compiler ignores this declaration and moves on. Otherwise, Compiler asks Scope to declare a new variable called a for that scope collection. Compiler then produces code for Engine to later execute, to handle the a = 2 assignment. The code Engine runs will first ask Scope if there is a variable called a accessible in the current scope collection. If so, Engine uses that variable. If not, Engine looks elsewhere as per scope hirerachy. If Engine eventually finds a variable, it assigns the value 2 to it. If not, Engine will raise its hand and yell out an error.

To summarize: two distinct actions are taken for a variable assignment: First, Compiler declares a variable (if not previously declared) in the
current Scope, and second, when executing, Engine looks up the variable in Scope and assigns to it, if found.


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s