Asher Cohen
Back to posts

JavaScript Variable Declarations: var, let, and const

Understanding the differences between var, let, and const for modern JavaScript development

Introduction

JavaScript has three ways to declare variables: var, let, and const. Understanding their differences is crucial for writing modern, bug-free JavaScript code.

Quick Comparison

Featureconstletvar
Can Be ReassignedNoYesYes
Can Be RedeclaredNoNoYes
HoistingNoNoYes
ScopeBlockBlockFunction

const

const is for values that should never be reassigned.

const PI = 3.14159;
const API_URL = 'https://api.example.com';

// ❌ Error: Assignment to constant variable
PI = 3.14;

Important: const doesn't make objects immutable—it only prevents reassignment.

const user = { name: 'John' };
user.name = 'Jane'; // ✅ Allowed (object mutated)
user = {}; // ❌ Error (reassignment)

Use const by default for all declarations that don't need reassignment.

let

let is for variables that need to be reassigned.

let count = 0;
count = 1; // ✅ Allowed

let user = null;
user = { name: 'John' }; // ✅ Allowed

let has block scope—it's only available within the nearest {}.

if (true) {
  let blockVar = 'inside';
  console.log(blockVar); // 'inside'
}
console.log(blockVar); // ❌ ReferenceError

var

var is the old way of declaring variables. Avoid using it in modern code.

var name = 'John';
var name = 'Jane'; // ✅ Allowed (redeclaration)

var has function scope, not block scope.

function example() {
  if (true) {
    var functionVar = 'inside';
  }
  console.log(functionVar); // 'inside' (leaks out of block!)
}

var is hoisted to the top of its function scope.

console.log(name); // undefined (not ReferenceError!)
var name = 'John';

// Equivalent to:
var name;
console.log(name);
name = 'John';

Modern Best Practices

Default to const

// ✅ Good practice
const name = 'John';
const age = 30;

// Use let only when needed
let count = 0;
count++;

Avoid var

// ❌ Old style
var i = 0;

// ✅ Modern style
let i = 0;

Block Scope Awareness

// ✅ let/const respect block scope
for (let i = 0; i < 5; i++) {
  // i is only available in this block
}
console.log(i); // ❌ ReferenceError

// ❌ var leaks
for (var j = 0; j < 5; j++) {
  // j leaks out
}
console.log(j); // 5 (accessible!)

Common Pitfalls

const with Objects

const obj = { a: 1 };
obj.a = 2; // ✅ Allowed (mutation)
obj = { a: 3 }; // ❌ Error (reassignment)

// For true immutability, use Object.freeze()
const frozen = Object.freeze({ a: 1 });
frozen.a = 2; // ❌ Error in strict mode

Hoisting Confusion

// var is hoisted
console.log(x); // undefined
var x = 5;

// let/const are hoisted but not initialized
console.log(y); // ❌ ReferenceError (Temporal Dead Zone)
let y = 5;

When to Use Each

Use const

  • Configuration values
  • Function declarations
  • Imported modules
  • Any value that shouldn't be reassigned

Use let

  • Loop counters
  • Accumulators
  • State that changes over time
  • Temporary variables

Avoid var

  • In modern JavaScript (ES6+)
  • When block scope is needed
  • When you want to prevent redeclaration

Conclusion

Modern JavaScript development follows this hierarchy:

  1. Default to const
  2. Use let when reassignment is needed
  3. Avoid var (legacy code only)

This approach leads to more predictable, maintainable code.

#javascript #es6 #best-practices