Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое Symbol.toPrimitive?
Определение
Symbol.toPrimitive — это встроенный символ (well-known symbol) в JavaScript, который определяет метод преобразования объекта в примитивное значение. Когда JavaScript операция требует примитивное значение (число, строка или булево), он вызывает этот метод.
Синтаксис и параметры
const myObject = {
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return 42;
}
if (hint === 'string') {
return 'my object';
}
return true; // default
}
};
console.log(+myObject); // 42 (number coercion)
console.log(String(myObject)); // "my object"
console.log(myObject == true); // true
hint параметр может быть:
- 'number' — требуется числовое значение (операции сравнения, арифметика)
- 'string' — требуется строка (конкатенация, template literals)
- 'default' — неясно, какой тип требуется (обычно операторы +, ==)
Практические примеры
Пример 1: Создание Date-подобного объекта
class CustomDate {
constructor(date) {
this.date = new Date(date);
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.date.getTime();
}
if (hint === 'string') {
return this.date.toISOString();
}
return this.date.toString();
}
}
const myDate = new CustomDate('2026-03-23');
console.log(+myDate); // Timestamp в миллисекундах
console.log(String(myDate)); // ISO строка
console.log(myDate + 1000); // Arithmetic: число + 1000
Пример 2: Денежная валюта
class Money {
constructor(amount, currency) {
this.amount = amount;
this.currency = currency;
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.amount;
}
return `${this.amount} ${this.currency}`;
}
}
const price = new Money(99.99, 'USD');
console.log(price + 10); // 109.99 (arithmetic)
console.log(String(price)); // "99.99 USD"
console.log(price > 50); // true (comparison)
Пример 3: Версионный объект
class Version {
constructor(major, minor, patch) {
this.major = major;
this.minor = minor;
this.patch = patch;
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.major * 10000 + this.minor * 100 + this.patch;
}
return `${this.major}.${this.minor}.${this.patch}`;
}
}
const v1 = new Version(1, 2, 3);
console.log(String(v1)); // "1.2.3"
console.log(v1 > 10201); // true (version 1.2.1 < 1.2.3)
Как работает преобразование
JavaScript имеет иерархию для преобразования объектов:
- Если определён Symbol.toPrimitive — используется он (имеет приоритет)
- Иначе, если требуется число:
- Вызовет
valueOf() - Если не вернул примитив, вызовет
toString()
- Вызовет
- Если требуется строка:
- Вызовет
toString() - Если не вернул примитив, вызовет
valueOf()
- Вызовет
const obj = {
valueOf() {
console.log('valueOf called');
return 42;
},
toString() {
console.log('toString called');
return 'object';
},
[Symbol.toPrimitive](hint) {
console.log('toPrimitive called with:', hint);
return 123;
}
};
console.log(+obj); // Выведет: "toPrimitive called with: number" → 123
console.log(String(obj)); // Выведет: "toPrimitive called with: string" → "123"
Отличие от valueOf и toString
| Метод | Вызывается | Гибкость |
|---|---|---|
| Symbol.toPrimitive | Явно для преобразования в примитив | Высокая (hint параметр) |
| valueOf() | Для числовых операций | Средняя |
| toString() | Для строковых операций | Низкая |
Когда использовать
- Кастомные типы данных: Money, Date, Version, Size
- DSL объекты: для удобной работы с доменными моделями
- Логирование: разные представления в разных контекстах
- Сравнения: сложные объекты с их собственной логикой сравнения
Важные замечания
- Всегда возвращай примитив, не объект:
// ❌ Неправильно
[Symbol.toPrimitive]() {
return {}; // TypeError: Cannot convert object to primitive value
}
-
hint параметр — только подсказка, не гарантия. Строки всегда вызовут 'string', но для объектов может быть 'default'
-
Используй редко — это может запутать читаемость кода. Применяй только когда это имеет смысл доменно
Заключение
Symbol.toPrimitive — это мощный механизм для контроля преобразования объектов в примитивные значения. Правильное его использование делает API объектов более интуитивным и безопасным, особенно для специализированных типов данных вроде денежных сумм, дат или версий.