Stars
JavaScript Var vs Let vs Const: Key Differences & Best Uses
calendar01 Sep 2024
read10 minute read

JavaScript Var vs Let vs Const: Key Differences & Best Uses

Introduction

Variables are a cornerstone of JavaScript, allowing developers to store and manage data efficiently. Over time, JavaScript introduced new ways to declare variables, moving beyond the traditional var with the addition of let and const in ES6. Understanding the differences between JavaScript var vs let vs const is crucial for writing modern, clean, and bug-free code. In this blog, we’ll explore these differences, their best use cases, and practical examples to guide you in choosing the right one for your needs.

Understanding var

In JavaScript, var was the original way to declare variables. It is function-scoped, meaning a var variable is only accessible within the function where it is declared. If declared outside a function, it becomes global. Unlike let and const, which are block-scoped, var does not respect block boundaries (e.g., within if or for blocks).

Another notable feature of var is hoisting, where declarations are moved to the top of their scope during execution. This allows referencing a var variable before its declaration, though its value will be undefined until assigned.

Example of Hoisting:

console.log(x); // Outputs: undefined
var x = 5;
console.log(x); // Outputs: 5

In this example, x logs as undefined before it's declared due to hoisting, where var x is treated as if it's moved to the top of its scope.

Issues with var: Accidental Globals and Re-declaration

One of the common pitfalls with var is the accidental creation of global variables. If you forget to use var in a function, JavaScript will create a global variable, which can lead to unexpected behavior.

function setValue() {
    value = 10; // Accidentally creates a global variable
}
setValue();
console.log(value); // Outputs: 10 (global variable created unintentionally)

Another issue is that var allows re-declaration within the same scope, which can lead to hard-to-track bugs:

var x = 10;
var x = 20;
console.log(x); // Outputs: 20

Here, the variable x is re-declared and assigned a new value, potentially overwriting the previous value without any warning.

When to Use var

  • Suitable for maintaining older legacy codebases where refactoring is not feasible.
  • Use when function-level scoping is explicitly required instead of block scoping.
  • In rare scenarios where maximum browser compatibility with older environments is needed.

Understanding let

Introduced in ES6, let is a block-scoped variable declaration, meaning it is confined to the block (e.g., a loop or conditional) in which it is defined. Unlike var, which is function-scoped and accessible throughout an entire function, let ensures variables are only accessible within their specific block. This behavior helps prevent errors caused by variables being unintentionally accessed outside their intended scope, making your code cleaner and more predictable.

Example of let in a Loop:

for (let i = 0; i < 3; i++) {
    console.log(i); // Outputs 0, 1, 2
}
console.log(i); // ReferenceError: i is not defined

In this example, i is only accessible within the loop due to block scoping.

Comparison with var:

if (true) {
    var x = 10;
    let y = 20;
}
console.log(x); // Outputs 10 (function-scoped)
console.log(y); // ReferenceError: y is not defined (block-scoped)

Here, x is accessible outside the if block due to var's function scope, while y is not accessible outside the block due to let's block scope.

When to Use let

  • Use for variables that should only exist within a specific block, such as inside loops or conditionals.
  • Choose when the variable's value will change over time, such as in iterative processes.
  • Prevent unintended behavior caused by hoisting, as it does not allow access before declaration.

Understanding const

const, introduced in ES6, is a block-scoped declaration similar to let but used for variables that should not be reassigned. Once a const variable is assigned a value, it cannot be reassigned, making it ideal for constants or values meant to remain unchanged.

However, const enforces immutability only on the variable binding, not the value itself. For objects or arrays declared with const, their properties or elements can still be modified, though the reference cannot be reassigned.

Example with Primitive Values

const myNumber = 10;
myNumber = 20; // Error: Assignment to constant variable.

In this example, trying to reassign the value of myNumber results in an error because const does not allow reassignment.

Example with Objects/Arrays

const myArray = [1, 2, 3];
myArray.push(4); // Allowed
console.log(myArray); // Output: [1, 2, 3, 4]

const myObject = { name: "John" };
myObject.name = "Doe"; // Allowed
console.log(myObject); // Output: { name: "Doe" }

Even with const, the contents of myArray and myObject can be modified. The const keyword only prevents reassignment of the variable, not the mutability of the data within the object or array.

When to Use const

  • Use const by default for variables that do not require reassignment.
  • Ideal for defining constants or fixed values to prevent unintended changes.
  • Helps reduce bugs by signaling variables intended to remain constant.
  • Use let only when a variable's value needs to change.

Comparing var, let, and const

Key Differences:

Featurevarletconst
ScopeFunction-scopedBlock-scopedBlock-scoped
HoistingHoisted (initialized as undefined)Hoisted (but not initialized)Hoisted (but not initialized)
Re-declarationAllowed within the same scopeNot allowed in the same scopeNot allowed in the same scope
ImmutabilityMutableMutableImmutable binding, but mutable contents for objects/arrays

Best Practices

In modern javascript var vs let vs const , developers favor  const and let over var for more predictable, maintainable, and bug-free code. Here are some best practices:

  • Use const by Default: Always default to const for variables that don’t need to be reassigned. It ensures clarity in your code, prevents accidental changes, and signals to others that the value remains constant throughout its lifecycle.
  • Use let for Reassignment: Opt for let when you know a variable’s value will change, such as in loops or conditions. It combines flexibility with block-scoping, reducing the risk of variables leaking out of their intended scope.
  • Avoid var: Avoid using var in modern JavaScript due to its function-scoping, hoisting, and redeclaration issues, which can lead to unpredictable behavior. Use it only when working with or maintaining legacy codebases.

Sample Refactor: Converting var to let and const 

Here’s a simple example of refactoring older javascript var vs let vs const code that uses var to a more modern approach with let and const
Before Refactoring:

function calculateTotal(prices) {
var total = 0;
for (var i = 0; i < prices.length; i++) {
    var price = prices[i];
    total += price;
}
var discount = 0.1;
var finalTotal = total - (total * discount);
return finalTotal;
}

After Refactoring:

function calculateTotal(prices) {
let total = 0;
for (let i = 0; i < prices.length; i++) {
 const price = prices[i]; // price doesn't change within the loop
    total += price;
}
const discount = 0.1; // discount remains constant
const finalTotal = total - (total * discount); // finalTotal doesn't change after calculation
return finalTotal;
}

In the refactored version, let is used for total as it changes, while const is used for price, discount, and finalTotal since they remain constant. This ensures clearer, more robust code, aligning with JavaScript var vs let vs const best practices.


Code Examples

Example of Scope:

function scopeTest() {
    if (true) {
        var a = 1;
        let b = 2;
        const c = 3;
    }
    console.log(a); // Outputs 1 (function-scoped)
    console.log(b); // ReferenceError: b is not defined (block-scoped)
    console.log(c); // ReferenceError: c is not defined (block-scoped)
}
scopeTest();

In this example, var is function-scoped, so a is accessible outside the if block. However, let and const are block-scoped, so b and c are not accessible outside the block they were defined in.

Example of Re-declaration

var x = 20; // No error, x is now 20

let y = 10;
let y = 20; // Error: Identifier 'y' has already been declared

const z = 10;
const z = 20; // Error: Identifier 'z' has already been declared

With var, re-declaring the same variable is allowed and updates its value. In contrast, both let and const do not permit re-declaration within the same scope, resulting in an error if attempted.

Example of Immutability:

myArray.push(4); // Allowed
console.log(myArray); // Output: [1, 2, 3, 4]

myArray = [4, 5, 6]; // Error: Assignment to constant variable

In this case, const prevents the reassignment of the variable myArray, which would result in an error. However, the contents of the array can still be modified, such as adding a new element.

Common Pitfalls and How to Avoid Them

When working with javascript var vs let vs const, developers often encounter common pitfalls that can lead to bugs or unexpected behavior. Understanding these pitfalls and knowing how to avoid them is crucial for writing clean, reliable code.

Accidental Global Variables with var

One of the most common mistakes with var is accidentally creating global variables. This happens when a var declaration is omitted inside a function or block, causing the variable to be attached to the global object.

function calculate() {
    total = 100; // No var/let/const declaration, creates a global variable
}
calculate();
console.log(total); // Outputs 100, but total is now global!

How to Avoid: Always use let or const when working with JavaScript var vs let vs const to ensure proper block or function scoping and avoid unintended global variables.

Hoisting Confusion with var

var is hoisted to the top of its scope, but only the declaration is hoisted, not the assignment. This can lead to confusing behavior if you try to use the variable before it is assigned.

console.log(name); // Outputs undefined
var name = "Alice";

 Use let or const, which are also hoisted but not initialized. This prevents variables from being accessed before they are defined, reducing the chance of errors.

Re-declaration with var

var allows for re-declaration within the same scope, which can lead to unexpected overwrites and bugs, especially in larger functions.

var count = 10;
var count = 20; // No error, but original value is lost

How to Avoid: Avoid using var. Among javascript var vs let vs const , Use let or const instead, which do not allow re-declaration within the same scope.

Misunderstanding const with Objects and Arrays

Many developers assume that const makes the entire object or array immutable, but in reality, it only prevents reassignment of the variable. The contents of the object or array can still be modified.

const person = { name: "Alice" };
person.name = "Bob"; // Allowed, object properties can be modified

person = { name: "Charlie" }; // Error: Assignment to constant variable

How to Avoid: const applies to the variable binding, not the value. For truly immutable objects or arrays, use Object.freeze() or libraries designed for immutability.

Scope Misconceptions with let and const

Developers may incorrectly assume that variables declared with let or const are accessible outside of the block they were defined in, similar to var.

if (true) {
    let x = 10;
}
console.log(x); // ReferenceError: x is not defined

Always be aware of the block scope when using let and const. If you need a variable to be accessible in a wider scope, declare it outside the block.

By understanding these common pitfalls and using var, let, and const appropriately, you can avoid many of the issues that commonly arise in JavaScript development. This leads to cleaner, more maintainable, and less error-prone code.

Conclusion

In this blog, we've explored the key differences between javascript var vs let vs const—the three primary ways to define variables in JavaScript. We've seen how var is function-scoped and hoisted, but its quirks can lead to unintended behavior. On the other hand, let and const, introduced in ES6, offer block-scoping and greater predictability, making them the preferred choices for modern javascript var vs let vs const development.

For further reading and to deepen your understanding of JavaScript var vs let vs const, check out the following resources:

MDN Web Docs: var

MDN Web Docs: let

MDN Web Docs: const

Understanding when and how to use javascript var vs let vs const is crucial for writing clean, efficient, and bug-free code. By defaulting to const, using let only when necessary, and avoiding var in new code, you can avoid many common pitfalls and improve the maintainability of your projects.

Code Icon
Fasttrack Frontend
Development using CodeParrot AI
Background
CodeParrot Logo

CodeParrot

Ship stunning UI Lightning Fast

Y Combinator

Resources