Variable hoisting in Javascript plays an important role in Javascript and understanding it helps understand and avoid many potentiel bugs. In this post, I will make variable hoisting as easy as it gets and give tips on newer ways to declare variables. 

Before I dive into hoisting, let’s understand scoping in Javascript.

Javascript support lexical scoping. And Lexical Scoping sets the scope of a variable so that it can only be refrenced from the block in which it was defined in. Lexical scoping is set at compile time and this is why a variable declared Lexcically is called a private variable. To get a further understanding of Lexcial Scoping, it is worthwile to understand its opposite, Dynamic Scoping. Dynamic Scoping sets the scope of a variable so that the variable can always be refrenced as long as the block in which the variable was defined in has not ended or returned.

An example of the comparison of the two types of scopes can help understand it better:

//Dynamic Scoped pseudocode example
function bar() {
  print a;
}
function foo() {
  a = 20;
  bar(); // calling the function that accesses
}

//calling the function
foo(); // 20
// Dynamic Scoped pseudocode examplefunction bar() {  print a;}function foo() {  a = 20;  bar(); // calling the function, which tries to access the variable local to this function}//calling the functionfoo(); // Uncaught ReferenceError: a is not defined

Now that we know the difference between Lexical and Dynamic scoping, we should know that Javascript is Lexical scoped. There is an exception with the scoping rule of Javascript variables and that is that the variables are not scoped to their nearest block or statement, but rather they are scoped to the containing function that the variable is declared in. And this exception to the rules can cause subtle bugs.

Let’s look at the following example:

function foo() {
  var a = "hello ";
  console.log(a + b); // hello undefined 
  var b = "world"; }

In this example, it should have given an error, but it did not. The reason is variable hoisting. Javascript took the declaration of the variable b and placed it at the top of the function and kept the initialization at where it is. In reality, the previous example looks like this:

function foo() {  
  var a = "hello ";
  var b; // hoisted
  console.log(a + b); // hello undefined
  b = "world";
}

 Now let’s get to how we can avoid these subtle bugs:

  1. One way is to explicitly place the variable declarations at the top of the defining function. 

  2. One more thing to note is that when we are in a catch block, then variable hoisting does NOT occur. In other words, if we are in a caught exception, then the scope of that variable would be the containing catch block, not the function that the catch is enclosed in. For example:
    function foo() { var a = "hello "; try { throw "exception"; } catch (a) { a = "world"; } console.log(a); } foo(); // hello <br>

  3. Another good way is to use the let keyword when declaring instead of var. If your application supports ECMA6, then letLet limits the scope to the defining block or statement. So our previous example, if used with let would give us an error and not run:
    function foo() { let a = "hello "; console.log(a + b); let b = "world"; } foo(); //Uncaught ReferenceError: b is not defined<br>

 Points of Benefit and Takeaways:

  •  Variable declarations within a block are hoisted to the top of the enclosing function.

  • Redeclarations of a variable is treated as a single variable.

  • Caught exceptions have their own scope, hoisting is not done from a catch block.

  • To avoid confusion, manually hoist local variable declarations.

  • To avoid variable hoisting, use let instead of var (ECMA6 only).
Categories: JavaScript

0 Comments

Leave a Reply

Avatar placeholder

Your email address will not be published. Required fields are marked *