FundamentalsChapter 8 of 21
let
A name you can reassign, scoped to the block it lives in.
A name that can change
let declares a variable you intend to reassign. Everything else about it matches const.
JavaScript
let attempts = 0;
attempts = attempts + 1;
attempts += 1;
console.log(attempts);Output
2
Block scope
A let variable exists only inside the nearest pair of braces. Outside them the name does not exist at all.
JavaScript
let visible = 'outer';
if (true) {
let hidden = 'inner';
console.log(visible, hidden);
}
console.log(typeof hidden);Output
outer inner undefined
This is why loops behave the way you expect. Each pass of a for loop with let gets its own copy of the counter:
JavaScript
const jobs = [];
for (let i = 0; i < 3; i += 1) {
jobs.push(() => i);
}
console.log(jobs.map((job) => job()));Output
[0, 1, 2]
Note
The same loop written with var logs [3, 3, 3], because there is only ever one counter for the whole loop. That difference is the whole reason let exists.
Declaring twice
Redeclaring a name in the same scope is a syntax error, which catches a whole class of accidental collisions.
JavaScript
let total = 1;
let total = 2; // SyntaxError: Identifier 'total' has already been declaredOutput
SyntaxError: Identifier 'total' has already been declared
The same name in a nested block is fine, because that is a different scope.
Declaring without a value
A let may be declared empty and filled in later. Until then it holds undefined.
JavaScript
let result;
console.log(result);
result = 'ready';
console.log(result);Output
undefined ready
Test yourself
2 questionsWhere does a let variable exist?
Show the answer
Inside the nearest braces only Block scope is the difference from var, and it is why loop counters behave predictably.
What happens if you declare the same let name twice in one scope?
Show the answer
A SyntaxError The program refuses to start, which is better than two unrelated values quietly sharing a name.
const
A name that cannot be pointed somewhere else, and what that does not protect.