Suggest an editImprove this articleRefine the answer for “Ways to declare a variable: var, let, const”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**There are three ways to declare a variable: `var`, `let` and `const`, and the difference between them is scope, the ability to redeclare, and hoisting behaviour.** `var` is function scoped and hoists with the value `undefined`; `let` and `const` are block scoped and unreachable before their declaration (the temporal dead zone). Reach for `const` by default and for `let` only when the value genuinely has to change. ```javascript const PI = 3.14; // never reassigned let age = 25; // reassigned var old = 'Tim'; // legacy style, better avoided ``` **Key point:** `const` by default, `let` when needed, `var` not at all in modern code.Shown above the full answer for quick recall.Answer (EN)Image**JavaScript has three ways to declare a variable: `var`, `let` and `const`.** They differ in scope, in whether they can be redeclared, and in how they behave under hoisting. Let us go through them in detail. ## Theory ### TL;DR - `var`, function scoped, allows redeclaration, hoists with the value `undefined`. - `let`, block scoped, the value can be reassigned, redeclaring it in the same block is not allowed. - `const`, block scoped, cannot be reassigned, but the contents of an object or array can still change. - `let` and `const` are hoisted too, yet before their declaration line they sit in the temporal dead zone and throw a `ReferenceError`. - The modern standard: `const` by default, `let` when needed, `var` not at all. ### Quick example ```javascript function demo() { if (true) { var fromVar = 'visible in the whole function'; let fromLet = 'visible only inside this block'; } console.log(fromVar); // 'visible in the whole function' console.log(fromLet); // ReferenceError: fromLet is not defined } ``` ### 1. `var`, the old way (ES5 and earlier) ```javascript var name = 'Tim'; ``` Details: - It can be redeclared and reassigned: ```javascript var x = 10; var x = 20; // does not raise an error ``` - Function scope (it ignores `{}` blocks): ```javascript if (true) { var a = 5; } console.log(a); // 5, the variable "escaped" the block ``` - It is hoisted, so the variable is reachable before its declaration, but its value is `undefined`: ```javascript console.log(user); // undefined var user = 'Alex'; ``` > Using `var` in modern code is not recommended. ### 2. `let`, the modern way for values that change ```javascript let age = 25; age = 26; // reassignment is allowed ``` Details: - The value can be changed, but the name cannot be redeclared in the same block: ```javascript let a = 1; // let a = 2; SyntaxError ``` - Block scope: ```javascript if (true) { let x = 10; } console.log(x); // ReferenceError, the variable is not visible outside the block ``` - It is unreachable before its declaration, unlike `var`: ```javascript console.log(a); // ReferenceError let a = 5; ``` > Use `let` when the value of the variable is going to change. ### 3. `const`, a constant (an immutable binding) ```javascript const PI = 3.14; ``` Details: - It cannot be reassigned or redeclared: ```javascript const x = 10; x = 20; // TypeError ``` - But if it holds an object or an array, the data inside can still be changed: ```javascript const user = { name: 'Tim' }; user.name = 'Alex'; // allowed // user = {} not allowed, the binding itself cannot be reassigned ``` - Block scope, same as `let`. > Use `const` by default, and `let` only if the variable really has to change. When you need genuine immutability of an object, apply `Object.freeze()`. ### Hoisting and the temporal dead zone All three declarations are hoisted; the difference is what happens before the declaration line. `var` is initialised with `undefined` while the scope is being created, so reading it does not fail and quietly returns `undefined`, which is a source of hard to catch bugs. `let` and `const` reserve the name as well but leave it uninitialised: the gap between the start of the block and the declaration line is called the temporal dead zone (TDZ), and any access inside it throws a `ReferenceError`. ```javascript console.log(withVar); // undefined, quiet and dangerous var withVar = 1; console.log(withLet); // ReferenceError: Cannot access 'withLet' before initialization let withLet = 1; ``` A second practical difference shows up in loops: `let` creates a fresh binding on every iteration, while `var` has a single one for the whole function. ```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 ``` ### Quick comparison | Feature | `var` | `let` | `const` | | --- | --- | --- | --- | | Scope | Function | Block | Block | | Can be redeclared | yes | no | no | | Can be reassigned | yes | yes | no | | Hoisting | Yes, with the value `undefined` | Yes, but unusable before the declaration | Yes, but unusable before the declaration | | Modern standard | Obsolete | Yes | Yes | ### Common mistakes - **Believing that `const` makes an object immutable.** Only the binding is frozen: `user.name = 'Alex'` works, while `user = {}` throws a `TypeError`. - **Declaring a `const` without a value.** `const x;` is a `SyntaxError`, the value is required right away. - **Relying on `var` hoisting** and reading the variable before its declaration, getting `undefined` instead of an error. - **Using `var` in a loop with asynchronous callbacks** and then wondering why every callback sees the final counter value. - **Picking `let` where the value never changes.** It hides intent: `const` tells the reader immediately that no reassignment is coming.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.