Что такое Symbol в JavaScript?
Что такое Symbol
Symbol — один из семи примитивных типов JavaScript (наряду с string, number, bigint, boolean, null, undefined). Значение типа Symbol всегда уникально: два Symbol с одинаковым описанием никогда не равны друг другу.
const a = Symbol('id');
const b = Symbol('id');
console.log(a === b); // false
Создание Symbol
Symbol создаётся вызовом функции Symbol(). Вызывать её через new нельзя — это вызовет TypeError:
const sym = Symbol('описание');
console.log(typeof sym); // 'symbol'
console.log(sym.description); // 'описание'
Основные применения
Уникальные ключи свойств объекта
Symbol часто используют как ключи свойств, чтобы избежать конфликтов имён — особенно в библиотеках и фреймворках:
const ID = Symbol('id');
const user = {
name: 'Иван',
[ID]: 42
};
console.log(user[ID]); // 42
console.log(Object.keys(user)); // ['name'] — Symbol не виден
Свойства с ключами-Symbol не попадают в Object.keys(), Object.values(), JSON.stringify() и for...in. Получить их можно через Object.getOwnPropertySymbols() или Reflect.ownKeys().
Well-known Symbols
JavaScript использует встроенные Symbol для настройки поведения объектов:
class MyCollection {
constructor(...items) {
this.items = items;
}
// Делаем объект итерируемым
[Symbol.iterator]() {
let index = 0;
const items = this.items;
return {
next() {
return index < items.length
? { value: items[index++], done: false }
: { done: true };
}
};
}
}
const col = new MyCollection(1, 2, 3);
for (const item of col) {
console.log(item); // 1, 2, 3
}
Другие well-known Symbols: Symbol.toPrimitive, Symbol.hasInstance, Symbol.toStringTag, Symbol.asyncIterator.
Symbol.for и Symbol.keyFor — глобальный реестр
Symbol.for(key) создаёт Symbol в глобальном реестре или возвращает существующий по тому же ключу:
const s1 = Symbol.for('app.token');
const s2 = Symbol.for('app.token');
console.log(s1 === s2); // true
console.log(Symbol.keyFor(s1)); // 'app.token'
Это удобно для обмена Symbol между модулями или iframe.
Важные особенности
- Symbol нельзя неявно привести к строке:
'prefix' + Symbol()бросит TypeError. Используйте.toString()или.description. - Symbol не сериализуются в JSON.
- Symbol-свойства не копируются оператором spread и
Object.assign()— только черезObject.getOwnPropertySymbols().
Когда применять
- Создание «скрытых» или «полуприватных» полей объекта.
- Расширение сторонних объектов без риска конфликта имён.
- Реализация кастомного поведения через well-known Symbols.
- Константы, которые должны быть абсолютно уникальными.
Что хочет услышать интервьюер
Кандидат объяснит, что Symbol — примитив ES6 с гарантированной уникальностью
Упомянет, что Symbol-ключи не перечисляются стандартными методами (Object.keys, for...in, JSON.stringify)
Знает разницу между Symbol() и Symbol.for() (локальный vs глобальный реестр)
Приведёт практический пример: скрытые поля, расширение объектов без коллизий
Знает хотя бы один well-known Symbol (Symbol.iterator, Symbol.toPrimitive и т.д.)
Пример: Основы Symbol и уникальность
const sym1 = Symbol('id');
const sym2 = Symbol('id');
console.log(sym1 === sym2); // false — всегда уникальны
console.log(sym1.description); // 'id'
console.log(typeof sym1); // 'symbol'
// Нельзя: new Symbol() — TypeError
// Нельзя: неявное приведение к строке
// console.log('key: ' + sym1); // TypeError
console.log('key: ' + sym1.toString()); // 'key: Symbol(id)'
Пример: Symbol как ключ свойства — скрытие от перебора
const SECRET = Symbol('secret');
const config = {
host: 'localhost',
[SECRET]: 'super-secret-token'
};
console.log(Object.keys(config)); // ['host']
console.log(JSON.stringify(config)); // '{"host":"localhost"}'
console.log(config[SECRET]); // 'super-secret-token'
// Получить все Symbol-ключи объекта
const symbols = Object.getOwnPropertySymbols(config);
console.log(symbols); // [Symbol(secret)]
Пример: Symbol.for — глобальный реестр
// Создание или получение Symbol из глобального реестра
const token1 = Symbol.for('app.auth.token');
const token2 = Symbol.for('app.auth.token');
console.log(token1 === token2); // true — один и тот же Symbol
// Получить ключ из реестра
console.log(Symbol.keyFor(token1)); // 'app.auth.token'
// Обычный Symbol не регистрируется
const local = Symbol('local');
console.log(Symbol.keyFor(local)); // undefined
Пример: Well-known Symbol: Symbol.iterator
class Range {
constructor(private from: number, private to: number) {}
[Symbol.iterator]() {
let current = this.from;
const last = this.to;
return {
next(): IteratorResult<number> {
if (current <= last) {
return { value: current++, done: false };
}
return { value: undefined as any, done: true };
}
};
}
}
const range = new Range(1, 5);
console.log([...range]); // [1, 2, 3, 4, 5]
for (const n of range) {
console.log(n); // 1, 2, 3, 4, 5
}
Типичные ошибки
Путают уникальность: думают, что Symbol('x') === Symbol('x') возвращает true
Пытаются создать Symbol через new Symbol() вместо Symbol()
Не знают, что Symbol-свойства невидимы для JSON.stringify и Object.keys
Не различают Symbol() и Symbol.for() — думают, что это одно и то же
Не могут привести реальный use-case и описывают Symbol только теоретически


