Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Символы

Символ (symbol) — особый примитивный тип данных: значение, которое гарантированно уникально. Символы используют как ключи свойств, которые не должны случайно совпасть с другими ключами или попасть в обычный перебор. Сам JavaScript с их помощью описывает поведение объектов, например перебор в for...of.

Создание символа

Символ создают функцией Symbol(). Каждый вызов даёт новое значение, не равное никакому другому — даже символу с тем же описанием:

console.log(Symbol('id') === Symbol('id')); // false

Описание символа

Строка в скобках — описание символа. Оно нужно только для отладки: помогает понять, что это за символ, при выводе в консоль:

const id = Symbol('id');
 
console.log(typeof id); // symbol
console.log(id.description); // id

Символ как ключ

Символ можно сделать ключом свойства объекта. При создании объекта его пишут в квадратных скобках, обращаются к свойству тоже через скобки:

const id = Symbol('id');
const user = { name: 'Анна', [id]: 7 };
 
console.log(user[id]); // 7

Добраться до такого свойства может только тот, у кого есть сам символ. Посторонний код не перезапишет его по ошибке, даже если заведёт своё свойство id.

Скрытые свойства

Свойства-символы не попадают в Object.keys(), цикл for...in и JSON.stringify(). Поэтому в них удобно хранить служебные данные, которые не должны уйти на сервер:

const id = Symbol('id');
const user = { name: 'Анна', [id]: 7 };
 
console.log(Object.keys(user).join(', ')); // name
console.log(JSON.stringify(user)); // {"name":"Анна"}

Полностью они не спрятаны: Object.getOwnPropertySymbols(user) вернёт их список.

Глобальный реестр: Symbol.for

Иногда разным частям программы нужен один и тот же символ. Symbol.for() ищет символ с таким именем в общем реестре и создаёт его, только если его там ещё нет:

const a = Symbol.for('app.id');
const b = Symbol.for('app.id');
 
console.log(a === b); // true

Встроенные символы

У JavaScript есть набор встроенных символов, через которые объект настраивает своё поведение. Symbol.iterator из прошлого урока делает объект перебираемым, а Symbol.toPrimitive решает, во что объект превратится в вычислениях:

const price = {
  amount: 12,
  [Symbol.toPrimitive]() {
    return this.amount;
  },
};
 
console.log(price * 2); // 24

Частая ошибка

Обращаться к свойству-символу через точку. Запись user.id ищет обычное свойство со строковым ключом 'id', а не символ из переменной id:

const id = Symbol('id');
const user = { [id]: 7 };
 
console.log(user.id); // undefined
console.log(user[id]); // 7

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.