Understanding var, let and const in JavaScript
Tags: javascript, es6, es5
Published: 2019-07-23 22:46:24

---
title: Understanding var, let and const in JavaScript
published: true
tags: javascript, ES6, ES5
canonical_url: 
---
> You can check my other articles about Frontend development, Selenium and Test Automation at [CosmoCode.io](CosmoCode.io)

In this tutorial, we’ll explore the three different ways to declare a variable in JavaScript <g id="15" data-gr-id="15">– </g>`var`<g id="15" data-gr-id="15">,</g> `let`  <g id="8" data-gr-id="8">and </g>`const`<g id="8" data-gr-id="8"> keywords</g>. The <g id="9" data-gr-id="9">keyword </g>`var`<g id="9" data-gr-id="9"> is</g> available since the beginning of JavaScript. <g id="10" data-gr-id="10">Keywords </g>`let`<g id="10" data-gr-id="10"> </g><g id="11" data-gr-id="11"><g id="10" data-gr-id="10">and</g> </g>`const`<g id="11" data-gr-id="11"> were</g> added in ES6. We’ll also understand <g id="12" data-gr-id="12">why </g>`var`<g id="12" data-gr-id="12"> is</g> problematic and we should <g id="13" data-gr-id="13">use </g>`let`<g id="13" data-gr-id="13"> </g><g id="14" data-gr-id="14"><g id="13" data-gr-id="13">or</g> </g>`const`<g id="14" data-gr-id="14"> instead</g>.

## `var` k<g id="7" data-gr-id="7">eyword</g>

Till ES5 `var` was the only way to declare variables in JavaScript:

```javascript
//Declaring variable
var car;
//Initializing variable
car = 'Tesla';
```

Most of the time we do the declaration and initialization at once:

```javascript
var car = 'Tesla';
```

**Hey, I know these simple things. They are common across all programming languages.**

No, they are not so simple<g id="86" data-gr-id="86">.</g> In JavaScript scoping works differently and it causes great confusion and frustrations to beginners<g id="5" data-gr-id="5">..</g> There is also the concept of _hoisting_ and _shadowing_.

If you have no idea of “scopes”, “hoisting” or “shadowing”, don't panic and read further.

### Scope of a variable in JavaScript

The term _scope_ in the programming world refers to the _visibility_ of a variable or other entities. Variables are not visible outside the scope in which they are declared. In JavaScript (till ES5), the scope of a variable is either a _global_ _scope_ or a _function_ _scope_. Before the ES6, there was no concept of _block scope_.

#### Global Scope

Any variable declared outside of a function is of global-scope, which means they can be accessed by any part of the program.

Let us see things in action:

```javascript
var msg = 'Hello World';
function greet(){
  console.log(msg);
}

greet();
```

Output:

```sh
Hello World
```

In this example variable `msg` is defined outside of any function. So it has a global scope. We know that if any variable has a global scope, any part of the program can access it. Hence it is visible inside the function `greet()`.


#### Local Scope (Function Scope)

If a variable is declared _inside_ a function, it is NOT visible _outside_ that function. Even if the variable is declared (using `var`) _inside a code block_ (e.g,`for`<g id="8" data-gr-id="8">, </g>`while`<g id="8" data-gr-id="8"><g id="8" data-gr-id="8">,</g> <code>if</code>), the variable is visible throughout the whole function, <em>outside that code-block</em>.</g>

Let us take an example:

```javascript
function greet(){
  if(true){
    var msg = 'Hello World';
  }
  console.log(msg);
}

greet();
console.log(msg);
```

Output:

```sh
Hello World
Uncaught ReferenceError: msg is not defined
```

As we can see the scope of the <g id="6" data-gr-id="6">variable </g>`msg`<g id="6" data-gr-id="6"> </g><g id="7" data-gr-id="7"><g id="6" data-gr-id="6">is</g> </g>_<g id="7" data-gr-id="7">function</g>_ _scope_. Although the variable is declared _inside_ <g id="8" data-gr-id="8">the </g>`if`<g id="8" data-gr-id="8"> block</g>, it is available _outside_ the local-block within the function. But it is not available _outside the function_ as we can see the <g id="9" data-gr-id="9">output </g>`Uncaught ReferenceError: msg is not defined`<g id="9" data-gr-id="9"> for</g> trying to access it outside the function.

It happens due to hoisting.

### Hoisting

Where do you hoist a flag?

On top of the castle.

Let us take an example to understand \*hoisting\* in JavaScript:

```javascript
console.log(msg);
var msg = 'Hello World';
```

Output:

```sh
undefined
```

**Wait…! I think we should get the following error because the variable msg was not declared when we tried to access it**

```sh
Uncaught ReferenceError: msg is not defined
```

Well, in JavaScript, it does not matter where variables are declared within a particular scope. All variable declarations are moved to the top of their scope.

The above program was translated by the JS interpreter as:

```javascript
var msg;
console.log(msg);
msg = 'Hello World';
```

As we can see the variable declaration was hoisted at the top of the scope, global-scope in this case. But the variable assignment was NOT hoisted. The JavaScript interpreter assigned it the default <g id="84" data-gr-id="84">value </g>`undefined`<g id="84" data-gr-id="84">.</g> Hence we got the output `undefined`.

The same concept would apply with function scope (local scope). All variable declarations inside a function will be <g id="4" data-gr-id="4">hoisted</g> at the top of the function, no matter where they are declared in the function.

```javascript
function greet(){
  if(true){
    var msg = 'Hello World';
  }
  console.log(msg);
}

greet();
console.log(msg);
```

The above program was translated by JavaScript interpreter as if var `msg` was hoisted at the top of the function although it is declared inside the `if` block.

```javascript
function greet(){
  var msg;
  if(true){
    msg = 'Hello World';
  }
  console.log(msg);
}

greet();
console.log(msg);
```

Hence we get the output – `Hello World`

### Shadowing

If we declare a local variable and a global variable with the same name, the local variable will take precedence when it is referred inside a function. It is called _shadowing_, the inner variable shadows the outer variable. The Javascript interpreter searches for the variable at the innermost scope and continues until the first match is found.

```javascript
var msg = 'Hello ';
var name = 'John';
function greet(){
  var msg = 'Julia';
  if(true){
    console.log(msg + name); //Hello Julia
  }
}

greet();
```

The moment <g id="61" data-gr-id="61">the </g>`if`<g id="61" data-gr-id="61"> block</g> is executed by the JavaScript interpreter, it looks for the <g id="126" data-gr-id="126">variable </g>`msg`<g id="126" data-gr-id="126"> in</g> the local scope. As it is found there, it uses the local scope variable, even if the same variable is declared in the outer scope as well. <g id="692" data-gr-id="692">Variable </g>`name`<g id="692" data-gr-id="692"> it</g> is not found in the inner scope so the JS interpreter tries to find it in the outer scope and it is found.

> Scoping and Hoisting works the same for functions as it works with variables.

### Issues with `var`

No, that we have understood different concepts related to `var` , let us discuss the issues with var and why you should avoid using it.

Let us take an example:

```javascript
var greetings = 'Hello John';

function greet() {
  console.log(greetings); // undefined
  if (true) {
    var greetings = 'Hello Julia';
    console.log(greetings); //Hello Julia
  }
  console.log(greetings); //Hello Julia
}

greet();
```

If you are coming from another programming <g id="11" data-gr-id="11">language background</g> like Java, Python, C# <g id="7" data-gr-id="7">etc</g>, you must be thinking “what the heck”. Don’t you think as greetings is a global variable the first output should <g id="16" data-gr-id="16">be </g>`Hello John`<g id="16" data-gr-id="16"> ?</g> And the third output should be `Hello John` because although inside <g id="13" data-gr-id="13">the </g>`if`<g id="13" data-gr-id="13"> block</g> we have declared the same <g id="14" data-gr-id="14">variable </g>`greetings`<g id="14" data-gr-id="14"> it</g> should not be visible outside <g id="15" data-gr-id="15">the </g>`if`<g id="15" data-gr-id="15"> block</g>?

Incorrect!

We just learned about **scoping** , **hoisting** and **shadowing** in JavaScript. We know there is no concept of **block scope** in JavaScript(till ES5). Let us apply these learnings for the above example.

When the JavaScript interpreter encounters the variable declaration <g id="14" data-gr-id="14">for </g>`greetings`<g id="14" data-gr-id="14"> inside</g> the <g id="15" data-gr-id="15">local </g>`if`<g id="15" data-gr-id="15"> block</g>, it _hoisted_ the variable declaration at the top of the function. But only the declaration is hoisted, not initialization. The variable has the default <g id="17" data-gr-id="17">value </g>`undefined`<g id="17" data-gr-id="17"> that</g> the JavaScript interpreter assigns while declaration. When `greetings` is referred inside the first print statement, due to \*shadowing\* the JavaScript interpreter used the inner declaration of <g id="24" data-gr-id="24">the </g>`greetings`<g id="24" data-gr-id="24"> variable</g>, not the global one. But since the inner declaration <g id="25" data-gr-id="25"><g id="13" data-gr-id="13">of</g> </g>`greetings`<g id="25" data-gr-id="25"> was</g> not initialized yet, it printed its default <g id="26" data-gr-id="26">value </g>`undefined`<g id="26" data-gr-id="26">.</g>

Again, the same concept of _hoisting_ and _shadowing_ got applied in the third output. The interpreter took the function-scoped declaration <g id="10" data-gr-id="10">of </g>`greetings`<g id="10" data-gr-id="10">.</g> The only difference is this time<g id="8" data-gr-id="8"> </g>`greetings`<g id="8" data-gr-id="8"> was</g> already <g id="6" data-gr-id="6">intialized</g> inside <g id="9" data-gr-id="9">the </g>`if`<g id="9" data-gr-id="9"> block</g>.

> As we can see variables declared <g id="10" data-gr-id="10">with </g>`var`<g id="10" data-gr-id="10"> are</g> confusing and prone to introduce bugs in the program, if not written with at most care. And that is the reason you should never <g id="11" data-gr-id="11">use </g>`var`<g id="11" data-gr-id="11"> to</g> declare variables in your program. Always use `let` or `const` to declare variables.

## `let` keyword in ES6

The ES6 specification addressed these issues with JavaScript and introduced \*\*block scoping\*\* with a new keyword `let`.

Let us take the same example as the previous one with a change – replacing `var` with `let` keyword :

```javascript
let greetings = 'Hello John';

function greet() {
  console.log(greetings); //Hello John
  if (true) {
    let greetings = 'Hello Julia';
    console.log(greetings); //Hello Julia
  }
  console.log(greetings); //Hello John
}

greet();
```

As we see the output is more predictable with <g id="14" data-gr-id="14">the </g>`let`<g id="14" data-gr-id="14"> keyword</g>. The first time <g id="15" data-gr-id="15"><g id="8" data-gr-id="8">the</g> </g>`greetings`<g id="15" data-gr-id="15"> is</g> <g id="12" data-gr-id="12">referred</g> in the print statement, it took the global value because it was not yet declared locally. The JavaScript interpreter declared the second instance <g id="16" data-gr-id="16">of </g>`greeting`<g id="16" data-gr-id="16"> in</g> the local scope inside <g id="17" data-gr-id="17">the </g>`if`<g id="17" data-gr-id="17"> block</g>. It retains the local <g id="92" data-gr-id="92">value </g>`Hello Julia`<g id="92" data-gr-id="92"> inside</g> <g id="19" data-gr-id="19">the </g>`if`<g id="19" data-gr-id="19"> block</g>. But outside <g id="20" data-gr-id="20">the </g>`if`<g id="20" data-gr-id="20"> block</g> in where the variable was declared, the <g id="21" data-gr-id="21">same </g>`greetings`<g id="21" data-gr-id="21"> variable</g> is not visible to the interpreter. Hence it took the global declaration in the third print statement.

As we see the `let` keyword is behaving similar to most of the other programming languages and is having \*block scope\*. That is the reason we should “mostly” <g id="6" data-gr-id="6">use </g>`let`<g id="6" data-gr-id="6"> <g id="4" data-gr-id="4">keyword</g></g> to declare variables in JavaScript and never <g id="7" data-gr-id="7">the </g>`var`<g id="7" data-gr-id="7">.</g>

## `const` keyword in ES6

I hope you have noticed the earlier statement – we should “ **mostly** ” <g id="7" data-gr-id="7">use </g>`let`<g id="7" data-gr-id="7"> keyword</g>. We have used mostly because when we have variables that are never going to change their value, we should declare them <g id="8" data-gr-id="8">with </g>`const`<g id="8" data-gr-id="8"> <g id="5" data-gr-id="5">keyword</g></g>. It is a good safety feature because if any part of the program <g id="10" data-gr-id="10">try</g> to change the value of the variable, the JavaScript interpreter will raise an Exception.

Let us see things in action:

```javascript
function greet() {
  const greetings = 'Hello World';
  if (true) {
    greetings = 'Hello Julia';
    console.log(greetings);
  }
}

greet();
```

If we run this code, the JavaScript interpreter will raise an Exception where we try to change the value of `const` variable `greetings`.

```sh
Uncaught TypeError: Assignment to constant variable.
    at greet (<anonymous>:4:15)
    at <anonymous>:9:1
```

There is no other difference between `let` and `const`

## Conclusion

We hope this tutorial gave you a good understanding of all the three ways to declare variables in JavaScript. We discussed <g id="75" data-gr-id="75">as </g>`var`<g id="75" data-gr-id="75"> does</g> not have block scope, it is bug prone and we should never use it. We should use <g id="197" data-gr-id="197">E</g>S6’s `let` <g id="257" data-gr-id="257">or </g>`const`<g id="257" data-gr-id="257"> instead</g>. We also learned that we should <g id="9" data-gr-id="9">use </g>`const`<g id="9" data-gr-id="9"> when</g> we want to restrict a variable so that it never changes its value and remain <g id="5" data-gr-id="5">a constant</g>.