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

Какие методы приведения типов есть в каждом объекте?

1.0 Junior🔥 131 комментариев
#JavaScript Core

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

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

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

Какие методы приведения типов есть в каждом объекте

В 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 и удобной работы с объектами!

Какие методы приведения типов есть в каждом объекте? | PrepBro