Suggest an editImprove this articleRefine the answer for “The difference between let, const and var”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`var` is function scoped, while `let` and `const` are block scoped: they live only inside `{ ... }`.** All three declarations are hoisted, but `var` is immediately initialised with `undefined`, whereas `let` and `const` land in the Temporal Dead Zone, so touching them before the declaration line throws a `ReferenceError`. `var` may be redeclared in the same scope, `let` and `const` may not (`SyntaxError`). The value of `var` and `let` can be reassigned, the value of `const` cannot (`TypeError`), and `const` protects the binding itself, not the contents of an object or array. In the browser a top level `var` adds a property to the global `window` object, while `let` and `const` do not, which makes the code safer. ```javascript if (true) { var a = 10; let b = 20; } console.log(a); // 10 console.log(b); // ReferenceError: b is not defined ``` **Key point:** use `const` by default, `let` when the value genuinely changes, and `var` never in modern code.Shown above the full answer for quick recall.Answer (EN)Image**`let` and `const` differ from `var` by being block scoped, by forbidding redeclaration and by using the Temporal Dead Zone instead of a silent `undefined`.** On top of that `const` forbids reassignment, and neither `let` nor `const` adds a property to the global object in the browser, unlike `var`. ## Theory ### TL;DR - `var` is function or globally scoped; `let` and `const` are block scoped. - All three are hoisted, but `var` is initialised to `undefined`, while `let` and `const` sit in the TDZ and throw a `ReferenceError`. - Redeclaration is allowed only for `var`; for `let` and `const` it is a `SyntaxError`. - `var` and `let` can be reassigned; `const` throws a `TypeError`. - `const` protects the binding, not the contents: object properties and array elements can still change. - In the browser a top level `var` becomes a property of `window`, `let` and `const` do not. ### Quick example ```javascript function demo() { if (true) { var scopedToFunction = 'var'; let scopedToBlock = 'let'; const alsoScopedToBlock = 'const'; } console.log(scopedToFunction); // 'var', visible in the whole function console.log(scopedToBlock); // ReferenceError console.log(alsoScopedToBlock); // ReferenceError } demo(); ``` ### The main differences | Criterion | `var` | `let` | `const` | | --- | --- | --- | --- | | **Scope** | Function or global | Block (`{ ... }`) | Block (`{ ... }`) | | **Hoisting** | Hoisted and initialised to `undefined` | Hoisted but **not initialised** (error when touched before the declaration) | Hoisted but **not initialised** (error when touched before the declaration) | | **Redeclaration** | Allowed in the same scope | Error | Error | | **Reassignment** | Allowed | Allowed | Not allowed | | **Added to the window object (in the browser)** | Yes (`window.varName`) | No | No | ### Scope `var` is function scoped. An `if` block, a `for` block or a bare `{ ... }` is no barrier for it: the variable belongs to the nearest function or to the global scope. ```javascript if (true) { var a = 10; } console.log(a); // 10 (available outside the block) ``` `let` and `const` are block scoped. They exist only inside the curly braces they were declared in. ```javascript if (true) { let b = 20; const c = 30; } console.log(b); // ReferenceError console.log(c); // ReferenceError ``` > `let` and `const` only "live" inside the `{}` block. This is exactly why a `for` loop with `let` gives every iteration its own variable, while `var` gives one shared variable for the whole loop: ```javascript for (var i = 0; i < 3; i++) { setTimeout(() => console.log(i)); // 3, 3, 3 } for (let j = 0; j < 3; j++) { setTimeout(() => console.log(j)); // 0, 1, 2 } ``` ### Hoisting and the Temporal Dead Zone Every variable is "hoisted" to the top of its scope, but in different ways. `var` is immediately initialised to `undefined`, while `let` and `const` land in the **Temporal Dead Zone (TDZ)**, a temporary dead zone where the variable already exists but cannot be touched yet. ```javascript console.log(a); // undefined (var is hoisted and initialised) var a = 5; console.log(b); // ReferenceError (b is in the TDZ) let b = 10; console.log(c); // ReferenceError (c is in the TDZ) const c = 15; ``` The TDZ is not a flaw but a safeguard: instead of a silent `undefined` that shows up later as a strange bug, you get an error on the exact line where the mistake was made. ### Redeclaration, reassignment and `const` with objects Only `var` lets you redeclare a variable in the same scope. Reassignment works for `var` and `let`, but not for `const`. ```javascript var x = 1; var x = 2; // allowed console.log(x); // 2 let y = 1; let y = 2; // SyntaxError: Identifier 'y' has already been declared const z = 1; z = 2; // TypeError: Assignment to constant variable ``` An important nuance: `const` protects the **binding**, not the **contents**. The object or array the constant points at stays mutable. ```javascript const user = { name: 'Tim' }; user.name = 'Alex'; // the property can be changed console.log(user.name); // 'Alex' user = {}; // TypeError: the object itself cannot be reassigned ``` When you need the contents to be genuinely immutable, use `Object.freeze(user)`. ### The global object and the rule of thumb In the browser a top level `var` creates a property on the global object, `let` and `const` do not. ```javascript var x = 10; let y = 20; const z = 30; console.log(window.x); // 10 console.log(window.y); // undefined console.log(window.z); // undefined ``` `var` adds the variable to the global object (`window`, `globalThis`), which makes it easy to overwrite someone else's global by accident. `let` and `const` do not, which makes the code **safer**. | Situation | What to use | Why | | --- | --- | --- | | The variable must change | `let` | Safer than `var`, block scoped | | The variable must not change | `const` | States immutability explicitly | | Legacy code (before ES6) | `var` | Obsolete, only for supporting old projects | A simple rule to remember: > `const` by default. > `let` if the value has to change. > `var` never in modern code. ### Common mistakes - **Thinking `const` makes an object immutable.** Only the binding of the name to the value is fixed; object fields and array elements change quite happily. - **Believing `let` and `const` are not hoisted.** They are hoisted, they just stay in the TDZ until the declaration line, hence a `ReferenceError` rather than `undefined`. - **Using `var` in a loop with asynchronous callbacks.** One shared variable for the whole loop produces the classic `3, 3, 3` instead of `0, 1, 2`. - **Relying on `var` "just working" outside a block.** That is a source of accidental overwrites and name collisions in a large file. - **Expecting `window.myLet` in the browser.** `let` and `const` variables never reach the global object, so such access yields `undefined`.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.