The Object toString() method
By Flavio Copes
Learn how the JavaScript toString() method returns a string representation of an object, defaulting to [object Object] unless you override it yourself.
Called on an object instance, toString() returns a string representation of the object. By default that’s the [object Object] string, unless you override it with something more useful.
const person = { name: 'Fred' }
person.toString() //[object Object]
Every object inherits this method from Object.prototype, so it’s always there, even on an empty object.
When does JavaScript call it for you?
You rarely call toString() by hand. JavaScript calls it automatically whenever an object needs to become a string.
That happens with string concatenation and template literals:
const person = { name: 'Fred' }
console.log('Hello ' + person) //Hello [object Object]
console.log(`Hello ${person}`) //Hello [object Object]
If you’ve ever seen [object Object] printed on a web page, this is why. Some object ended up in a string context, and the default toString() kicked in.
For debugging, the fix is to not stringify the object at all. Pass it to console.log() as its own argument, or use JSON.stringify():
console.log('Hello', person) //Hello { name: 'Fred' }
console.log(JSON.stringify(person)) //{"name":"Fred"}
How to override toString()
You can give your objects a better string representation by defining your own toString():
const person = {
name: 'Fred',
age: 87,
toString() {
return `${this.name}, ${this.age} years old`
}
}
`${person}` //'Fred, 87 years old'
Now every place that converts the object to a string uses your version.
Built-in objects do exactly this. Arrays override toString() to join their items with commas, and dates return a readable date string:
[1, 2, 3].toString() //'1,2,3'
new Date(2019, 3, 21).toString() //'Sun Apr 21 2019 00:00:00 ...'
That’s why an array in a template literal looks fine while a plain object doesn’t.
A trick with Object.prototype.toString
The original method has a second life as a type checker. Called with .call() on any value, it reveals the internal type:
Object.prototype.toString.call([1, 2, 3]) //[object Array]
Object.prototype.toString.call(null) //[object Null]
Object.prototype.toString.call(new Date()) //[object Date]
Notice we go through Object.prototype directly. Calling [1, 2, 3].toString() would use the array’s own overridden version, and we’d get '1,2,3' instead.
For arrays specifically, prefer Array.isArray(). But the .call() trick covers cases where nothing else works, like telling null apart from an object.
Related posts about js: