Object.prototype.toString()

Returns a bracketed type tag such as [object Array] describing the object's internal kind.

Signature
toString()
  • Added in JavaScript ES1

Return value

stringA string of the form "[object Type]", where Type comes from the value's Symbol.toStringTag or its internal kind.

Errors

Never throws for the default implementation; called via .call() it accepts every value, including null and undefined.

Changelog

  • PHP ES2015The tag is now taken from a Symbol.toStringTag property when one is present, so any object can change what this method reports about it.

Called on a plain object, toString() produces the famous "[object Object]" — the string you see when an object is accidentally concatenated or interpolated. That is the same mechanism, not a bug.

The type-check idiom

Its real use is Object.prototype.toString.call(value), which invokes the base implementation on any value regardless of what that value's own toString does. It is the classic way to tell apart things typeof cannot:

ValuetypeoftoString.call()
null"object"[object Null]
[]"object"[object Array]
new Date()"object"[object Date]
/x/"object"[object RegExp]

Unlike instanceof, it also works across iframes and realms, where each realm has its own Array.

What trips people up

Since ES2015 the tag is read from Symbol.toStringTag, so any object can claim to be anything: set that symbol and the check reports whatever you chose. Treat the result as a strong hint, not a security boundary — for arrays specifically, Array.isArray() is exact and cannot be spoofed.

Objects with a null prototype have no toString at all; calling obj.toString() on them throws, though .call() still works.

Example

Try it yourself
Loading editor…
Press Run to execute the code.

When to use it

  • Distinguish arrays, dates and regexes when typeof reports plain "object"
  • Identify values that arrived from another realm, where instanceof fails
  • Explain a "[object Object]" appearing in log output or a template string

Frequently asked questions

Why do I see [object Object] in my output?

An object was converted to a string without a custom toString(), so the default Object.prototype.toString() ran; use JSON.stringify() or log the object itself instead of interpolating it.

Is Object.prototype.toString.call() a reliable type check?

It is reliable for built-ins across realms, but any object can override its tag with Symbol.toStringTag, so use Array.isArray() for arrays and treat the tag as a hint elsewhere.

Why does calling toString() on my object throw?

The object has a null prototype and therefore inherits no toString; call Object.prototype.toString.call(obj) or String(obj) alternatives that do not rely on inheritance.

More examples

A type() helper

Slicing off the "[object " prefix and the closing bracket leaves a usable name. The last line shows what this buys you: typeof collapses null, arrays and every other object into a single useless answer.

Example · javascript
function type(value) {
  return Object.prototype.toString.call(value).slice(8, -1).toLowerCase();
}

console.log(type(null));        // "null"
console.log(type([]));          // "array"
console.log(type(new Date(0))); // "date"
console.log(type(NaN));         // "number"
console.log(type(new Set()));   // "set"
console.log(typeof null, typeof []); // "object" "object"

The tag can be changed

A class can give itself a meaningful tag, which is useful in logs. The same mechanism lets any object impersonate a built-in, so a tag of [object Array] proves nothing while Array.isArray() stays correct. The last pair shows .call() working on a null-prototype object that has no toString of its own.

Example · javascript
class Stream {
  get [Symbol.toStringTag]() {
    return "Stream";
  }
}
console.log(Object.prototype.toString.call(new Stream())); // [object Stream]

const liar = { [Symbol.toStringTag]: "Array" };
console.log(Object.prototype.toString.call(liar));         // [object Array]
console.log(Array.isArray(liar));                          // false — not fooled

const bare = Object.create(null);
console.log(Object.prototype.toString.call(bare));         // [object Object]
console.log(typeof bare.toString);                         // "undefined"

Discussion

  • Be the first to comment on this lesson.