JavaScript let keyword
last modified April 16, 2025
In this article we explore the let
keyword in JavaScript, which
declares block-scoped variables. We'll examine its behavior and advantages.
The let keyword
The let
keyword declares variables that are limited to the block,
statement, or expression where they're used. Unlike var
, let
variables aren't hoisted to the top of their scope. This prevents common
scoping issues in JavaScript.
Variables declared with let
have block scope, meaning they only
exist within the nearest curly braces. They can't be redeclared in the same
scope, but can be reassigned. This makes code more predictable and maintainable.
The temporal dead zone is a period where variables exist but can't be accessed. It starts at the beginning of the block and ends when the declaration is processed. This prevents referencing variables before their declaration.
Basic let declaration
This example shows the basic usage of the let
keyword.
let message = "Hello, World!"; console.log(message); message = "Updated message"; console.log(message);
Here we declare a variable message
with let
and
initialize it. We then reassign a new value to it. Unlike const
,
let
allows reassignment. The variable is block-scoped to the
current execution context.
$ node main.js Hello, World! Updated message
Block scope demonstration
This example demonstrates the block-scoping behavior of let
.
let x = 10; if (true) { let x = 20; console.log(x); // 20 } console.log(x); // 10
The x
variable inside the if block is a separate variable from
the outer x
. This shows how let
creates new
variables in each block scope. The outer x
remains unchanged.
$ node main.js 20 10
Temporal dead zone
This example illustrates the temporal dead zone behavior with let
.
console.log(y); // ReferenceError let y = 5;
Attempting to access y
before its declaration throws a
ReferenceError. This differs from var
which would return
undefined
. The temporal dead zone prevents usage before declaration.
$ node main.js ReferenceError: Cannot access 'y' before initialization
Loop counter with let
Using let
in loop counters creates a new binding for each iteration.
for (let i = 0; i < 3; i++) { setTimeout(() => { console.log(i); }, 100); }
Each iteration gets its own i
variable, solving the classic closure
problem in loops. With var
, all timeouts would log 3. Here we get
0, 1, 2 as expected due to block scoping.
$ node main.js 0 1 2
Redeclaration prevention
let
prevents redeclaration of the same variable in the same scope.
let name = "Alice"; let name = "Bob"; // SyntaxError
Attempting to redeclare name
in the same scope throws a SyntaxError.
This helps catch potential bugs where variables might be unintentionally reused.
Different scopes can have variables with the same name though.
$ node main.js SyntaxError: Identifier 'name' has already been declared
Block scope in switch statements
Switch statements create separate block scopes for each case when using let
.
let choice = 1; switch (choice) { case 1: let message = "First case"; console.log(message); break; case 2: let message = "Second case"; // SyntaxError console.log(message); break; }
This fails because message
is being redeclared in the same block.
To fix this, wrap each case in curly braces to create separate blocks. This
demonstrates how switch statements share the same block scope.
$ node main.js SyntaxError: Identifier 'message' has already been declared
Practical use case: block-scoped variables
Here's a practical example showing how let
improves code safety.
function calculate() { let result = 0; for (let i = 0; i < 5; i++) { result += i; } // i is not accessible here console.log(result); if (result > 3) { let message = "Large result"; console.log(message); } // message is not accessible here } calculate();
This shows how let
keeps variables contained to their logical blocks.
The loop counter i
and the message
variable are only
accessible within their respective blocks. This prevents accidental misuse.
$ node main.js 10 Large result
Source
In this article we have demonstrated how to use the let keyword to declare block-scoped variables in JavaScript.