← Назад к вопросам

Что такое Simbol.toPrimitive?

1.8 Middle🔥 111 комментариев
#JavaScript Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое 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 имеет иерархию для преобразования объектов:

  1. Если определён Symbol.toPrimitive — используется он (имеет приоритет)
  2. Иначе, если требуется число:
    • Вызовет valueOf()
    • Если не вернул примитив, вызовет toString()
  3. Если требуется строка:
    • Вызовет 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 объекты: для удобной работы с доменными моделями
  • Логирование: разные представления в разных контекстах
  • Сравнения: сложные объекты с их собственной логикой сравнения

Важные замечания

  1. Всегда возвращай примитив, не объект:
// ❌ Неправильно
[Symbol.toPrimitive]() {
  return {}; // TypeError: Cannot convert object to primitive value
}
  1. hint параметр — только подсказка, не гарантия. Строки всегда вызовут 'string', но для объектов может быть 'default'

  2. Используй редко — это может запутать читаемость кода. Применяй только когда это имеет смысл доменно

Заключение

Symbol.toPrimitive — это мощный механизм для контроля преобразования объектов в примитивные значения. Правильное его использование делает API объектов более интуитивным и безопасным, особенно для специализированных типов данных вроде денежных сумм, дат или версий.

Что такое Simbol.toPrimitive? | PrepBro