var, let, and const in JavaScript


In JavaScript, variable declaration is an essential concept. The language provides three ways to declare variables: var, let, and const. While they may seem similar at first glance, each has distinct characteristics that affect how the variables behave, including scoping, hoisting, and mutability. Understanding the differences between these three is crucial for writing efficient, bug-free code.

var, let, and const in JavaScript

In this article, we'll explore how var, let, and const work, compare their behaviors, and identify best practices for using each.


1. The var Keyword

Before ES6 (ECMAScript 2015), var was the only way to declare variables in JavaScript. However, it has some quirks that can lead to unintended issues, especially in larger codebases.

Characteristics of var:

  • Function Scoped: Variables declared with var are function-scoped, meaning they are only available within the function they are declared in. If declared outside any function, they are globally scoped.
  • Hoisting: Variables declared with var are hoisted to the top of their scope (global or function scope). However, the initialization remains in its original position, leading to the possibility of accessing undefined before assignment.
  • Can be Re-declared: You can declare a variable using var multiple times within the same scope without errors, which can cause accidental overwriting.

Example:

function testVar() {
  console.log(x);  // Output: undefined (due to hoisting)
  var x = 10;
  console.log(x);  // Output: 10
}

testVar();

In the above example, the declaration of x is hoisted to the top of the function scope, but its value (10) is assigned only at the point of the var declaration.


2. The let Keyword

With the introduction of ES6, the let keyword was introduced to improve variable scoping in JavaScript. let resolves many of the issues that arise with var.

Characteristics of let:

  • Block Scoped: Variables declared with let are limited to the block, statement, or expression where they are defined. A block is defined by a pair of curly braces {}.
  • No Hoisting (in practical sense): Although technically hoisted, let variables are not initialized until they are declared in the code. Accessing them before declaration results in a ReferenceError.
  • Cannot be Re-declared in the Same Scope: Once a variable is declared using let in a scope, it cannot be re-declared in the same scope, preventing accidental overwriting of values.

Example:

function testLet() {
  // console.log(y);  // ReferenceError: Cannot access 'y' before initialization
  let y = 20;
  console.log(y);  // Output: 20
}

testLet();

Block Scope Example:

if (true) {
  let a = 30;
  console.log(a);  // Output: 30
}
// console.log(a);  // Error: 'a' is not defined

In this example, a is only accessible within the block (if statement). Once the block is exited, the variable a no longer exists.


3. The const Keyword

The const keyword was also introduced in ES6 and is used to declare variables whose value cannot be reassigned. However, it's important to note that const does not make the variable itself immutable—only the binding between the variable and its value is fixed.

Characteristics of const:

  • Block Scoped: Like let, const is block-scoped, meaning it is only accessible within the block in which it is declared.
  • No Reassignment: A variable declared with const cannot be reassigned after its initial declaration. However, for objects and arrays, the contents can still be modified.
  • Hoisting: const is also technically hoisted, but like let, it is not initialized until the point of declaration, resulting in a ReferenceError if accessed beforehand.

Example:

const z = 100;
console.log(z);  // Output: 100

// z = 200;  // TypeError: Assignment to constant variable

Using const with Objects and Arrays:

const person = { name: 'John', age: 30 };
person.age = 31;  // Allowed, since we're modifying the content, not reassigning the variable
console.log(person);  // Output: { name: 'John', age: 31 }

// person = {};  // TypeError: Assignment to constant variable

While you cannot reassign a const object, you can modify the properties of the object.


Key Differences Between var, let, and const

  1. Scope:
    • var: Function-scoped or globally scoped.
    • let: Block-scoped.
    • const: Block-scoped.
  2. Re-declaration:
    • var: Can be re-declared in the same scope.
    • let: Cannot be re-declared in the same scope.
    • const: Cannot be re-declared and must be initialized at the time of declaration.
  3. Reassignment:
    • var: Can be reassigned.
    • let: Can be reassigned.
    • const: Cannot be reassigned after the initial declaration.
  4. Hoisting:
    • var: Variables are hoisted and initialized with undefined.
    • let and const: Variables are hoisted but not initialized, causing a ReferenceError if accessed before declaration.

Best Practices for Using var, let, and const

  1. Use const by default: If a variable should not be reassigned, use const to declare it. This makes your code clearer and more predictable.
  2. Use let for mutable variables: If you know that a variable's value will change (e.g., in a loop or if the value depends on user input), use let.
  3. Avoid var: With the introduction of let and const, it is generally recommended to avoid var due to its unpredictable behavior with hoisting and re-declarations, which can lead to bugs.
  4. Prefer block scoping: Block-scoped variables (using let and const) are safer and reduce the risk of unintended side effects, especially in large codebases or when working in nested blocks like loops or conditionals.

var, let, and const comparision

The introduction of let and const in ES6 has significantly improved the way we handle variables in JavaScript. While var was the traditional way of declaring variables, it comes with certain quirks, such as function-level scoping and hoisting, which can lead to unexpected results. let and const offer more robust alternatives with block-level scoping, ensuring safer and more predictable behavior in modern JavaScript development.

In summary:

  • Use const for variables that shouldn't change.
  • Use let for variables that will change over time.
  • Avoid var whenever possible to prevent scope-related issues.

By understanding these differences and following best practices, you'll write cleaner, more maintainable JavaScript code.