ComparisonComparisons

let vs const vs var

const and let have block scope, while var has function scope. const doesn’t allow reassignment. In new code write const, and let only for values that change.

On this page

Side-by-side comparison

#
  • Scope

    const
    Block
    let
    Block
    var
    Function
  • Reassignment

    let
    Yes
    var
    Yes
  • Redeclaration in the same scope

    const
    No, SyntaxError
    let
    No, SyntaxError
    var
    Yes, no error
  • Referencing before the declaration

    const
    ReferenceError
    let
    ReferenceError
    var
    The value undefined
  • Value at declaration

    const
    Required
    let
    Optional
    var
    Optional
  • A variable in a loop with a callback

    const
    In for...of every iteration gets its own constant
    let
    Every iteration gets its own variable
    var
    One variable shared by all iterations
  • When to use it

    const
    By default
    let
    When the value changes
    var
    Only in old code

Example

#
JavaScript
const course = 'JavaScript'
let level = 1
level = level + 1

if (level > 1) {
  var visible = 'var is visible outside the block'
  let hidden = 'let only exists inside the block'
}

console.log(course, level)
console.log(visible)
console.log(typeof hidden)
Console
JavaScript 2
var is visible outside the block
undefined

Definition and usage

#

All three keywords declare variables, but they differ in scope, whether they can be reassigned, and how they behave before the declaration. let and const entered the language in ES2015 and have block scope: they exist only inside the curly braces where they were declared. var has function scope, so it reaches beyond if blocks and loops.

const doesn’t let you assign the variable a new value, but it doesn’t freeze the object: you can still add an element to an array declared with const. let allows reassignment. Up to the point of declaration, both sit in what’s called the temporal dead zone, so referencing them earlier throws a ReferenceError. A var declaration is hoisted to the top of the function and holds undefined until the assignment runs.

The practical rule: const by default, let only for values that genuinely change (counters, running totals in a loop), and var not at all. You’ll run into it in older projects and in old forum answers, so it’s worth understanding how it differs.

Syntax

#
Syntax
const name = value
let name = value
var name = value

More examples

#
const doesn’t freeze an array
JavaScript
const skills = ['HTML']
skills.push('CSS')
console.log(skills)

try {
  skills = []
} catch (error) {
  console.log(error.name)
}
Console
['HTML', 'CSS']
TypeError

You can change the contents of an array or object, just not the assignment itself. Use Object.freeze() to freeze an object.

A loop with setTimeout: var vs let
JavaScript
for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log('var', i), 0)
}

for (let j = 0; j < 3; j++) {
  setTimeout(() => console.log('let', j), 0)
}
Console
var 3
var 3
var 3
let 0
let 1
let 2

All the functions from the first loop see the same variable i, which is 3 once the loop finishes. let creates a new variable for every iteration.

The temporal dead zone: let before its declaration
JavaScript
try {
  console.log(points)
  let points = 10
} catch (error) {
  console.log(error.name)
}

console.log(bonus)
var bonus = 5
Console
ReferenceError
undefined

Good practices

#
  • Start with const and switch to let only once the editor or linter flags an attempted reassignment.
  • The ESLint rules prefer-const and no-var enforce this rule across the whole project.
  • The block scope of let and const applies to every block: if, loops, try, and standalone curly braces.

Related entries

#

Spotted a mistake or missing an example? Write to us.