In this blog we will talk about ES6 – Overview And Comparison – “var” Vs “let”

Let’s talk about “var” first. “var” in JavaScript works differently than similar keywords in other languages. Variables defined with “var” are hoisted on the top and we can use them before they are declared. 

studentName = "Jake"; // we can use studentName here   
var studentName;  

Let me give you some pointers here about JavaScript Hoisting. 

Hoisting is JavaScript’s default behavior where all variable declarations with the “var” keyword in a function are placed on the top of that function. We can prove this behavior by taking some more examples. 

function favoriteFood(name){  
if(name === "Charlie"){  
   var food = "burger";  
}  
else  
{  
   var food = "I haven't the foggiest idea."  
}  
return food;  
}  

Many of us might expect that it would return undefined or it would throw some warning or errors as the food variable is defined more than once. 

But in case of hoisting, only one declaration of any given variable is hoisted to the top of the function, and any other declarations of the given variable are ignored. 

After hoisting, this function should look like this.

function favoriteFood(name){  
var food;  
if(name === "Charlie"){  
   food = "burger";  
}  
else  
{  
   food = "I haven't the foggiest idea."  
}  
return food;  
}  

As we can see in the above-given example, the declaration of variable food is moved to the top of the function, and only once. 

Here is one more interesting example.

function favoriteFood(name){  
if(name === "Charlie"){  
   food = "burger";  
}  
else  
  {  
      food = "I haven't the foggiest idea."  
   }  
return food;  
var food;  
}  

As you can see, we moved the declaration of food down to the bottom of the function. 

It’s not a recommended practice because it’s bemusing. But it works because of hoisting. This code will still work as expected even though it looks like the declaration of food is blocked by the return statement and will never be reached. 

The next important thing to understand about “var” is scope. The “var” keyword uses functional scope.  

function testVariableScope{  
var greeting = "Good Morning!";  
{  
   var greeting = "Good Afternoon!";  
}  
{  
   var greeting = "Good Evening!";  
}  
return greeting;  
}  

This function will return “Good Evening” because of functional scope of “var” variable. If it had block scope it would return “Good Morning”! 

Let’s talk about the new ES6 keyword “let”, 

As we saw, “var” uses hoisting and function scope whereas “let” doesn’t use hoisting and uses block-scope. So what does that mean? Well, let’s go back to our earlier examples, and change each “var” keyword to “let”. 

function favoriteFood(name){  
if(name === "Charlie"){  
   let food = "burger";  
}  
else  
{  
   let food = "I haven't the foggiest idea."  
}  
return food;  
}  

Now TypeScript gives us an error, it cannot find the name food. It’s because “let” keyword in ES6 is block-scoped. Blocks are the closest containing set of curly braces.   

With “let”, the first food variable is only scoped to if statement curly braces and the second food variable is only scoped to else curly braces. The final food doesn’t reference anything at all, which is why TypeScript gives us an error. 

Let’s fix this problem by adding a declaration to the top.

function favoriteFood(name){  
let food;  
if(name === "Charlie"){  
   let food = "burger";  
}  
else  
{  
   let food = "I haven't the foggiest idea."  
}  
return food;  
}  

Now, as per the nature of block scope of “let”, we now have declared three variables in different block scopes. And, this function will always return undefined because the values are only set on the variable scoped to the blocks, not the one declared at the top of the function, which actually gets returned.  

To set it straight, we need to remove the let keyword in each branch. Now there’s one food variable that exists throughout the function and it’ll work as intended.

function favoriteFood(name){  
let food;  
if(name === "Charlie"){  
   food = "burger";  
}  
else  
{  
   food = "I haven't the foggiest idea."  
}  
return food;  
}  

The second major difference from “var” is that the “let” keyword doesn’t hoist. 

To see this in action let’s reuse existing example where we declared the variable after the return statement. 

function favoriteFood(name){  
if(name === "Charlie"){  
   food = "burger";  
}  
else  
{  
   food = "I haven't the foggiest idea."  
}  
return food;  
let food;  
}  

Because of hoisting this above-given code worked fine when using “var”. But TypeScript gives us an error every time we reference food and error goes like Block-scoped variable food used before its declaration.  

The reason for this error is because variables declared using “let” are not hoisted. So, we can’t use a variable declared with “let” until after the “let” keyword has been hit. Because of hoisting it’s fine to re-declare a variable with the “var” keyword inside a scope. 

The “var” keywords are hoisted to the top of the scope and the lines are treated as assignments. However, with “let” re-declaring, a variable in the same scope becomes a duplicate identifier error. This can be useful to identify possible bugs in your program.

If you enjoyed this post, I’d be very grateful if you’d help it spread by emailing it to a friend or sharing it on Twitter, LinkedIn, or Facebook. Thank you!

LEAVE A REPLY

Please enter your comment!
Please enter your name here