Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як об'єкт перетворюється на примітив: valueOf, toString і Symbol.toPrimitive?

Коли об'єкт опиняється там, де потрібен примітив (+obj, obj + '', `${obj}`, obj > 5, obj == 1), рушій викликає перетворення на примітив з «підказкою» (hint), якого типу очікують:

  • 'number' - арифметика й порівняння: +obj, obj * 2, obj > 5;
  • 'string' - шаблонні рядки, String(obj), ключі об'єкта;
  • 'default' - коли незрозуміло: бінарний +, ==.

Алгоритм:

  1. якщо є метод obj[Symbol.toPrimitive](hint) - викликається він;
  2. інакше для 'string' пробуються toString(), потім valueOf();
  3. для 'number' і 'default' - спершу valueOf(), потім toString();
  4. перший результат-примітив і використовується. Якщо обидва повернули об'єкт - TypeError.
const price = {
  amount: 42,
  valueOf() { return this.amount; },
  toString() { return `${this.amount} грн`; },
};

price + 1;       // 43        (default → valueOf)
price * 2;       // 84        (number → valueOf)
`${price}`;      // '42 грн'  (string → toString)
String(price);   // '42 грн'

Повний контроль - Symbol.toPrimitive:

const money = {
  [Symbol.toPrimitive](hint) {
    if (hint === 'number') return 42;
    if (hint === 'string') return '42 грн';
    return 'default';
  },
};

+money;          // 42
`${money}`;      // '42 грн'
money + '';      // 'default'

Як це пояснює «дивацтва» JavaScript:

  • [] + [] → '': масиви через toString() стають порожніми рядками;
  • [] + {} → '[object Object]';
  • [5] * 2 → 10: [5].toString() = '5', потім число;
  • Date - єдиний вбудований об'єкт, для якого 'default' означає рядок: date + 1 дає рядок з датою й одиницею, а date - 1 - число (мітку часу мінус 1).

Практична цінність:

  • порівняння дат a < b працює через valueOf(), що повертає мілісекунди;
  • власні числові типи (гроші, вектори) можуть поводитися природно в шаблонах, але арифметику через valueOf краще не будувати: price1 + price2 дасть число й «загубить» валюту. Явні методи (add, format) надійніші;
  • в об'єктах-значеннях, що потрапляють у шаблони, корисний змістовний toString() - замість [object Object] у логах і повідомленнях.

Докладніше в документації: Symbol.toPrimitive

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання