When you pass an element reference to a template literal and print it to the console, it resolves to [object Object]
because JavaScript automatically converts the object (in this case, the DOM element) to a string using its toString()
method. By default, the toString()
method for an object returns a string in the format [object TypeName]
, which is not very informative.
However, when you pass the element reference directly to console.log()
, the console prints it as <ELEMENT>
(where ELEMENT
is the actual HTML tag, like <div>
or <span>
) because the console is capable of recognizing and handling DOM elements. Instead of just calling toString()
, the console prints a more user-friendly representation of the DOM element.
Breakdown
Here is a breakdown of the two approaches described above:
- Template Literal
- Console Logging Directly
Template Literal
When you use a template literal like `${element}`
, JavaScript implicitly converts the element to a string using element.toString()
, which results in [object Object]
.
const element = document.querySelector('.greeting');
// Greeting: [object HTMLParagraphElement]
console.log(`Greeting: ${element}`);
.greeting { color: green; }
<p class="greeting">Hello World</p>
Console Logging Directly
When you pass element
directly to console.log(element)
, the console recognizes the DOM element and prints it in a more readable format, typically showing the tag name and attributes of the element.
const element = document.querySelector('.greeting');
// Greeting: <p class="greeting">Hello World</p>
console.log('Greeting:', element);
.greeting { color: green; }
<p class="greeting">Hello World</p>
Using outerHTML
If you want to print the element's HTML representation in a template literal, you could use the Element.prototype.outerHTML
method instead:
const element = document.querySelector('.greeting');
// Greeting: <p class="greeting">Hello World</p>
console.log(`Greeting: ${element.outerHTML}`);
.greeting { color: green; }
<p class="greeting">Hello World</p>
\
Using JSON.stringify
If you want to print an object's JSON representation in a template literal, you could use the JSON.stringify
method instead:
/* == Calls default toString() == */
const obj = { message: 'Hello World' };
// Greeting: [object Object]}
console.log(`Greeting: ${obj}}`);
// Greeting: {"message":"Hello World"}
console.log('Greeting:', obj);
// Greeting: {"message":"Hello World"}
console.log(`Greeting: ${JSON.stringify(obj)}`);
/* == Calls custom toString() == */
const obj2 = {
message: 'Hello World',
toString() {
return JSON.stringify(this);
},
};
// Greeting: {"message":"Hello World"}
console.log(`Greeting: ${obj2}`);
.greeting { color: green; }
<p class="greeting">Hello World</p>
console.log('my object is: ', obj);
. Templates themselves are not smart about making a string representation of an object so you can't get the desired output purely from a template literal. They just invoke the default string conversion which is not what you want here. You will have to make the desired string representation yourself and pass that to the literal.