> For the complete documentation index, see [llms.txt](https://strctr.gitbook.io/programming/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://strctr.gitbook.io/programming/01-languages/javascript/01-language/b-structured/b2-objects/10-object-prototype-to-string.md).

# 10. Object.toString

* [Ponyfoo: Investigating Performance ofObject#toStringin ES2015](https://ponyfoo.com/articles/investigating-performance-object-prototype-to-string-es2015)
* [2ality: Well Known Symbols - toStringTag](http://2ality.com/2015/09/well-known-symbols-es6.html#symboltostringtag-string)

In ES5 and earlier, each object had the internal own property `[[Class]]` whose value hinted at its type. You could not access it directly, but its value was part of the string returned by `Object.prototype.toString()`, which is why that method was used for type checks, as an alternative to `typeof`.

## Call

Во всех *встроенных* объектах есть специальное внутреннее свойство `[[Class]]`, в котором хранится информация о его типе или конструкторе. Его можно прочитать его «в обход», воспользовавшись методом `toString` стандартного объекта `Object`. Для получения `[[Class]]` нужна именно внутренняя реализация `toString` стандартного объекта `Object`, другая не подойдёт.

`Object.prototype.toString()` works as follows:

* Convert `this` to an object `obj`.
* Determine the `toString` tag `tst` of `obj`.
* Return `'[object ' + tst + ']'`.

```javascript
const ToString = value => Object.prototype.toString.call(value);

ToString([1, 2]); // [object Array]
ToString(new Date()); // [object Date]
ToString({ name: "Anton" }); // [object Object]
ToString(123); // [object Number]
ToString("string"); // [object String]
```

* Этот способ подходит только для встроенных объектов
* Для собственных конструкторов он работать не будет.

## `Symbol.toStringTag`

In ES6, there is no internal property `[[Class]]`, anymore, and using `Object.prototype.toString()` for type checks is discouraged. In order to ensure the backwards-compatibility of that method, the public property with the key `Symbol.toStringTag` was introduced. You could say that it replaces `[[Class]]`.

`Symbol.toStringTag` symbol used to control the behavior of the `Object.prototype.toString()` built-in method. Implementation of `Object.prototype.toString()` for ES6+ now converts its this value into an object first via the abstract operation `ToObject` and then looks for `Symbol.toStringTag` on the resulting object and in its prototype chain.

```javascript
class A {
  get [Symbol.toStringTag]() { return 'A'; }
}
Object.prototype.toString.call(‘’);     // "[object String]"
Object.prototype.toString.call({});     // "[object Object]"
Object.prototype.toString.call(new A);  // "[object A]"
```

Features:

* Warn: `@@toStringTag` lookup on object requires huge time compare to direct `toString` call.
* `@@toStringTag` is a read-only property

## Algorithm

When the `toString()` method is called, the following steps are taken:

1. If the this value is `undefined`, return `"[object Undefined]"`.
2. If the this value is `null`, return `"[object Null]"`.
3. Let `O` be `ToObject(this value)`.
4. Let `isArray` be `IsArray(O)`.
5. `ReturnIfAbrupt(isArray)`.
6. If `isArray` is true, let `builtinTag` be `"Array"`.
7. Else, if `O` is an exotic `String` object, let `builtinTag` be `"String"`.
8. Else, if `O` has an `[[ParameterMap]]` internal slot, let `builtinTag` be `"Arguments"`.
9. Else, if `O` has a `[[Call]]` internal method, let `builtinTag` be `"Function"`.
10. Else, if `O` has an `[[ErrorData]]` internal slot, let `builtinTag` be `"Error"`.
11. Else, if `O` has a `[[BooleanData]]` internal slot, let `builtinTag` be `"Boolean"`.
12. Else, if `O` has a `[[NumberData]]` internal slot, let `builtinTag` be `"Number"`.
13. Else, if `O` has a `[[DateValue]]` internal slot, let `builtinTag` be `"Date"`.
14. Else, if `O` has a `[[RegExpMatcher]]` internal slot, let `builtinTag` be `"RegExp"`.
15. Else, let `builtinTag` be `"Object"`.
16. Let `tag` be `Get(O, @@toStringTag)`.
17. `ReturnIfAbrupt(tag)`.
18. If `Type(tag)` is not String, let tag be `builtinTag`.
19. Return the String that is the result of concatenating `"[object ", tag, and "]"`.

## Standard library

In the JavaScript standard library, there are the following custom toString tags. Objects that have no global names are quoted with percent symbols (for example: `%TypedArray%`).

* Module-like objects:
  * `JSON[Symbol.toStringTag]` → `'JSON'`
  * `Math[Symbol.toStringTag]` → `'Math'`
* Actual module objects `M`: `M[Symbol.toStringTag]` → `'Module'`
* Built-in classes
  * `ArrayBuffer.prototype[Symbol.toStringTag]` → `'ArrayBuffer'`
  * `DataView.prototype[Symbol.toStringTag]` → `'DataView'`
  * `Map.prototype[Symbol.toStringTag]` → `'Map'`
  * `Promise.prototype[Symbol.toStringTag]` → `'Promise'`
  * `Set.prototype[Symbol.toStringTag]` → `'Set'`
  * `get %TypedArray%.prototype[Symbol.toStringTag]` → `'Uint8Array'` etc.
  * `WeakMap.prototype[Symbol.toStringTag]` → `'WeakMap'`
  * `WeakSet.prototype[Symbol.toStringTag]` → `'WeakSet'`
* Iterators
  * `%MapIteratorPrototype%[Symbol.toStringTag]` → `'Map Iterator'`
  * `%SetIteratorPrototype%[Symbol.toStringTag]` → `'Set Iterator'`
  * `%StringIteratorPrototype%[Symbol.toStringTag]` → `'String Iterator'`
* Miscellaneous
  * `Symbol.prototype[Symbol.toStringTag]` → `'Symbol'`
  * `Generator.prototype[Symbol.toStringTag]` → `'Generator'`
  * `GeneratorFunction.prototype[Symbol.toStringTag]` → `'GeneratorFunction'`
