> Как модифицировать класс в JavaScript для кастомного сравнения экземпляра с числом (JavaScript)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Инити

Стек: JavaScript

> Пример ответа

Короткий ответ

Для кастомного сравнения экземпляра класса с числом в JavaScript нужно переопределить метод valueOf() или Symbol.toPrimitive. Эти методы вызываются при неявном приведении типа, например в операциях сравнения (==, <, >). valueOf() возвращает примитивное значение, которое JS использует для сравнения. Для строгого равенства (===) это не работает - требуется явное преобразование.

Подробное объяснение

JavaScript использует алгоритм абстрактного сравнения (Abstract Equality Comparison) для == и Relational Comparison для <, >, <=, >=. При сравнении объекта с примитивом вызывается метод ToPrimitive, который сначала пытается вызвать valueOf(), затем toString(). Если ни один не возвращает примитив - выбрасывается TypeError.

Symbol.toPrimitive - более современный и гибкий способ. Он принимает хинт ("number", "string", "default") и позволяет вернуть разные значения для разных контекстов. Например, для арифметических операций хинт "number", для строковой конкатенации - "string".

Важно: === (строгое равенство) не вызывает ToPrimitive - сравниваются типы напрямую. Для работы с === нужно явно преобразовывать экземпляр в число через Number(instance) или унарный +.

На практике

В реальных проектах такая модификация полезна для value-объектов: денежных сумм, координат, временных интервалов. Например, класс Money может сравниваться с числом через valueOf(), возвращая сумму в минимальных единицах. Это упрощает код: if (price > 100) вместо if (price.amount > 100).

Однако нужно быть осторожным: неявное приведение может привести к трудноотлавливаемым багам, особенно при использовании ==. Рекомендуется документировать такое поведение и, возможно, добавить явный метод .toNumber().

Пример кода

JAVASCRIPT
class Temperature {
constructor(celsius) {
this.celsius = celsius;
}
// Для неявного приведения к числу
valueOf() {
return this.celsius;
}
// Более гибкий вариант с Symbol.toPrimitive
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.celsius;
}
if (hint === 'string') {
return `${this.celsius}°C`;
}
// hint === 'default' - для == и операций сравнения
return this.celsius;
}
}
const temp = new Temperature(25);
console.log(temp > 20); // true (valueOf)
console.log(temp == 25); // true (Symbol.toPrimitive с hint 'default')
console.log(temp + 5); // 30 (Symbol.toPrimitive с hint 'number')
console.log(String(temp)); // "25°C" (Symbol.toPrimitive с hint 'string')
console.log(temp === 25); // false - строгое равенство не работает

Как отвечать на собеседовании

Начни с ключевого механизма - valueOf() и Symbol.toPrimitive. Объясни разницу между == и === в контексте приведения типов. Упомяни, что Symbol.toPrimitive даёт больше контроля через хинты. Приведи практический пример из реального проекта (value-объект). Подчеркни ограничения: не работает для ===, может усложнить отладку. Если спросят про производительность - скажи, что вызов методов при каждом сравнении имеет накладные расходы, но для большинства приложений это не критично.

Что проверяет интервьюер

  • Понимание системы типов JavaScript и механизмов приведения
  • Знание протокола ToPrimitive и его этапов
  • Умение различать абстрактное и строгое равенство
  • Практический опыт с value-объектами и кастомными типами
  • Осознание trade-off между удобством и явностью кода

Типичные ошибки

  • Попытка переопределить valueOf для работы с === - это невозможно, нужно явное преобразование
  • Забыть, что valueOf должен возвращать примитив, иначе JS вызовет toString
  • Путать valueOf с toString - первый для чисел, второй для строк
  • Не учитывать, что Symbol.toPrimitive переопределяет оба метода и имеет приоритет
  • Использовать неявное приведение в сложных выражениях без документации - это усложняет поддержку кода

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью