Suggest an editImprove this articleRefine the answer for “Scope of var, let and const”. 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 only live inside the `{ ... }` block where they are declared.** All three are hoisted, but reading a `var` before its declaration gives `undefined`, whereas `let` and `const` throw a `ReferenceError` because they sit in the temporal dead zone (TDZ). `var` can be redeclared and reassigned, `let` can only be reassigned, and `const` can be neither (although an object it points to can still be mutated). ```javascript function test() { if (true) { var x = 1; let y = 2; const z = 3; } console.log(x); // 1 console.log(y); // ReferenceError console.log(z); // ReferenceError } test(); ``` **Key point:** default to `const`, switch to `let` when the value must change, and do not use `var` in new code.Shown above the full answer for quick recall.Answer (EN)Image**`var` is function scoped while `let` and `const` are block scoped, so a variable declared with `var` inside an `if` or a loop leaks into the whole function, whereas `let` and `const` stay inside their own curly braces.** Besides scope, the three differ in how they behave during hoisting, whether they can be redeclared, and whether they can be reassigned. ## Theory ### TL;DR - `var` has function scope, `let` and `const` have block scope. - All three are hoisted, but `var` is initialised to `undefined`, while `let` and `const` sit in the TDZ until their declaration line and throw a `ReferenceError`. - Redeclaration in the same scope: `var` allows it, `let` and `const` throw a `SyntaxError`. - Reassignment: `var` and `let` allow it, `const` forbids it, but mutating the object behind the reference is still allowed. - Modern practice: `const` by default, `let` when needed, `var` only in legacy code. ### Quick example ```javascript function test() { if (true) { var x = 1; let y = 2; const z = 3; } console.log(x); // 1 console.log(y); // ReferenceError console.log(z); // ReferenceError } test(); ``` `x` is available because `var` "ignores" the `if` block and is hoisted to the function level. `y` and `z` are visible only inside the `if`. ### Scope: function versus block | Keyword | Scope | | --- | --- | | `var` | **Function scope** | | `let`, `const` | **Block scope** | **Function scope** means the variable is visible everywhere in the function where it is declared, regardless of any `{}` block. **Block scope** means the variable is visible **only inside the block** `{ ... }` where it is declared: the body of an `if`, the body of a loop, any pair of curly braces. ### Hoisting and the TDZ All variables are **hoisted** to the top of their scope, but they behave differently. | Keyword | Hoisted | Usable before the declaration? | | --- | --- | --- | | `var` | yes | yes, but the value is `undefined` | | `let`, `const` | yes | no, an error because of the TDZ (*temporal dead zone*) | Example with `var`: ```javascript console.log(a); // undefined var a = 10; ``` JavaScript hoists the declaration `var a`, but not the assignment `a = 10`. Example with `let` and `const`: ```javascript console.log(b); // ReferenceError let b = 20; ``` `b` is hoisted too, but it lives in the temporal dead zone (TDZ): from the start of the scope up to the actual declaration line. Any access in that window throws a `ReferenceError`. ### Redeclaration and reassignment | Keyword | Can it be redeclared? | | --- | --- | | `var` | Yes, it overwrites the value | | `let`, `const` | No, `SyntaxError` | ```javascript var x = 1; var x = 2; // allowed console.log(x); // 2 let y = 1; let y = 2; // SyntaxError ``` | Keyword | Can the value be changed? | | --- | --- | | `var` | Yes | | `let` | Yes | | `const` | No, but the object inside can be mutated | ```javascript let name = 'Maria'; name = 'Oleh'; // allowed const user = { name: 'Maria' }; user.name = 'Oleh'; // allowed: we mutate the object user = {}; // TypeError: the reference cannot be reassigned ``` `const` freezes the binding, that is the reference, not the contents of the object. To freeze the contents as well you need `Object.freeze`. ### An example that shows every difference ```javascript function demo() { console.log(a); // undefined // console.log(b); // ReferenceError // console.log(c); // ReferenceError var a = 1; let b = 2; const c = 3; if (true) { var a = 10; // the same variable! let b = 20; // a new variable const c = 30; // a new variable console.log(a, b, c); // 10 20 30 } console.log(a, b, c); // 10 2 3 } demo(); ``` `var a` leaked out of the block and overwrote the outer value, while `let` and `const` created their own local variables inside the block, so the outer `b` and `c` were left untouched. ### Which one to use in practice | Keyword | When to use it | | --- | --- | | `let` | For variables whose value has to change | | `const` | By default, always, unless the reference has to change | | `var` | Never, only to maintain legacy code | Summary table: | Property | `var` | `let` | `const` | | --- | --- | --- | --- | | Scope | Function | Block | Block | | Hoisted | Yes | Yes | Yes | | Use before declaration | `undefined` | Error (TDZ) | Error (TDZ) | | Redeclaration | Yes | No | No | | Reassignment | Yes | Yes | No | | Modern standard | Legacy | Recommended | Default | ### Common mistakes - Assuming that a `var` inside an `if` or a `for` creates a local variable. It actually belongs to the whole function and can overwrite the outer value. - Confusing hoisting with "no error". `let` and `const` are hoisted too, accessing them inside the TDZ simply fails with a `ReferenceError`. - Thinking `const` makes the value immutable. It only forbids reassigning the variable; object fields and array elements can still be mutated. - Using `var` in a loop together with asynchronous code: every iteration sees one shared variable, whereas `let` creates a fresh binding per iteration. - Relying on `var` redeclaration as a way to "refresh" a variable: it is a silent overwrite that hides bugs.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.