Какие методы приведения типов есть в каждом объекте?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Какие методы приведения типов есть в каждом объекте
В JavaScript каждый объект имеет встроенные методы для приведения типов (type coercion). Они позволяют автоматически или явно преобразовывать объекты в примитивные типы: строки, числа и логические значения.
Три главных метода
Эти методы вызываются автоматически при приведении типов:
1. toString() — преобразование в строку
toString() есть у всех объектов:
const obj = { name: 'Alice' };
console.log(obj.toString()); // "[object Object]"
const arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"
const date = new Date();
console.log(date.toString()); // "Wed Mar 26 2026 10:30:00 GMT+0300"
Переопределение toString:
const user = {
name: 'Alice',
age: 30,
toString() {
return `User: ${this.name}`;
}
};
console.log(String(user)); // "User: Alice"
console.log(user + ''); // "User: Alice" (автоматический вызов)
2. valueOf() — преобразование в примитивное значение
valueOf() используется для чисел и операций:
const num = new Number(42);
console.log(num.valueOf()); // 42 (примитив, не объект)
const bool = new Boolean(true);
console.log(bool.valueOf()); // true
const str = new String('hello');
console.log(str.valueOf()); // 'hello'
Переопределение valueOf:
const product = {
name: 'Laptop',
price: 1000,
valueOf() {
return this.price; // Возвращает числовое значение
}
};
console.log(product + 500); // 1500 (автоматический вызов valueOf)
console.log(product * 2); // 2000
console.log(Number(product)); // 1000
3. Symbol.toPrimitive — явное приведение типа
Symbol.toPrimitive — это новый метод для контроля приведения:
const smartObject = {
count: 10,
[Symbol.toPrimitive](hint) {
console.log('hint:', hint); // 'string', 'number' или 'default'
if (hint === 'number') {
return this.count;
}
if (hint === 'string') {
return `Count: ${this.count}`;
}
return this.count; // default
}
};
// При приведении в строку
console.log(String(smartObject)); // hint: 'string' → "Count: 10"
// При приведении в число
console.log(Number(smartObject)); // hint: 'number' → 10
// При операциях
console.log(smartObject + 5); // hint: 'default' → 15
Порядок вызова методов
Есть точный порядок, в котором JavaScript вызывает эти методы:
Числовое приведение (Number())
┌─────────────────────────┐
│ 1. Symbol.toPrimitive │
│ (hint = 'number') │
├─────────────────────────┤
│ 2. valueOf() │
├─────────────────────────┤
│ 3. toString() │
└─────────────────────────┘
Строковое приведение (String())
┌─────────────────────────┐
│ 1. Symbol.toPrimitive │
│ (hint = 'string') │
├─────────────────────────┤
│ 2. toString() │
├─────────────────────────┤
│ 3. valueOf() │
└─────────────────────────┘
Дефолтное приведение (==, +, -)
┌─────────────────────────┐
│ 1. Symbol.toPrimitive │
│ (hint = 'default') │
├─────────────────────────┤
│ 2. valueOf() │
├─────────────────────────┤
│ 3. toString() │
└─────────────────────────┘
Примеры использования
Пример 1: Преобразование Класса в число
class Duration {
constructor(minutes) {
this.minutes = minutes;
}
valueOf() {
return this.minutes * 60; // Возвращает секунды
}
toString() {
return `${this.minutes} мин`;
}
}
const duration = new Duration(5);
console.log(String(duration)); // "5 мин"
console.log(Number(duration)); // 300
console.log(duration + 100); // 400 (300 + 100)
console.log(duration + ' остаток'); // "5 мин остаток"
Пример 2: Дата с кастомным форматом
class CustomDate {
constructor(date) {
this.date = new Date(date);
}
valueOf() {
return this.date.getTime(); // Timestamp для сравнения
}
toString() {
return this.date.toLocaleDateString('ru-RU');
}
}
const date1 = new CustomDate('2025-01-01');
const date2 = new CustomDate('2025-03-26');
console.log(String(date1)); // "01.01.2025"
console.log(date1 < date2); // true (сравнивает timestamps)
console.log(date2 - date1); // ms между датами
Пример 3: Money класс
class Money {
constructor(amount, currency = 'USD') {
this.amount = amount;
this.currency = currency;
}
[Symbol.toPrimitive](hint) {
if (hint === 'number') {
return this.amount;
}
if (hint === 'string') {
return `${this.amount} ${this.currency}`;
}
return this.amount; // default
}
}
const wallet = new Money(100, 'RUB');
console.log(String(wallet)); // "100 RUB"
console.log(wallet + 50); // 150 (100 + 50)
console.log(`Я имею ${wallet}`); // "Я имею 100 RUB"
Приведение типов в операциях
Унарный плюс — преобразование в число:
const user = {
age: '25',
[Symbol.toPrimitive](hint) {
return hint === 'number' ? parseInt(this.age) : this.age;
}
};
console.log(+user); // 25 (вызовет Symbol.toPrimitive)
console.log(user + 0); // 25
Двойное отрицание — преобразование в boolean:
const obj = {};
console.log(!!obj); // true (все объекты truthy)
Конкатенация строк:
const obj = {
toString() { return 'Object'; }
};
console.log('Result: ' + obj); // "Result: Object"
console.log(`Result: ${obj}`); // "Result: Object" (шаблонная строка)
Частые ошибки
❌ Ошибка 1: Забыли, что объект всегда truthy
const obj = { isEmpty: true };
if (obj) {
console.log('Выполнится'); // Объект всегда truthy!
}
// Если нужно проверить свойство:
if (obj.isEmpty) {
console.log('Правильно');
}
❌ Ошибка 2: valueOf() не вызовется в некоторых случаях
const obj = { valueOf() { return 10; } };
console.log(obj == 10); // false! (сравнивает как объекты)
console.log(obj === 10); // false
// Нужно явно преобразовать:
console.log(Number(obj) == 10); // true
❌ Ошибка 3: Циклический вызов методов
// Это создаст infinite loop!
const badObj = {
toString() { return String(this); }, // вызывает toString() снова!
};
// String(badObj); // RangeError!
Практическое применение
Кастомный класс Vector:
class Vector {
constructor(x, y) {
this.x = x;
this.y = y;
}
valueOf() {
return Math.sqrt(this.x ** 2 + this.y ** 2); // Длина вектора
}
toString() {
return `(${this.x}, ${this.y})`;
}
}
const v = new Vector(3, 4);
console.log(String(v)); // "(3, 4)"
console.log(Number(v)); // 5 (длина: √(9+16) = 5)
console.log(v + 0); // 5
Методы приведения типов — это мощный инструмент для создания интуитивных API и удобной работы с объектами!