var, let, and const – Why to avoid var 😷 and how to put the other two to good use? - Javascript
Tags: javascript, webdev, developer, tips
Published: 2021-06-12 10:06:47

Well, in this blog, we will illustrate the differences between `var`, `let` and `const`. We'll also discuss why we should avoid `var` and prefer `const`.

In ES5, we had only one way of declaring variables using `var`. But with ES6 we now have three to declare a variable namely `var`, `let` and `const`.

### 1. var

Firstly let us see how `var` works:

```js
for (var i = 0; i < 10; i++) {
  console.log(i);
}
```

In most programming languages, the scope of `i`will be inside the body of `loop` only. The value of `i` can be accessible within the **body** of `for loop`.

Let us see what happens if we console the value of variable `i` after the loop.

```js
for (var i = 0; i < 10; i++) {
  console.log(i);
}
console.log("After loop ", i); //This prints 10. 😳 Why is that?
```

We can see that we are able to access the variable `i` even outside the `loop`, which is very **intuitive** when coming from another programming language. No one would expect the variable `i` to **survive** outside the `loop`.

Why does that happen🤔?
The reason is that there is only one type of variable scope in ES5, which is a function scope.

To illustrate the above statement, let us wrap the above code inside a function and execute the function.

```js
function counter() {
  for (var i = 0; i < 10; i++) {
    console.log(i);
  }
  console.log("After loop ", i); //still prints 10 🤥
}
counter();
```

Let us move the console.log() to outside of the loop and see what happens.

```js
function counter() {
  for (var i = 0; i < 10; i++) {
    console.log(i);
  }
}
console.log("After loop ", i); //It throws an error this time: Reference error: i is not defined. 🤤
counter();
```

This time it throws an error `Refrence error: i is not defined` and it is because the scope of `var` is within the f unction scope . The variable `i` will be available only within the function counter and if called from outside the function it will throws and error.

In order to avoid this type of error, Some developers used the concept of Immediately Invoked Function Expression (IIFE).

This is how IIFE looks like.

```js
(function() {
  for (var i = 0; i < 10; i++) {
    console.log(i);
  }
})();
console.log("After loop ", i);
```

> Most of the Javascript developer does not know about IIFE.

**IIFE is a function that is declared and called immediately.**

> People do this to keep the variables that are inside the IIFE to pollute the rest of the code. It creates lots of cohesive block of safe-heaven.

#### Javascript variables are hoisted

What do `Javascript variables are hoisted` means?
Well, it means that they are hoisted to the top of their function.

What Javascript compiler or interpreter does is it will go through the code, and it will find variable declaration and push them up to the top of the function.

> 70% of javascript developers do not know the concept of hoisting.

Upon compiling the below code it still works. A the variable `i` of `for loop` is hoisted to top of the function.

```js
(function() {
  var i; //It pushes the variable to top of the function.
  for (i = 0; i < 10; i++) {
    console.log(i);
  }
})();
```

> Keep note it doesn't matter how many lines of code are there in between, it will still move the variable declaration to the top of the function.

There is also a horrible aspect of hoisting. Let's say you forgot the variable declaration. as shown in below code

```js
(function() {
  for (i = 0; i < 10; i++) {
    console.log(i);
  }
})();
console.log("After loop ", i); // This prints 10. What the heck just happened??😧
```

Why does it prints `10`? This happened because the javascript interpreter has put the variable declaration out of the function this time.

> If there is no variable declaration inside a function the interpreter will keep going up the function chain all upto global/window object. And then if it finds it then it will place the variable in the global/window object.

```js
var i;
(function() {
  for (i = 0; i < 10; i++) {
    console.log(i);
  }
})();
console.log("After loop ", i);
```

- This is of course horrible because you can accidently declare a global variables.

- This is why we are encouraged to always use `use strict` statement, it prevents us from accidentally declaring a global variable.

```js
"use strict";
(function() {
  for (i = 0; i < 10; i++) {
    console.log(i);
  }
})();
console.log("After loop ", i);
```

This time the above code will throw an error `RefrenceError: i is not defined.`

```js
"use strict";
var i = 9999;
(function() {
  for (var i = 0; i < 10; i++) {
    console.log(i); // this prints 1 2 ...10
  }
})();
console.log("After loop ", i); // This prints 9999
```

Even though we are using the same variable name, it prints 9999 because the inner `var i = 0` is scoped to the function only.

This time let's remove var from inside the function and see what happens

```js
"use strict";
var i = 9999;
(function() {
  for (i = 0; i < 10; i++) {
    console.log(i); // this prints 1 2 ...10
  }
})();
console.log("After loop ", i); // This prints 10
```

It prints 10, this is because `i` inside function is reassigning the outside variable `i`. As mentioned above it will check if variable `i` is defined in function, if it doesn't found it then it will move up to the global/window. As it finds the variable `i` then it will be re-assigned. That is the reason why it is logging out 10.

> Always remember the concept of hoisting. Hoisting is nothing but moving the variable declaration to the top of the function or global/window object.

### 2. let

Now let us demonstrate the same example using `let`.

```js
"use strict";
var i = 9999;
for (let i = 0; i < 10; i++) {
  console.log(i);
}
console.log("After for loop", i); // This prints 9999. It works.
```

We can see from the example code above that `let` is not behaving like `var`. And the above code works as expected.
The reason why it worked is that `let` introduces `block scoping`. The variable `let i = 0` of `for loop` will be available only inside the body of `for loop`.

The block scoping of `let` is also valid for if/else, switch etc.

```js
"use strict";
var i = 9999;
for (let i = 0; i < 10; i++) {
  console.log(i);
}
if (true) {
  let i = 1000;
}
console.log("After for and if", i); // This still prints 9999.
```

From the code snippet we can see that the the scope of variable `i` is scoped with in `for loop` and `if` respectively.

Just like `var` we can re-assign let.

```js
let i = 10;

i = 57;

console.log(i); // Prints 57
```

> `let` is block scope while `var` is function scope.

A lot of people say that `let` is the new `var` and I agree with that.

### 3. const

`const` is a variable just like `let` which cannot be re-assigned. To demonstrate this, let me show you an example.

```js
const i = 10;

i = 57;

console.log(i);
```

The code above throws an error `TypeError: Assignment to constant variable.`

Let's look at an example below

```js
const x = {
  y: 10,
};
x.y = 15;

console.log(x); // Prints {y: 15}
```

We can see that we are able to update the property of `x`. Now let us try to assign a new object to constant variable `x`.

```js
const x = {
  y: 10,
};
x = { z: 11 };
console.log(x); // This time it throws an error
```

The code snippet above throws an error because we are re-assigning a constant variable.

### var vs let vs const

Whole blog summarized in a table.

|         Scopes         | var     | let     | const   |
| :--------------------: | ------- | ------- | ------- |
| Stored in global scope | `true`  | `false` | `false` |
|     Function Scope     | `true`  | `true`  | `true`  |
|      Block Scope       | `false` | `true`  | `true`  |
|   Can be re-assigned   | `true`  | `true`  | `false` |
|   Can be re-declared   | `true`  | `false` | `false` |
|     Can be hoisted     | `true`  | `false` | `false` |

### Conclusion

> - Always use `const` if you do not want to change the variable.
> - Whenever you are using `let` first ask yourself if you are really changing the variable or do you really need to change it. If the answer is **yes** then use `let` else use `const`.
> - Always use 'const'. If you REALLY need to change state, use 'let'. 'var' is dead.
> - `var` should always be avoided because of hoisting.

In this blog we have learnt about

- Why to avoid `var`.
- What `hoisting` in javascript is.
- What Immediately Invoked Function Expression (IIFE) is and how to use it.
- How to decide between using let and const.


## Conclusion

I hope this post saved your time and life. If you liked the post, feel free to share it to help others find it!

You may also want to read <a href="https://pratapsharma.in/getting-started-with-git/" target="_blank">Getting Started with Git - A beginner's guide</a>

You may also follow me on <a href="https://www.linkedin.com/in/prataps22/" target="_blank">LinkedIn</a> and <a href="https://twitter.com/Pratap2210" target="_blank">Twitter</a>.

💌 If you’d like to receive more tutorials in your inbox, you can sign up for the newsletter [here](https://pratap.substack.com).