let, const & var
const name = 'Ada'; // reassignment throws
const user = { name: 'Ada' };
user.name = 'Grace'; // fine — the binding is const, the object isn't frozen
let count = 0;
count += 1; // fine — let can be reassigned
if (true) {
let scoped = 'inside';
var leaky = 'also inside';
}
// scoped is not visible here — leaky is (var ignores the block)
console.log(typeof hoisted); // "undefined", not an error
var hoisted = 'declaration is hoisted, the assignment is not';
Block scoping replaced function scoping — const by default, let when it needs to change.
- const
- Can't be reassigned — but an object/array it holds can still be mutated
- let
- Block-scoped, reassignable — the default when a value needs to change
- var
- Function-scoped, hoisted with value undefined — avoid in new code
- TDZ
- let/const exist but throw if read before their declaration line runs