#Javascript
10/01/2021

difference between var, let, and const

One of the features that came with ES6 is the addition of let and const, used to declare variables. They were added to solve an issue with var that we'll discuss later.

For now, we need to review what is Scope and Hoisting to understand the difference between these variables.

Scope

The scope is a range of variables determining their visibility and availability in various places in the code. It depends on how you declared a variable, which is very related to what we discuss in this article. Basically, there are two types of scope, global-scope, and local-scope, but we could also divide them into block-scope, function-scope, and global-scope. Let’s consider an example.

const example1 = 20  // Global Scope

Function example() {
  if(true) {
     console.log(example1);  //20
     console.log(example2);  //Undefined
     console.log(example3 );  //ReferenceError
      var example2 = 12;  //Function Scope
      let  example3 = 30;  // Block Scope
  }
  console.log(example1);  //20
  console.log(example2);  //12
  console.log(example3)  //ReferenceError
}

In variable example1, we have a global scope: Any variable that’s not inside any function or block (curly braces pair) can be accessed from anywhere in the program.

In variable example2, we have a function-scope: Any variable declared in a function can be accessed within the function where it is declared.

In variable example3, we have a block-scope: A variable that can be accessed only within the curly braces pair where it is declared.

Hoisting

Hoisting is a javascript mechanism that transfers function and variables declarations to the top of their scope before code execution; however, these variables declarations are moved to the top without their definitions. let's look at an example

var a = 1;   // initialization of a
console.log(a + ' ' + b);  // '1 undefined'
var b = 2;  // initialization of b

which for the interpreter is equivalent to:

var a = 1;  // initialization of a
var b;  // declaration of b
console.log(a + ' ' + b);  // '1 undefined'
b = 2;  // initialization of b

Now that we understand these two concepts let's see in detail what's the difference between var, let, and const.

Var

With var, you can declare variables visible inside a function, even after leaving the block in which they are defined.

function example () {
  if (false) {
    var ex = 5;
  }
return ex;
}

console.log(example()); // undefined

In the example above, we have a var variable that has a function-scope. When we call the example function, we get undefined, which is the value of ex that we are returning. What's happening here is that this variable is hoisted to the top of the function and initialized with a value of undefined, and because the if statement is false (meaning that it will never run), the value of our variable ex when we return it, is the initial value of undefined. If we change the false value to true in the if statement, we would get 5 when calling the example function because there we are initializing the ex variable with a value of 5.

Since var has a function-scope, the hoisting mechanism can become an issue, so let's consider a more advanced example to understand it.

function printNumbers() {
   for (var i = 0; i < 10; i++) {
      setTimeout(
         function printer() {
	    console.log(i);
       }, 100 );
   }
}

console.log(printNumbers()); // 10 (10 times)

The printNumbers function should print the numbers 0 through 9 to the console. However, when you try to run this code, only the number 10 is printed (10 times). Why?

The problem is that we are declaring the variable inside the for-loop with var, and as we just learned, this var declaration is hoisted to the top of the function. The program would be reading the code like so:

function printNumbers() {
   var i;
   for (i = 0; i < 10; i++) {
      setTimeout(
         function printer() {
	    console.log(i);
      },100 );
   }
}

console.log(printNumbers()); // 10 (10 times)

Perhaps now it makes sense the result that we are getting; if not, let me explain... Notice that all the functions that are executed in the setTimeout keep a reference to the variable i. If the functions are executed immediately, the value of i would be as expected. But since the execution will happen eventually, the value of i will then be the last value it got from the loop iteration. Therefore the printer function is logging to console the last value it got from the loop iteration (which is 10) for each iteration.

To fix the bug, we need the value to be printed to live within a scope not shared by all printer functions. And here is where comes the let keyword to fix this problem.

In conclusion, var variables can be re-declared and updated, hoisted to the top of their scope, and initialized with undefined.

Let

Using the let keyword, we declare local variables within the block scope, which means the scope is limited to the code block in which they are declared.

If we use the previous example again but now with let, we see that it solves the problem.

function printNumbers() {
   for (let i = 0; i < 10; i++) {
     setTimeout(
        function printer() {
	   console.log(i);
     }, 100 * I);
   }
}

console.log(printNumbers()); // 0 1 2 3 4 5 6 7 8 9

Let variables are hoisted to the top, but unlike var, they are not initialized,, so it means that they do not exist outside the block-code where they're declared.

So in the example above now, we get the result expected because, in this case, the variable i that is declared with let only exist within the for-loop. In this case, the variable i is independent in each iteration and, therefore, the printer function log to console a new variable with its value for each iteration.

Another feature of let is that you can update its value, but you cannot re-declared it.

Const

The const keyword is used to declare constants. It has the same behavior as let block-scope, hoisted to the top, and not initialized.

The difference is that you cannot re-declared a const variable. (this example also applies to let) For example, you cannot do this:

const example = 5;
const example = 8; //error

You cannot update the value of const variables when using primitive data types (numbers, booleans, strings, etc.) for example:

const example1 = 2;
example1 ++;  //error

const example2 = "hello";
example2 = "bye";  // errror

const example3 = false;
example3 = true;  //error

However, when you initialize a const variable with a non-primitive data type like an array or an object, you can still update it like so:

const example4 = [];
example4.push(5);
console.log(example4);  // [5]
const example5 = {};
example5.name = "Harry";
console.log(example5);  // {name: "Harry"}

I hope it was helpful.

difference between var, let, and const

Blog

© Copyright 2025 | CristianBernal All Rights Reserved