Symbol - примітивний тип для унікальних ідентифікаторів. Кожен виклик Symbol() створює значення, що не дорівнює жодному іншому, навіть з тим самим описом:
const id1 = Symbol('id');
const id2 = Symbol('id');
id1 === id2; // false
Опис ('id') - лише для налагодження, на унікальність не впливає.
Символи як ключі властивостей - не конфліктують з жодними іншими ключами:
const internal = Symbol('internal');
const user = { name: 'Оля', [internal]: { loadedAt: Date.now() } };
Object.keys(user); // ['name'] - символьний ключ прихований
JSON.stringify(user); // '{"name":"Оля"}'
user[internal]; // доступ лише з посиланням на сам символ
Бібліотека може додати службові дані до чужого об'єкта, не ризикуючи зіткнутися з його полями і не потрапляючи в серіалізацію чи for...in. Але символьні ключі не приватні: Object.getOwnPropertySymbols() чи Reflect.ownKeys() їх покажуть.
Глобальний реєстр - Symbol.for(key) повертає той самий символ для того самого ключа в усьому застосунку (навіть між iframe):
Symbol.for('app.cache') === Symbol.for('app.cache'); // true
Найважливіше практичне застосування - вбудовані (well-known) символи. Через них ваші об'єкти підключаються до механізмів мови:
Symbol.iterator- об'єкт стає ітерованим (for...of, spread):
class Range {
constructor(from, to) { this.from = from; this.to = to; }
*[Symbol.iterator]() {
for (let n = this.from; n <= this.to; n++) yield n;
}
}
[...new Range(1, 3)]; // [1, 2, 3]
Symbol.asyncIterator- дляfor await...of;Symbol.toPrimitive- перетворення на число чи рядок;Symbol.toStringTag- що показуєObject.prototype.toString([object Money]);Symbol.hasInstance- поведінкаinstanceof;Symbol.dispose/Symbol.asyncDispose- для явного керування ресурсами (using).
Ще застосування:
- значення-«константи», які гарантовано не збігаються з даними:
const NOT_FOUND = Symbol('not found')замістьnullчи-1, які можуть бути реальними значеннями; - ключі для
provide/injectу Vue - щоб різні бібліотеки не перезаписали одна одній залежності.
Обмеження: символ не перетворюється неявно на рядок (`${sym}` - TypeError), лише явно через String(sym) чи sym.description.