So here's a weird thing.
The console
methods have their own C-like String Substitution methods.
Wait, String Substitution?
Literally, substituting part of a string for something else. In Programming land, that usually means building strings via interpolation or formatting strings:
guest = {name: "Fortesque-Delcourt", calling_gift: "a rather nice sherry"}
console.log( `Sir, Mr ${guest.name} has called. He's bought ${guest.calling_gift}` );
// Output:
"Sir, Mr Fortesque-Delcourt has called. He's bought a rather nice sherry."
OK so you can add strings, so what?
You can use Template Literals, or string concatenation, but the "C-Like" formatting referred to in the docs say you can also use templates with placeholders, passing the replacement strings as part of the method arguments:
console.log(
"Sir, Mr %s has called. He's bought %s",
guest.name,
guest.calling_gift
);
// Output:
"Sir, Mr Fortesque-Delcourt has called. He's bought a rather nice sherry."
You're not restricted to substituting literal strings. Instead, the templating engine tries to convert the passed object into the data type specified by the placeholder.
Let's say we have an object representing the investment losses of a Victorian gentleman:
let losses = {
pounds: 150,
reputation: 45.7,
body_parts: "Teeth"
faith: ["The Markets", "New-Fangled Steam"]
}
Here's what you get when you pass various types to the different placeholders:
Template String | losses.body_part | losses.pounds | losses.reputation |
---|---|---|---|
"Lost: %s" | "Lost: Teeth" | "Lost: 150" | "Lost: 45.7" |
"Lost: %i" | "Lost: NaN" | "Lost: 150" | "Lost: 45" |
"Lost: %f" | "Lost: NaN" | "Lost: 150" | "Lost: 45.7" |
Is this useful?
No, not particularly. It does let you see at a glance if you pass a String in as an Integer or Float but... That's not gonna save the world.
What is useful is the Object placeholders, %o
and %O
.
The Object Placeholders
If you call console.log
while combining an Object with a String (eg console.log("Your Object, Sir" + obj)
, you're likely to get back the stunningly unhelpful default toString
output:
[object Object]
This is Gross... But! If you use one of the Object placeholders, you'll get something that represents an enumeration of the properties and their values. What kind of something depends on the operator, and what kind of console you're using.
Node.js CLI
From the CLI, calling console.log
with the uppercase %O
operator will generate an inline enumeration.
Using the lowercase %o
will generate a multi-line enumeration.
Inline (with %O)
console.log("%O", losses)
//Output:
{ pounds: 150, reputation: 45.7, body_parts: 'Teeth', Faith: ['The Markets', 'New-Fangled Steam'] }
Multi-Line (with %o)
console.log("%o", losses)
//Output:
{
pounds: 150,
reputation: 45.7,
body_parts: 'Teeth',
Faith: ['The Markets', 'New Fangled Steam', [length]: 2]
}
Browser Console
In the Chrome console, things act sort of backwards. Here, the lowercase "%o" operator will return an =inline= enumeration:
Inline (with %o)
console.log("%o", losses)
// Output:
> { pounds: 150, reputation: 45.7, body_parts: 'Teeth', Faith: ['The Markets', 'New-Fangled Steam'] }
Object Linking (with %O)
The cool part, however, is with %O
. Using the uppercase format, the output string will contain only the object's name... Which is clickable, taking you to the inspector to let you poke around!
Let's say our losses
object is an instance of the Losses
class, and it also contains some sort of history
object. We can create a rich, readable debugging message which gives us easy access to object internals, but doesn't clutter up the console:
console.log(
"Your %O exceed %d pounds. See %o.",
losses,
losses.pounds,
losses.history
)
//Output:
Your >Losses exceed 150 pounds. See >History.
Wrap-up
So that's the power of Console String Substitution! Easy formatting for terse but richly informative console messages.
If you liked this, please hit the Dopamine (❤️) Switches (🦄) on the left, and subscribe to my writing for the next entry in the JS Console Debugging series!
Recognition
Header image is by @Sigmund, used under the Unsplash License.
Top comments (1)
Yup! As long as you're logging the object directly. Append it to a string and (at least when I checked) you tend to get the results of
toString
. I've added an explicative example; Thanks for the catch!(FWIW
Console.assert
(which inspired me to write this post, as part of a longer post ) seems to prefer returning thetoString
representation on the command line and was sometimes returning it in the browser... But of course, now I can't replicate it and I look Foolish On The Internet)