What is up with var, let and const? What the hell is the difference between these three?
Tags: javascript
Published: 2021-08-17 15:56:24

With ES2016 came two new methods to declare variable i.e. `let` and `const`. Before that the developers had access to only `var`(I feel bad for them, no kidding). 

So, what's the catch here? Why are there three different ways to declare variables? Wasn't JavaScript already confusing enough and now they're making it more confusing.

Before we can understand how `var` and `let/const` differ we need to understand a computer science-y concept called `scope`.


## Function scope vs Block Scope

JavaScript comes with two kinds of scope i.e Function scope and block scope. Let's have a look at the difference in both of them.

### Function Scope
```
function myFn() {
  var foo = 'peekaboo!';
  
  console.log(foo); // 'peekaboo!'
}

console.log(foo); // ReferenceError: foo is not defined
```

Variables are function-scoped when using var because their visibility is restricted to the function. You'll get an error if you try to utilise it outside of the function.

### Block Scope

```
if (true) {
  var foo = 'peekaboo!';
  let bar = 'i see u';
  const baz = 'baby blue!';

  console.log(foo); // 'peekaboo!';
  console.log(bar); // 'i see u';
  console.log(baz); // 'baby blue!';
}

console.log(foo); // 'peekaboo!';
console.log(bar); // ReferenceError: bar is not defined
console.log(baz); // ReferenceError: baz is not defined
```

Notice the visibility of foo isn’t limited by the if-statement block. However, both `bar` and `baz` are limited in visibility to the block of code.

This concept of scope is the most prominent distinction between the old-fashioned `var` and modern `let/const`.



![image](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pbhe41h74iecbev8p1r6.png)
 
Source: https://twitter.com/mpjme

## VAR

Let's have a look at the following code snippet

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

console.log(i);
```

According to you what will be the output of the following program??
If you said 

```
//0
//1
//2
//3
```
then you're absolutely correct.

The variable `i` is accessible outside of the for-loop. This is expected since variables defined with var have a function scope rather than a block scope i.e they're accessible within the whole function in which they are defined in.

If it's so cool then what's the problem with using var? Why aren't we using it?

I'll use the example below to explain:
```
    var greeter = "hey hi";
    var times = 4;

    if (times > 3) {
        var greeter = "say Hello instead"; 
    }
    
    console.log(greeter) // "say Hello instead"
```
So, since `times > 3` returns `true`, greeter is redefined  to "say Hello instead". While this is not a problem if you knowingly want greeter to be redefined, it becomes a problem when you do not realise that a variable greeter has already been defined before.

If you have used greeter in other parts of your code, you might be surprised at the output you might get. This will likely cause a lot of bugs in your code. This is why let and const are necessary.

In layman terms, `var` can be redefined and it's values can also be changed?

So Shubhra, what can we do to save ourselves from making such blunder in production code???

Well, worry not, the people in the JavaScript headquaters knew that you would be having this problem and already gave a solution for this.

Here comes `let` to save the day.

## LET

In many ways `let` is like a cousin of `var`. It has a lot of similarities but differentiates in ways that makes ES2016 a more modern-feeling language.

Let us take the same example we took in `var`

```
for (let i = 0; i < 3; i++) {
  console.log(i);
}

console.log(i);
```

This time what do you think the output is going to be?? Well if you said

```
//0
//1
//2
//ReferenceError: i is not defined
```
then you're in luck.

Hey Shubhra, if `let` is a cousin of `var` then why is it coming undefined? 
Let me tell you, so `let` is blocked scope instead of being function scoped.

### let can be updated but not re-declared.
Just like `var`,  a variable declared with `let` can be updated within its scope. Unlike `var`, a `let` variable cannot be re-declared within its scope. So while this will work:
```
    let greeting = "say Hi";
    greeting = "say Hello instead";
```
this will return an error:
```
    let greeting = "say Hi";
    let greeting = "say Hello instead"; // error: Identifier 'greeting' has already been declared
```
However, if the same variable is defined in different scopes, there will be no error:
```
    let greeting = "say Hi";
    if (true) {
        let greeting = "say Hello instead";
        console.log(greeting); // "say Hello instead"
    }
    console.log(greeting); // "say Hi"
```
Why is there no error? 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`, you don't have to bother if you have used a name for a variable before as a variable exists only within its scope.

Also, since a variable cannot be declared more than once within a scope, then the problem discussed earlier that occurs with `var` does not happen.

## CONST

The keyword `const` is an abbreviation for constant. Similar to `let`, it’s block-scoped, however, you can’t reassign it.

What do you think is the output of this code?

```
const myBoolean = true;

if (myBoolean) {
  const turtles = [
    'leonardo',
    'donatello',
    'michaelangelo',
    'raphael'
  ];
  // turtles = turtles.concat('Shredder');  // 🙅‍♀️ this would throw an error

  console.log(turtles);
}

console.log(turtles);
 ```

The output 
```
// ['leonardo', 'donatello', 'michaelangelo', 'raphael']
// ReferenceError: turtles is not defined
```

Because the `const` is not transferred in this scenario, items can still be added to a const variable that links to an array or an object.
This is a topic for another blog. I will discuss it later.

## Conclusion

Because function-scope isn't as evident as block-scope, it's best to avoid using `var`. The objective of ES2016-2019 appears to be to replace `var` with `let/const` because they encourage better code habits.

If you need to construct a variable, you should usually use const. Use let instead if you know or suspect you'll need to reassign it (for-loops, switch statements, algorithm swapping).