JavaScript: Var and Let
Tags: es6, javascript, newbie, programming
Published: 2021-03-13 22:53:27

---
title: "JavaScript: Var and Let"
published: true
description: "What are the main differences between var and let variables and how do they relate to the number of bugs in your code?"
canonical_ur: https://www.cadejo.dev/blog/javascript-var-and-let/
tags: es6, javascript, newbie, programming
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/c9ybqoz8ndh3vtg5fm7l.jpg
---

Today I want to take you on an adventure where we'll discover the key differences between `var` variables and `let` variables.  Many introductions to coding (in Javascript) usually start with `var` variables, but I believe you should move to `let` variables as soon as you can. You'll have fewer bugs, and a better programming experience. Let's do this!

First, I want to introduce the concept of **Scope**. A definition I love to use goes like this:

> Scope is the area of code where you can access a symbol

A symbol, in this context, can be a variable or a function. We say that a symbol is 'within scope' when you can safely use it without any errors. For example:

```jsx
var variable = 'Hello'; 
// We can log variable here because is within scope
console.log(variable);
```

Things become a little bit more interesting when you are dealing with functions:

```jsx
console.log(variable); // This will not work

function thisIsAFunction() {
    var variable = 1; 
    console.log(variable); // This will work
}

console.log(variable); // This will not work

thisIsAFunction();
```

Notice how the logs outside of the function will not work (i.e. the name `variable` is not within scope), but the log inside the function will work.

## Why is that?

`var` variables use what we know as **Function-based scope**. If you declare a `var` variable inside a function, the variable will be within scope everywhere inside the function.

*<a href="https://developer.mozilla.org/en-US/docs/Glossary/Hoisting" target="_blank">Hoisting</a> is going to slightly complicate where you can access your variable. In general, It's safer to use your `var` variable only after you declare it. We'll talk about hoisting in an upcoming article, so get excited!*

Now, let's add an if statement inside our function: 

```jsx
console.log(variable); // This will not work

function thisIsAFunction() {
    if(true === true) { // This is a simple if statement to avoid confusion
        var variable = 1;
        console.log(variable); // This works
    }
    console.log(variable); // This works
} 

console.log(variable); // This will not work
```

Our `var` variable is only within scope inside the function where it was declared. Notice how even though `variable` was declared inside an if statement, you can still use it outside the statement. That's function-based scope at play!

Now let's go full power and change our `var` variable into a `let` variable:

```jsx
console.log(variable); // This will not work

function thisIsAFunction() {
    if(true === true) { // This is a simple if statement to avoid confusion
        let variable = 1; 
        console.log(variable); // This works
    }
    console.log(variable); // This will not work
} 

console.log(variable); // This will not work

thisIsAFunction();
```

Notice how as soon as we change `var` to `let`, one more log stops working.  

## What's the difference between the log in line 6 and the log in line 8?

The difference is that they are in different **blocks**. If you are thinking 'Well, what's a block?, I've got you covered my friend. 

If you want to get super technical, a block is a "lexical structure of source code which is grouped together", but I like to introduce the concept as: 

> Block -  whatever is contained inside curly brackets: functions, loops, if statements, etc.

*Objects are a funny exception to the definition I just gave about curly brackets, but that's the only exception I know of.*

Let's think about the blocks we have in our current function

```jsx
console.log(variable);

function thisIsAFunction() { // Start of block A
    if(true === true) { // Start of block B
        let variable = 1; 
        console.log(variable);
    } // End of block B
    console.log(variable); 
} // End of block A

console.log(variable);

thisIsAFunction();
```

Since `variable` was defined inside block B, it can only be used inside block B (here comes the important point) and inside every block contained within B.

## Technically Speaking, variable is inside block A Right?. Why is the console.log breaking?

Great point. Block B is inside Block A, so technically `variable` was declared inside block A.

However, the scope resolution rule `let` uses is going to look for the closest enclosing block (that would be block b) and allow you to use the variable everywhere inside that block and every other block within it. 

Blocks containing that 'closest enclosing block' won't have access to `variable`

## So what would happen if we move variable before the if statement?

```jsx
console.log(variable);

function thisIsAFunction() { // Start of block A
    let variable = 1; 
    if(true === true) { // Start of block B
        console.log(variable);
    } // End of block B
    console.log(variable); 
} // End of block A

console.log(variable);

thisIsAFunction();
```

It would be accessible everywhere inside block A as that would be the closest enclosing block. Since block B is inside block A, it'll also be accessible inside block B. 


![blocks, blocks everywhere meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ck53zymw49o4pu5xgo1y.jpg)

## This seems like adding a bunch of rules on top of var. What's the point?

Great question! Blocks tend to be smaller than functions. Basing our scoping rules on smaller scopes will mean that a variable name is 'available' on a smaller area of code. 

A smaller area of code means it is less likely to change that variable by mistake. 

![we don't make mistakes, we make happyc bugs meme](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ek0t705nc0ke3crdlr3s.jpg)

## I get it! Anything 'else?

One last thing. `let` also has built-in protections to avoid re-declaring the same variable by mistake.

```jsx
let kali = 'is cute';

// LOTS OF CODE IN BETWEEN

let kali = 2; // This will break
```

As soon as you try to re-declare the name `kali`, you'll get an error along the lines of  `redeclaration of identifier kali`. 

On the other hand:

```jsx
var kali = 'is cute';

// LOTS OF CODE IN BETWEEN

var kali = 2; // This works just fine
```

`var` variables will let you re-declare the same name over and over without any complaint. You could end up overstepping on someone else's (or even your own) variables without even realizing it. That's another big reason to use `let` variables as much as you can.

## In Summary

- Scope is the area of the code where you can access a name.
- `var` variables use function-based scope. They can be used inside the function where they are defined.
- `let` variables use block-based scope. They can be used inside the block where they are defined.
- `let` variables will not let you re-declare the same name.

## Thanks!

Thank you very much for reading my article! I have a youtube video covering these topics if you would like a more interactive demo: https://youtu.be/kIJ2Jh7Qwso

If you like my content and would like me to help you in your coding journey, you should join my newsletter: https://www.cadejo.dev/free-updates/