Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Исправляет и дополняет доку для метода объекта toString() #5118

Merged
merged 7 commits into from
Jan 21, 2024
108 changes: 95 additions & 13 deletions js/object-tostring/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: "`.toString()`"
description: "Метод преобразует объект в строковое представление."
description: "Возвращает строковое представление объекта."
authors:
- nlopin
related:
Expand All @@ -13,9 +13,7 @@ tags:

## Кратко

Метод `toString()` преобразует объект в строковое представление. Метод автоматически вызывается JavaScript, когда объект нужно представить в текстовом виде.

Если метод не переопределён, то он возвращает строку формата `[object тип]`, где _тип_ — это строка, которая уточняет тип объекта. В подавляющем большинстве вы будете видеть вывод `[object Object]`.
Метод `toString()` возвращает строковое представление объекта. Метод автоматически вызывается, когда объект нужно представить в текстовом виде. При необходимости поведение метода можно изменить.

## Пример

Expand All @@ -31,21 +29,104 @@ console.log(`Сейчас читаю ${book}`)

## Как пишется

Метод вызывается без аргументов. Возвращает строковое представление объекта.
`Object.prototype.toString()` не имеет аргументов.

`Object.prototype.toString()` возвращает строковое представление объекта.

## Как понять

Существует соглашение, что метод `toString()` вызывается JavaScript автоматически, если объект находится в контексте, где он должен быть представлен в виде строки. Чаще всего это случаи, связанные с печатью данных на экран или в консоль браузера.
Обычно метод `toString()` не используется для объектов явно, а вызывается JavaScript автоматически, если объект находится в контексте, где он должен быть представлен в виде строки.

Объекты, в отличие от примитивных типов, сложно преобразовывать в строку. Объект может содержать произвольное количество полей и без программиста непонятно, какие из них важные. Поэтому стандартная реализация метода `toString()` представляет собой заглушку и возвращает малоинформативную строку, например `'[object Object]'`.

Метод `toString()` является одним из нескольких базовых методов, наследуемых всеми объектами созданными из Object. Встроенные объекты (например: Number, Array, Error, Function и другие) переопределяют реализацию метода `toString()` для отображения объекта в более подходящем виде.

Например, [`Number` преобразует число в строку в указанной системе счисления](/js/number-tostring/), `Array` выводит список элементов через запятую, а `Error` отображает имя и сообщение об ошибке.

Следует отметить, что при использовании Console API метод `toString()` для объектов не используется:

```js
const person = {name: 'Brendan Eich', year: 1961}

// объект как аргумент console.log
console.log('person: ', person)
// person: { name: 'Brendan Eich', year: 1961 }

// строка как аргумент console.log
console.log('person: ' + person)
// person: [object Object]
```

### Описание стандартной реализации

Для обычных объектов (имеющих набор полей {ключ: значение}) метод `toString()` возвращает строку `'[object Object]'`.

<details>
<summary>
Однако, результат может быть иной. Это зависит от нескольких факторов:
</summary>

1. Значение `Symbol.toPrimitive`. Если объект имеет это специальное поле, описывающее преобразование объекта к примитивным типам, то результат этого преобразования к строке используется вместо `toString()`:

```js
const book = {
title: 'Замок',
author: 'Ф. Кафка'
}

book[Symbol.toPrimitive] = function(hint) {
if (hint === 'string') {
return `(название: ${this.title}, автор: ${this.author})`;
}
return true;
}

console.log(`Книга ${book}`)
// Книга (название: Замок, автор: Ф. Кафка)
```

2. Значение `Symbol.toStringTag`. Если объект имеет это специальное строковое поле, то его значение отображается как тип объекта:

```js
const book = {
title: 'Дар',
author: 'В. В. Набоков'
}

book[Symbol.toStringTag] = 'Book'

console.log(`Сейчас читаю ${book}`)
// Сейчас читаю [object Book]
```

3. тип this. Метод `Object.toString()` может быть вызван для значений других типов:

Объекты, в отличие от примитивных типов, сложно преобразовывать в строку. Объект может содержать произвольное количество полей и без программиста непонятно, какие из них важные. Поэтому стандартная реализация метода `toString()` представляет собой заглушку, печатающую `'[object Object]'`.
```js
const toString = Object.prototype.toString

Многие структуры данных, базирующиеся на объекте [`Object`](/js/object/), содержат собственные реализации этого метода. Например, [`Number` преобразует число в строку в указанной системе счисления](/js/number-tostring/), а массив выводит список элементов через запятую.
console.log(toString.call([1, 2, 3]))
// [object Array]

console.log(toString.call(25))
// [object Number]

console.log(toString.call(true))
// [object Boolean]
```

</details>

### Переопределение стандартной реализации

Стандартная реализация метода `toString()` не даёт достаточно информации об объекте даже для использования в отладке программы. Программисты могут переопределить метод `toString()`, чтобы выводить необходимые данные.
Существует несколько способов изменить поведение метода `toString()`.

#### Переопределение метода `toString()` на уровне объекта.

Если мы работаем в ООП стиле, то классу нужно просто добавить метод `toString()`:
Можно использовать перечисленные выше способы с использованием специальных полей: `Symbol.toPrimitive`, `Symbol.toStringTag`

#### Переопределение метода `toString()` для всех экземпляров класса.

Допустим классу требуется переопределить поведение метода `toString()`. Для этого нужно добавить собственную реализацию метода. Тогда все объекты этого класса будут использовать переопределённую реализацию:

```js
class Book {
Expand All @@ -67,7 +148,10 @@ console.log(`Читаю ${book}`)
// Читаю «Палата №6», автор А. П. Чехов
```

Если вы предпочитаете работать в функциональном стиле, то придётся создать новый тип объекта и переопределить метод `toString()` в прототипе:
#### Переопределение метода `toString()` на уровне прототипа функции.

Для создания объектов с необходимым набором свойств может использоваться функция.
В этом случае переопределить метод `toString()` можно для прототипа:

```js
function Book(title, author) {
Expand All @@ -83,5 +167,3 @@ const book = new Book('Палата №6', 'А. П. Чехов')
console.log(`Читаю ${book}`)
// Читаю «Палата №6», автор А. П. Чехов
```

Под капотом JavaScript обе реализации идентичны и отличаются только использованным синтаксисом.
Loading