It’s not hosting, it’s hoisting!

Developers often get confused with JavaScript scoping. As JavaScript resembles languages like C, it is often assumed it behaves the same way.

However, there’s a fundamental difference in scoping when compared to C in JavaScript. Let’s take a look at an example:

var count = 10;
function countMethod() {
if (!count) {
var count = 100;
}
alert(count); //alerts 100
}
countMethod();

Here, the value of count printed is 100 instead of 10. Why? Function and variable declarations are always moved to the top of their containing scope by the JavaScript interpreter. This is called as Hoisting (http://www.w3schools.com/js/js_hoisting.asp).

function countMethod() {
innerMethod();
var count = 1;
}


is actually interpreted like this:

function countMethod() {
var count;
innerMethod();
count = 1;
}

However,

var x = 5; // Initialize x
element = document.getElementById(“menu");  
element.innerHTML = x + " " + y;           // y is undefined here

var y = 7; // Initialize y

which means only the declarations are moved to the top and not the initialization. This tells us that JavaScript initialization are not hoisted.

Coming back to scoping, and the difference between other languages and JS, we see that C, C#, Java has a block-level scope and JavaScript, on the other hand has function-level scope.

var count = 10;
console.log(count); // 10
if (true) {
var count = 100;
console.log(count); // 100
}

console.log(count); // 100

This means that the count value assigned to 100 in the if condition, doesn’t create a new scope and caters to the default scope, thus modifying the value of count.

var count = 1;
function countMethod() {
var count = 10;
return;
}
countMethod();
alert(count); // prints 1

Here, we see that a new scope(function-level) has been created and thus doesn’t affect the outer scope.

This might seem very confusing to people coming from C,C++,C#,Java backgrounds.

Changes in ECMAScript 6

ECMAScript 6 has introduced Block-level declarations to bring in flexibility and usability of block-level scope. This is done by bringing in the keyword “let”.

This is very similar to var declaration. The variable declared with let has its scope limited to block-level. Thus, these variables declared with let are hoisted to the top of the block. However, referencing the variable in the block before the variable declaration results in a ReferenceError. The variable is in a “temporal dead zone” from the start of the block until the declaration is processed. This gets confusing as the variable declared with let are hoisted to the top of the block. It is however said, that they are not initialized with undefined like “var” and “function”, and we get a reference error.

function countMethod(condition){
if(condition)
{
   let count=10;
     return count;
  } 
 else{
   return null;
 }
}

Here, if the condition fails, then the variable count is not declared, which in case of var, would have been otherwise (top of function-level scope).

Also, “let” also prevents the redeclaration of variable in the same scope.

var count= 10;
let count = 100; //syntax error

Thus, Hoisting might look dangerous, and confusing, but it is one of the powerful features of the language. To ensure best practices, it’s recommended to use “use strict” or “JSLint“(http://www.jslint.com)

One thought on “It’s not hosting, it’s hoisting!

Leave a Reply

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

WordPress.com Logo

You are commenting using your WordPress.com 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