10. Object.toString

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 + ']'.

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.

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'

Last updated