# Variable Declaration in JavaScript: A Comprehensive Guide

Declaring variables is what we do most in JavaScript. Knowing the inside of the variable declaration process gives you more idea about it. For example, if you are new to JavaScript, the behavior of `var` statement likely to be confusing for you.

Through this article, you will learn how to declare, and mutate variables using `var`, `let`, and `const` statements, and have a better understanding of the differences between them.

I will explain each concept in two parts:

1. Before ES6 (`var` statement)
    
2. After ES6 (`let` and `const` statements)
    

**Let's dive into these statements:**

## Declaring Variables with Hoisting in Mind

When you declare variables in your app, the interpreter moves them to the top of their scope and allocates places in the memory before the execution starts. This process is called **Hoisting**.

### **1\. Variable declaration with** `var` **statement:**

When you declare a variable with `var` statement, it is initialized in the memory as `undefined` before the code execution. So, you can use the variable before declaring it, but it returns `undefined`.

When execution starts and reaches the line that the variable is declared, replaces the value in the memory with the value of the variable.

```javascript
console.log(strawberry); // undefined

var strawberry = '🍓';

console.log(strawberry); // 🍓
```

With this behavior, the program runs without errors. However, in some cases, this can lead to unexpected results.

### **2\. Variable declaration with** `let` **and** `const` **statements:**

When you declare a variable with `let` or `const` statements the variable is allocated in the memory as **uninitialized** in the *temporal dead zone*. You cannot use variables in the *temporal dead zone* before their declaration. So, if you try to use a variable before declaring it, the program returns an error.

When the program reaches the line where the variable is declared, it initializes the variable with that value.

```javascript
console.log(cherry); // ReferenceError

const cherry = "🍒";

console.log(cherry); // 🍒
```

If you try to run this code snippet, you will see an error similar to below. Because we try to access a variable in the *temporal dead zone*.

![ReferenceError: Cannot access 'cherry' before initialization](https://cdn.hashnode.com/res/hashnode/image/upload/v1686747528090/a420f21e-cd58-404d-8de1-b07a6ef99ce3.png align="center")

## Understanding Variable Scopes

In JavaScript:

* Everything between curly braces is *block scope*,
    

![A code snippet screenshot visualizes the block scope term in JavaScript.](https://cdn.hashnode.com/res/hashnode/image/upload/v1686751970366/36dbfa36-7edc-4e18-b9f3-20fce69a4767.png align="center")

* Everything inside a function is *function scope*.
    

![A code snippet screenshot visualizes the function scope term in JavaScript.](https://cdn.hashnode.com/res/hashnode/image/upload/v1691122652143/e12f1b1a-17ca-435c-9514-de21e51caff3.png align="center")

### **1\. Scope of** `var` **statement**

Variables declared with `var` statement are available globally. (If they are not declared in a function.) So, you can use the variables declared inner scope is in outer scopes and vice-versa:

```javascript
// Global Scope
var carrot = "🥕";

// Inner Scope
{
  console.log(carrot); // 🥕

  console.log(tomato); // undefined

  // More Inner Scope
  {
    console.log(carrot); // 🥕

    var tomato = "🍅";
  }

  console.log(tomato); // 🍅
}
```

As you can see from the code snippet:

1. We were able to use the `carrot` variable declared in the most outer (global) scope in the inner scopes.
    
2. We were able to use `tomato` variable declared in the inner scope in the outer scopes.
    

❗ Variables declared with `var` statement in a function are only available in the *function scope*, and cannot be used outside of it.

```javascript
// Function Scope
function declareMelon() {
  var watermelon = "🍉";
}

console.log(watermelon); // ReferenceError
```

### **2\. Scope of** `let` **and** `const` **statements:**

The variables declared with `let` and `const` statements are only available in *block scope*.

```javascript
const banana = "🍌";

// Block Scope
{
  console.log(banana); // 🍌

  let lemon = "🍋";

  // Inner Block Scope
  {
    console.log(banana); // 🍌
    console.log(lemon); // 🍋
  }
}

console.log(lemon); // ReferenceError
```

As you can see in the last line, you cannot use a variable created in the inner scope in the outer scopes.

![ReferenceError: lemon is not defined](https://cdn.hashnode.com/res/hashnode/image/upload/v1686814208553/7a633e42-44df-4055-8af4-e0ac58201806.png align="center")

## Mutating Variables

This time the parts will change, the first group involves `var` and `let` statements and the second involves `const` statement. Because `var` and `let` statements are mutable, and `const` statement is immutable.

### **1\. Mutation in** `var` **and** `let` **statements.**

As I said `var` and `let` statements are mutable, so you can assign new values to the variables declared with them.

```javascript
var pepper = "🌶️";
let apple = "🍏";

pepper = "🫑";
apple = "🍎";

console.log(pepper); // 🫑
console.log(apple); // 🍎
```

Additionally, you can mutate a variable from inner scopes:

* For `let` statement, the variable will change in the scope where the declaration is made.
    
* For `var` statement, the variable will change globally. (or in *functional scope.*)
    

```javascript
{
  pepper = "🌶️";
  apple = "🍏";

  console.log(pepper); // 🌶️
  console.log(apple); // 🍏
}

console.log(pepper); // 🌶️
console.log(apple); // 🍏
```

### **2\. Mutation in** `const` **statement**

Variables declared with `const` statement are immutable. So you cannot re-assign them.

```javascript
const strawberry = "🍓";

strawberry = "🍉"; // TypeError
```

If you try to run the code snippet above, the program throws an error similar to below:

![TypeError: Assignment to constant variable.](https://cdn.hashnode.com/res/hashnode/image/upload/v1687697471389/1a7b0d00-407e-46de-a420-356f4e0c61e3.png align="center")

**❗Important Note: You cannot mutate arrays and objects via assignment but can mutate them via their methods, and property assignment.**

```javascript
const fruitsArray = ["🍎", "🍐"];
const fruitsObject = {
  apple: "🍎",
  pear: "🍐",
};

fruitsArray[2] = "🍒"; // [ '🍎', '🍐', '🍒' ]
fruitsArray.push("🍌"); // [ '🍎', '🍐', '🍒', '🍌' ]

fruitsObject.cherry = "🍒"; // { apple: '🍎', pear: '🍐', cherry: '🍒' }
```

## Redeclaring Variables

Strangely, we can redeclare variables declared with `var` statement using the same name. This is another error-prone characteristic of `var` statement. Fortunately, this behavior has changed with `let` and `const` statements.

### **1\. Redeclaration with** `var` **statement:**

You can redeclare a variable declared with `var` statement in the same scope or inner-outer scopes.

As I said before, variables declared with `var` statement are global, so if you even redeclare a variable in the inner scope (again, except for functional scopes), the variable will change in all scopes.

```javascript
var pepper = "🌶️";

console.log(pepper); // 🌶️

// Inner Scope
{
  var pepper = "🥦";

  console.log(pepper); // 🥦
}

console.log(pepper); // 🥦
```

As you can see in the code snippet, This behavior tends to cause big problems. Because someone working in the same codebase, unintentionally may declare a variable using the same name used before.

### **2\. Redeclaration with** `let` **and** `const` **statements:**

You cannot redeclare variables declared with `let` or `const` statements in the same scope. If you try the program throws an error.

```javascript
let eggplant = "🍆";

let eggplant = "🥔"; // SyntaxError
```

But you can redeclare the variables in inner scopes. Because, as I said before, the variables declared with `let` and `const` statements are *block scope* and don't affect the outer scopes.

```javascript
const carrot = "🥕";

// Block Scope
{
  const carrot = "🍒";

  console.log(carrot); // 🍒
}

console.log(carrot); // 🥕
```

## Conclusion

Today ES6 statements are the default choice for variable declaration in JavaScript. Nevertheless, the `var` statement might still be encountered, especially in older apps. In this guide, you have learned the differences between `var`, `let`, and `const` statements, hoisting and scope in variable declaration.

Thank you for taking the time to read this article. If you have any questions, or thoughts feel free to comment.

See you in the next one!

---

## Stay in Touch

* [Twitter](https://twitter.com/femincan)
    
* [LinkedIn](https://www.linkedin.com/in/femincan)
    
* [GitHub](https://github.com/femincan)
    

## Resources

* [JavaScript Visualized: Hoisting](https://dev.to/lydiahallie/javascript-visualized-hoisting-478h) by *Lydia Hallie*
    
* [JavaScript Visualized: Scope (Chain)](https://dev.to/lydiahallie/javascript-visualized-scope-chain-13pd) by *Lydia Hallie*
    
* [Hoisting](https://developer.mozilla.org/en-US/docs/Glossary/Hoisting) by *MDN Web Docs*
