Back to the roots - A var, let and const story
Tags: javascript, webdev, typescript, beginners
Published: 2021-10-19 15:36:56

### An endless story, yeah? Oke, let's start with some introduction

If you ask someone why sometimes JS is so confusing, probably one of the reasons is **var**:weary: declaration. 

That was my experience too in 2017 when I had my first contact with JS. It was post-ES6(ES2015), which means the **let** and **const** were there. 
I thought: *"lucky me, var is history and now we live in a new era"* :raised_hands:. Guess what happened? Yeah, I was hit by a var bug in the face. TKO :punch::dizzy_face:, not stand a chance.

It's true that with ES2015 we have great alternatives for declarations in **let**:fire: and **const**:fire:, but it is also important to know how **var** works (and pray we do not go into it :pray:	).

Now, why are let and const such a great option? Well, let's see! :point_down:


### Scope

:point_right: Let's try to understand it first: in a few words, **scope** represents where these variables are available for use. 

- **var**

Variables defined with var have **global** or **function** scope.

Global scope -> when they are defined outside any function and are available in the whole window

Function scope -> when they are defined inside a function and are available inside that function

```javascript
var globalScope = 'global';

function varFcn() {
  var functionScope = 'function';
  console.log(globalScope); // -> 'global'
  console.log(functionScope); // -> 'function'
}

console.log(globalScope); // -> 'global'
console.log(functionScope); // -> Uncaught ReferenceError: functionScope is not defined
```

- **let**

Let declarations have **block scope**. What is a block? Well, a block is a code between {} - anything between curly braces is a block. 

Here is a comparison example to better understand the difference:

```javascript
var foodWithVar = 'salad';

if (true) {
  var drinkWithVar = 'beer';
}

console.log(foodWithVar); // -> 'salad'
console.log(drinkWithVar); // -> 'beer'

// Versus let declaration

let food = 'salad';

if (true) {
  let drink = 'beer';
}

console.log(food); // -> 'salad'
console.log(drink); // -> 'Uncaught ReferenceError: Can't find variable: drink'
```

- **const**

Is the same as variables declared with let.



### Hoisting

:point_right: Hoisting is a Javascript voodoo:mage: where variables and functions declarations are moved to the top of their scope before the execution. 

- **var** 

Besides being **hoisted**, the var variables are also **initialized with undefined**.

```javascript
console.log(food); // -> undefined
var food = 'pizza';
console.log(food); // -> 'pizza'

// The code above is interpreted like this:

var food; // default value for var declaration is 'undefined'
console.log(food); // -> undefined 
food = 'pizza';
console.log(food); // -> 'pizza'
```

- **let**

Declarations with let are also **hoisted**, but unlike a var, they are **not initialized with undefined**.

```javascript
console.log(food); // -> Uncaught ReferenceError: Cannot access 'food' before initialisation"
let food = 'pizza';
console.log(food); // -> 'pizza'

// The code above is interpreted like this:

let food; // let declaration has no default value
console.log(food); // -> Uncaught ReferenceError: Cannot access 'food' before initialisation"
let food = 'pizza';
console.log(food); // -> 'pizza'
```

- **const**

Is the same as variables declared with let.

### Redeclaration and reassignment

- **var** 

:heavy_exclamation_mark: I will say just this: var variables can be **redeclared**! :confused:

```javascript
var food = 'pizza';
var food = 'salad';

console.log(food); // -> 'salad'
// This is madness! Who wants salad instead of pizza...?
```

Also, vars can be **reassigned**.

:point_right: One thing I found out from a colleague is that in the pre-ES6 era, var redeclaration was used as a safety measure for controlling the value of the variable. Or to make sure the value is "clean". Seems like a nice hack, but also... strange, right?

- **let**

Let variables can **not be redeclared**, but can be **reassigned**. :partying_face:

```javascript
// Redeclaration not working
let food = 'salad';
let food = 'steak'; // SyntaxError: Identifier 'food' has already been declared

// Reassignment is working
let drink = 'tea';
drink = 'beer';
```

- **const**

Const variables can not be redeclared nor reassigned.

```javascript
const drink = 'tea';
drink = 'beer'; //TypeError: Assignment to constant variable.

const food = 'salad';
const food = 'steak'; // SyntaxError: Identifier 'food' has already been declared
```

But here is something interesting: :point_right: if you have an object declared with const you can modify his properties.

```javascript
const meal = {
  food: 'pizza',
  drink: 'cola'
};
meal.drink = 'pepsi';
meal.dessert = 'cake';
console.log(meal);
/*
{
  dessert: "cake",
  drink: "pepsi",
  food: "pizza"
}
*/

const meals = ['lunch'];
meals.push('dinner');
console.log(meals);
/*
["lunch", "dinner"]
*/
```


### Sort of conclusion

Look, I am not saying you should or should not use var. But, you need to be extra careful when using var because the math is not lying: 
*function scope + hoisting + redeclaration === :exploding_head:*

Don't believe me? Check this simple example:
```javascript
var food = 'salad';

if (true) {
  var food = 'burger';
}

console.log(food); // -> 'burger'
```
:rotating_light: So, *food* was re-declared and modified. That is a real problem (besides having burgers all the time not being very healthy). If you have used *food* in other parts of the code, you could be surprised by the output you might get. That can cause a lot of bugs in the code.

That is just one of many examples of how wrong things can go *when using var without knowing how it works*. :sos:

Also, var is common in legacy code. And if you don't know how let and const works, maybe it's easy to go with var. But, for me, let and const are the way to go and I encourage you to give them a try.

Well, I guess that's it for now. **May the let-const be with you!** Cheers :beers: