Variables#
JavaScript has three declaration forms: const (immutable
binding), let (block-scoped mutable), and var
(function-scoped legacy). Reach for const by
default, let only when the binding genuinely changes, and
var never in new code.
/types`.
Declarations#
Form |
Notes |
|---|---|
|
Block scope. The binding cannot be reassigned; the object it points at can still mutate. |
|
Block scope. Reassignable. Inside |
|
Function scope. Hoisted to the top of the function and
initialised to |
const max = 100; // cannot reassign
let count = 0; // can reassign
const arr = [1, 2, 3];
arr.push(4); // still allowed; binding unchanged
const cfg = Object.freeze({port: 80});
cfg.port = 8080; // silently ignored in non-strict;
// throws under "use strict"
Assignment#
= binds. Destructuring assignment binds many names at once
from an array or object on the right-hand side.
let a = 1, b = 2;
[a, b] = [b, a]; // swap
const {host, port = 80} = config; // destructure object
const [first, ...rest] = items; // destructure array
const {data: payload} = response; // rename on the way out
Scope#
JavaScript is lexically scoped. const and let bind to the
nearest enclosing block ({ ... }, function body, for
init, module body). var binds to the nearest function or
script.
{
const secret = "rk";
console.log(secret); // visible here
}
console.log(secret); // ReferenceError; out of scope
The temporal dead zone (TDZ) is the gap between the start of
the block and the let / const declaration. Reading the
binding in that window throws ReferenceError; var does
not have a TDZ (it reads as undefined).
console.log(x); // ReferenceError
const x = 1;
console.log(y); // undefined; var is hoisted but uninitialised
var y = 1;
Closures capture the binding, not the value, so a var inside
a for over an async body shares one slot.
for (var i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // prints 3 3 3
}
for (let i = 0; i < 3; i++) {
setTimeout(() => console.log(i), 0); // prints 0 1 2
}
Globals#
Globals live on globalThis (window in browsers,
global in Node). Bare x = 1 (without let / const
/ var) creates a global in non-strict mode and throws under
"use strict" and ES modules.
globalThis.answer = 42;
console.log(answer); // 42
ES modules are strict by default. Do not create globals; everything is imported and exported explicitly.