DEV Community

Ivana
Ivana

Posted on • Originally published at Medium on

Hoisting in JavaScript — let, const, and var

What exactly are let, var, and const?

let, var, and const are different ways to declare a variable in JavaScript. var was the only option in any pre-ES2015 code.let and const were introduced with with ES6.

Declarations
JavaScript variables are containers for storing data values. Creating a variable in JavaScript is called “declaring” a variable.

VAR

Creating new variables in JavaScript is a two-step process. First, we declare the variable:

var carName;

After the declaration, the variable has no value
(technically it has the value of undefined). The JavaScript engine sets aside a chunk of memory to store the declared variable. Then, we assign a value to that variable:

carName = "BMW";

Alt Text

Scope
Scope determines the accessibility (visibility) of variables. In JavaScript there are two types of scope: local and global scope.

Global Scope
Variables declared Globally (outside any function) have Global Scope.

// code here can NOT use carName
function myFunction() {
  var carName = "BMW ";
  // code here CAN use carName
}
// code here can NOT use carName

Block Scope
Variables declared inside a block {} can be accessed from outside the block. Variables declared with the var keyword cannot have Block Scope. Example:

{
  var x = 10;
}
// x CAN be used here

LET

ES2015 introduced two important new JavaScript keywords: let and const.let is preferred for variable declaration now.

let pi = 3.14159;
/=> undefined

Will throw an error if you try to declare the same variable a second time:

let pi = "the ratio between a circle's circumference and diameter";
//=> Uncaught SyntaxError: Identifier 'pi' has already been declared

let is a signal that the variable may be reassigned. It also signals that the variable will be used only in the block it’s defined in, which is not always the entire containing function. So a variable declared in a block with let is only available for use within that block. Example:

let greeting = "say Hi";
   let times = 5;

   if (times > 3) {
        let hello = "say Hello instead";
        console.log(hello);// "say Hello instead"
    }
   console.log(hello) // hello is not defined

We see that using hello outside of its block (the curly braces where it was defined) returns an error. This is because let variables are block-scoped.

However, if the same variable is defined in different scopes, there will be no error:

let greeting = "say Hello";
    if (true) {
        let greeting = "say Hello instead";
        console.log(greeting); // "say Hello instead"
    }
    console.log(greeting); // "say Hello"

This is because both instances are treated as different variables since they have different scopes. This fact makes let a better choice than var. When using let, we don't have to think if we have used a name for a variable before, as a variable exists only within its scope.

HOISTING

In JavaScript, a variable can be declared after it has been used, which means that you can use a variable before it has been declared. This behavior is referred to as hoisting.

Alt Text

Let’s use an example to illustrate how hoisting works. Let’s say that we declare a variable called students which contains a list of student names, but we declare that variable after we ask our program to print it:

console.log(students);
var students = ['Inna', 'Marco', 'Sam'];

Our program returns:

undefined

But if we tried to declare our variable without the var keyword, our program would return the following:

Uncaught ReferenceError: students is not defined

This is hoisting in action. Variables can be declared after they are referenced using the var keyword. In simple terms, our program interpreted our above example like this:

var students;
console.log(students);
students =  ['Inna', 'Marco', 'Sam'];

Unlike variables declared using var, fortunately, in ES6 let and const variables offer much better behavior, and cannot be hoisted.

Alt Text
Here’s an example of a program that uses let to declare a variable:

let name = "My Name";
function exampleFunction() {
 if (name === "Marko Carson") {
  let name = "Marko Carson";
 }
 console.log(name);
}
exampleFunction();

When our code runs, the following result will be returned: My Name. The let name = Marko Carson; declaration is enclosed within our function, which means that it has local scope. Because we use the let keyword, our variable is not hoisted.

In summary, variables using var are subject to hoisting, which saves variable declarations in memory. This may result in problems if you define and assign your variables in the wrong order.

let and const variables are not subject to this feature. However, an error will be returned if we try to declare a variable more than once, or reference a variable that has not yet been declared in the relevant scope:

let pi = 3.14159;
/=> undefined
let pi = "the ratio between a circle's circumference and diameter";
//=> Uncaught SyntaxError: Identifier 'pi' has already been declared

let is a signal that the variable may be reassigned. It also signals that the variable will be used only in the block it’s defined in, which is not always the entire containing function. So a variable declared in a block with let is only available for use within that block. Example:

let greeting = "say Hi";
   let times = 5;
   if (times > 3) {
        let hello = "say Hello instead";
        console.log(hello);// "say Hello instead"
    }
   console.log(hello) // hello is not defined

We see that using hello outside of its block (the curly braces where it was defined) returns an error. This is because let variables are block scoped.
If the same variable is defined in different scopes, there will be no error:

let greeting = "say Hello";
    if (true) {
        let greeting = "say Hello instead";
        console.log(greeting); // "say Hello instead"
    }
    console.log(greeting); // "say Hello"

This is because both instances are treated as different variables since they have different scopes. This fact makes let a better choice than var. When using let, we don't have to think if we have used a name for a variable before, as a variable exists only within its scope.

Alt Text

CONST

Declaring a variable with the const reserved word means that not only can it not be redeclared but it also cannot be reassigned. This is a good thing for three reasons:

  1. When we assign a primitive value (any type of data except an object) to a variable declared with const, we know that variable will always contain the same value.

  2. When we assign an object to a variable declared with const, we know that variable will always point to the same object.

  3. When another developer looks at our code and sees a const declaration, they immediately know that variable points to the same object or has the same value every other time it's referenced in the program.

const pi = 3.14159;
//=> undefined

pi = 2.71828;
//=> Uncaught TypeError: Assignment to constant variable.Conclusion

However, because const doesn't allow reassignment after the variable is initialized, we must assign a value right away:

const pi;
//=> Uncaught SyntaxError: Missing initializer in const declaration

const pi = 3.14159;
//=> undefined

Best practice is to always declare variables with const and then, if you later realize that the value has to change over the course of your program, circle back to change it to let.

Conclusion

  • Use var... never.

  • Use let... when you know the value of a variable will change. For example, a counter variable that starts at 0 and is subsequently incremented to 1, 2, 3, and so on.

  • Use const... for every other variable.

To connect please check my Github, LinkedIn or Twitter.

Thank you for reading!

Top comments (0)