Suggest an editImprove this articleRefine the answer for “Symbol in JS”. Your changes go to moderation before they’re published.Approval requiredContentWhat you’re changing🇺🇸EN🇺🇦UAPreviewTitle (EN)Short answer (EN)**`Symbol`** is a primitive data type (introduced in ES6) that represents a unique, immutable value: every call to `Symbol()` creates a new unique value, even if the descriptions match. **Key point:** symbols are most often used as unique object property keys, ones that are invisible to `for...in`, `Object.keys()`, and `JSON.stringify()`.Shown above the full answer for quick recall.Answer (EN)Image## What `Symbol` is > `Symbol` is a *primitive data type* (introduced in ES6) > representing a **unique and immutable value**. It is created via a function: ```javascript const id = Symbol(); ``` Every call to `Symbol()` creates a **new unique value**, even if the descriptions match. --- ### Example ```javascript const id1 = Symbol('user'); const id2 = Symbol('user'); console.log(id1 === id2); // false ``` > Although both symbols have the same description, `'user'`, > they are **different**. Every `Symbol()` is unique. --- ## Why `Symbol` is needed Symbols are most often used as **unique object property keys**, to avoid name conflicts. --- ### Example: ordinary keys can conflict ```javascript const user = { name: 'Oleh' }; user.id = 1; user.id = 2; // overwritten ``` But if you use `Symbol`: ```javascript const ID = Symbol('id'); const user = { name: 'Oleh', [ID]: 1 }; console.log(user[ID]); // 1 ``` Now the property `[ID]`: - is unique; - is not visible during a normal iteration of properties. --- ## Symbols do not take part in normal iteration ```javascript for (let key in user) { console.log(key); } // → "name" ``` ```javascript console.log(Object.keys(user)); // ["name"] ``` > A symbol does not appear in `for...in`, `Object.keys()`, or `JSON.stringify()`. But it can be retrieved: ```javascript console.log(Object.getOwnPropertySymbols(user)); // [Symbol(id)] ``` --- ## Symbols are often used "inside" the language JavaScript has **built-in (well-known symbols)**: special symbols that let you change the behavior of built-in operations. --- ### Examples of built-in symbols: | Symbol | Used for | |---|---| | `Symbol.iterator` | makes an object iterable (`for...of`) | | `Symbol.toPrimitive` | configures conversion to a primitive | | `Symbol.toStringTag` | sets the string returned by `Object.prototype.toString` | | `Symbol.hasInstance` | overrides the behavior of `instanceof` | | `Symbol.asyncIterator` | lets you use `for await...of` | --- ### Example: `Symbol.iterator` ```javascript const arr = [1, 2, 3]; const iterator = arr[Symbol.iterator](); console.log(iterator.next()); // { value: 1, done: false } ``` > The `Symbol.iterator` symbol makes an array "iterable": > that is exactly what lets it work with `for...of` and spread (`...arr`). --- ### Example: `Symbol.toPrimitive` ```javascript const user = { name: 'Oleh', age: 25, [Symbol.toPrimitive](hint) { return hint === 'string' ? this.name : this.age; } }; console.log(String(user)); // "Oleh" console.log(+user); // 25 ``` > The symbol lets you control how the object is converted to a number or a string. --- ## Symbols can be stored in a "registry" Sometimes a symbol with the same name needs to be **the same one**: that is what the **global symbol registry** is for. ```javascript const id1 = Symbol.for('user'); const id2 = Symbol.for('user'); console.log(id1 === id2); // true ``` > `Symbol.for(key)` looks up the symbol in the global registry. > If it is not found, it creates a new one and stores it under that key. You can get the description like this: ```javascript Symbol.keyFor(id1); // 'user' ``` --- ## Symbols are safe "hidden" keys They are ideal for: - creating private properties in libraries or classes; - extending objects without the risk of damaging someone else's data; - metadata (for example, in frameworks or an ORM). --- ## Example of use in a class ```javascript const _id = Symbol('id'); class User { constructor(name) { this.name = name; this[_id] = Math.random(); } } const user = new User('Oleh'); console.log(user); // { name: 'Oleh', [Symbol(id)]: 0.123... } console.log(Object.keys(user)); // ["name"] ``` > The symbol makes the `_id` field **invisible during normal iteration** > and protects it from being accidentally overwritten. --- ## Summary | Property | Description | |---|---| | Type | Primitive | | Uniqueness | Every `Symbol()` is unique | | Used as | A key for object properties | | Not visible | in `for...in`, `Object.keys()`, `JSON.stringify()` | | Has a global registry | via `Symbol.for()` and `Symbol.keyFor()` | | Examples of built-in symbols | `Symbol.iterator`, `Symbol.toPrimitive`, `Symbol.hasInstance`, and others | --- ## In short - `Symbol()` creates a **unique value**, even with an identical description. - It is used for **unique keys** of properties. - It does not take part in normal iteration, so it is convenient for "private" data. - It has built-in variants (`Symbol.iterator`, `Symbol.toPrimitive`, and others) that let you change the behavior of standard JS operations.For the reviewerNote to the moderator (optional)Visible only to the moderator. Helps review go faster.