Variables in Javascript: A Comprehensive Guide to Var, Let, and Const
Tags: javascript, variables, beginners, programming
Published: 2024-01-22 08:00:00

In software, a variable is a symbolic name that represents a _value_ or a _reference to a value_. It's a way to store information that can be reused and manipulated throughout your program. You can think of a variable like a label or even a sign pointer - it represents the data (which can potentially change) but is not the actual data itself. 

I am often reminded of that great scene in the Bruce Lee movie, "Enter the Dragon", where he tells his student that "it is like a finger pointing the way to the moon - don't concentrate on the finger, or you will miss all of that heavenly glory." The variable is important, but what it represents is actually what you care about.
{% embed https://www.youtube.com/watch?v=4O9o4CKTGzQ&t=74s %}

Ok, maybe that's a little bit of a stretch, but you get the idea. Variables are essential building blocks in JavaScript programming, allowing developers to store and manipulate data. There are 3 main ways to declare a variable, and your choice can have significant implications on your code's behavior and maintainability. Many developers just choose one and use it for everything, but that's just lazy and can sometimes cause problems.

Let's explore these three methods of variable declaration in JavaScript: `var`, `let`, and `const`, diving into when and why to use each, along with their respective advantages and drawbacks.

1\. `var`: Function-Scoped Variables
------------------------------------

In JavaScript, `var` is a keyword used to declare a variable. It has some specific behaviors that set it apart from other variable declaration keywords like `let` and `const`.

Here's what you need to know about `var`:

1.  **Function Scope**: Variables declared with `var` are function-scoped, meaning they are accessible within the function where they were declared (or globally if declared outside any function).
2.  **Hoisting**: Unlike `let` and `const`, variables declared with `var` are "hoisted" to the top of their containing function or global scope. This means that they are technically available from the beginning of that scope, but their value will be `undefined` until the code where they are assigned is executed.
3.  **Reassignment**: You can reassign new values to a variable declared with `var`.
4.  **Redeclaration**: In non-strict mode, you can redeclare a variable using `var` in the same scope without getting an error, which is not allowed with `let` and `const`.
5.  **No Block Scope**: `var` does not respect block scope (such as inside an `if` statement or a loop), which can sometimes lead to unexpected behavior. If you declare a variable with `var` inside a block, it's actually available to the entire surrounding function or global scope.

Because of these peculiarities, and with the introduction of `let` and `const` in ES6 (ECMAScript 2015), the use of `var` has become less common in modern JavaScript, and it's often recommended to use `let` or `const` instead for clearer scoping rules and better maintainability.

### When to Use

*   You need a variable with function-level scope.
*   You are working with older code that doesn't support ES6.
*   Typically, you should avoid `var`, but it can be handy in some cases.

#### Pros

*   **Function Scope:** Variables are accessible within the entire function where they're declared.
*   **Hoisting:** Variables are moved to the top of their scope and initialized with `undefined`, allowing them to be referenced before declaration.

#### Cons

*   **Lack of Block Scope:** Variables can be accessed outside the block they were declared in, leading to potential bugs.
*   **Hoisting Quirks:** Can cause confusion as variables are available before their declaration.

#### Example
``` javascript
    function varExample() {
      console.log(x); // undefined, because of hoisting
      var x = 10;
      console.log(x); // Output: 10
      
      if (true) {
        var x = 20; // Same variable, even though it's in a different block
      }
      
      console.log(x); // Output: 20, because var does not have block scope
    }
```

2\. `let`: Block-Scoped Variables
---------------------------------

So, if we had `var`, why did we need something else? The reason why the `let` keyword was introduced to javascript was because _function_ scope is confusing and this led to a number of bugs and errors. `let` was was introduced in ES6 (ECMAScript 2015) as an alternative to var, with some key differences in behavior:

1.  **Block Scope**: Unlike var, variables declared with let are block-scoped, meaning they are only accessible within the block in which they were declared (e.g., inside an if statement or a loop).
2.  **No Hoisting**: Although let declarations are hoisted, the variables are not initialized until the code execution reaches the declaration. Attempting to access the variable before its declaration will result in a ReferenceError.
3.  **Reassignment**: Like var, you can reassign new values to a variable declared with let.
4.  **No Redeclaration**: In strict mode, you cannot redeclare a variable using let in the same scope.

### When to Use

*   You need a variable with block-level scope.
*   You expect to reassign the variable within its scope.
*   Probably should be your default method for creating variables.

#### Pros

*   **Block Scope:** Variables are only accessible within the block where they're declared, reducing potential errors.
*   **No Hoisting Issues:** Variables are not initialized until the code execution reaches the declaration.

#### Cons

*   **More Limited Scope:** Might require more careful planning of where the variable is declared.

#### Example

``` javascript
    function letExample() {
    	console.log(x); // ReferenceError, because it doesn't exist yet (no hoisting)
    	let x = 10;
    
    	if (true) {
      		let x = 20; // Different variable because it's in a different block
      		let y = "I see how it works";
    	}
    	
    	console.log(x); // Output: 10, because we are in the block for the original variable
    	console.log(y); // ReferenceError, because y is block-scoped
    }
```


3\. `const`: Block-Scoped Immutable References
----------------------------------------------

The `const` keyword, which, like `let`, was introduced in ES6 (ECMAScript 2015). It has similarities to `let`, but with some unique characteristics:

1.  **Block Scope**: Just like `let`, variables declared with `const` are block-scoped.
2.  **No Hoisting**: Similar to `let`, `const` declarations are hoisted, but accessing them before their declaration in the code results in a ReferenceError.
3.  **No Reassignment**: Unlike `var` and `let`, once a variable is assigned with `const`, it cannot be reassigned. Attempting to do so will result in a TypeError.
4.  **No Redeclaration**: You cannot redeclare a variable using `const` in the same scope.
5.  **Must Be Initialized**: A `const` declaration must be initialized with a value at the time it's declared.

### When to Use

*   You want to declare a variable that should not be reassigned.
*   You need block-level scoping.

#### Pros

*   **Immutable Reference:** Prevents reassignment, making the code more predictable.
*   **Block Scope:** Like `let`, variables are only accessible within the block where they're declared.

#### Cons

*   **Not Fully Immutable:** Only the reference is constant, not the object itself. If the variable is an object, its properties can still be altered.

#### Example

``` javascript
    function constExample() {
    	if (true) {
    		console.log(PI); // ReferenceError, because it doesn't exist yet (no hoisting)
    		const PI = 3.14159;
    		PI = 3; // Error: Assignment to constant variable
    	}
    	console.log(PI); // ReferenceError, because PI is block-scoped
    	
    	const obj = { value: 5 };
    	obj.value = 10; // This is fine because object properties can be changed
    	obj = { value: 20 }; // TypeError, reassignment not allowed
    }
```


Conclusion
----------

In modern JavaScript development, understanding the appropriate use of `var`, `let`, and `const` is crucial. While you can safely plan to use `let` most of the time, it is important to understand how block scope works so you know when it makes sense.  

*   Use `var` for function-level scope, mainly when dealing with **older code** or specific scoping needs.
*   Utilize `let` when block-level scope is required, and you **expect the value to change within the block**.
*   Opt for `const` when you want to ensure that the reference to a **value stays constant within a block scope**.

By carefully choosing the right declaration method, developers can write code that is not only more readable but also more resilient and less prone to errors and unexpected behavior. It is usually better to hit scope-related errors earlier (more strict) than later (less strict).