How Symbol.toStringTag Works in JavaScript
Symbol.toStringTag is a built-in well-known JavaScript
symbol used to customize the string description returned by
Object.prototype.toString(). By assigning a string value to
this symbol on an object or class prototype, developers can replace the
default generic tag—such as "[object Object]"—with a custom
tag like "[object MyCustomClass]". This article explains
how the default string tagging mechanism works, how to implement
Symbol.toStringTag in objects and classes, and how
JavaScript uses it internally for type identification.
The Default Behavior of Object.prototype.toString
In JavaScript, invoking
Object.prototype.toString.call(value) is a classic method
used to reliably inspect an object’s internal [[Class]] or
type.
By default, built-in types produce recognizable tags:
Object.prototype.toString.call([1, 2, 3]); // "[object Array]"
Object.prototype.toString.call(new Map()); // "[object Map]"
Object.prototype.toString.call(new Date()); // "[object Date]"However, user-defined objects and class instances resolve to a generic tag by default:
class User {}
const user = new User();
console.log(Object.prototype.toString.call(user)); // "[object Object]"How Symbol.toStringTag Overrides the Default Tag
When Object.prototype.toString() executes, it checks
whether the target object contains a property keyed by
Symbol.toStringTag. If the property exists and its value is
a string, Object.prototype.toString() uses that string
inside the brackets instead of the default "Object".
Using Symbol.toStringTag with Plain Objects
You can define Symbol.toStringTag directly on an object
literal:
const customConfig = {
[Symbol.toStringTag]: "AppConfig",
apiUrl: "https://api.example.com",
};
console.log(Object.prototype.toString.call(customConfig));
// Output: "[object AppConfig]"Using Symbol.toStringTag with Classes
When working with ES6 classes, the standard practice is to implement
Symbol.toStringTag as a getter on the class prototype:
class DatabaseConnection {
get [Symbol.toStringTag]() {
return "DatabaseConnection";
}
}
const db = new DatabaseConnection();
console.log(Object.prototype.toString.call(db));
// Output: "[object DatabaseConnection]"Built-In Usage in JavaScript
Modern JavaScript engines use Symbol.toStringTag
internally across many built-in APIs to standardize their type
descriptions:
console.log(Math[Symbol.toStringTag]); // "Math"
console.log(Promise.resolve()[Symbol.toStringTag]); // "Promise"
console.log(new Set()[Symbol.toStringTag]); // "Set"
console.log(Object.prototype.toString.call(new Set())); // "[object Set]"Key Considerations
- Type Safety: The value assigned to
Symbol.toStringTagmust be a string. If a non-string value (such as a number or boolean) is assigned, it will be ignored, andObject.prototype.toString()will fall back to the default tag. - Debugging and Logging: Customizing
Symbol.toStringTagimproves readability during debugging and enhances custom type-checking utilities across different execution contexts (such as iframes or Node.js VM contexts) where theinstanceofoperator can sometimes fail.