This answer draws on preexisting ones in an effort to provide a systematic overview.
Tip of the hat to Rory O'Kane and Mike 'Pomax' Kamermans for their help.
tl;dr
To get the desired output for the example in the question ad hoc, use console.dir():
console.dir(myObject, { depth: null }) // `depth: null` ensures unlimited recursion
Why not util.inspect()? Because it’s already at the heart of diagnostic output: console.log() and console.dir() as well as the Node.js REPL use util.inspect() implicitly. It’s generally not necessary to require('util') and call util.inspect() directly - unless you want to capture the object visualization in a variable rather than printing to the console (e.g., let s = util.inspect(myObject, { depth: null }))
Alternatively, set the default depth to null:
const util = require('util') // or: import util from 'util' // Set the default depth to null to remove the recursion limit. // All subsequent console.log() and console.dir() calls will use this default. util.inspect.defaultOptions.depth = null console.log(myObject) // or: console.dir(myObject)
Note: At least in recent Node.js versions, Infinity works in lieu of null too.
Details below.
- The REPL: implicitly prints any expression's return value with
util.inspect() with syntax coloring;
i.e., just typing a variable's name and hitting Enter will print an inspected version of its value; e.g.: o = { one: 1, two: 'deux', foo: function(){} } // The REPL echoes the object definition with syntax coloring.
util.inspect() automatically pretty-prints object and array representations, but produces multiline output only when needed.
The pretty-printing behavior can be controlled by the compact property in the optional options argument; false uses multi-line output unconditionally, whereas true disables pretty-printing altogether; it can also be set to a number (the default is 3) to control the conditional multi-line behavior – see the docs.
By default, output is wrapped at around 60 characters thanks, Shrey , regardless of whether the output is sent to a file or a terminal. In practice, since line breaks only happen at property boundaries, you will often end up with shorter lines, but they can also be longer (e.g., with long property values).
In v6.3.0+ you can use the breakLength option to override the 60-character limit; if you set it to Infinity, everything is output on a single line.
If you want more control over pretty-printing, consider using JSON.stringify() with a 3rd argument, but note the following:
- Fails with objects that have circular references, such as
module in the global context. - Methods (functions) will by design NOT be included.
- You can't opt into showing hidden (non-enumerable) properties.
- Example call:
JSON.stringify({ one: 1, two: 'deux', three: true}, undefined, 2); // creates a pretty-printed multiline JSON representation indented with 2 spaces
util.inspect() options object (2nd argument):
An optional options object may be passed that alters certain aspects of the formatted string; some of the properties supported are:
See the latest Node.js docs for the current, full list.
showHidden
- if
true, then the object's non-enumerable properties [those designated not to show up when you use for keys in obj or Object.keys(obj)] will be shown too. Defaults to false.
depth
- tells inspect how many times to recurse while formatting the object. This is useful for inspecting large complicated objects. Defaults to 2. To make it recurse indefinitely, pass
null.
colors
- if true, then the output will be styled with ANSI color codes. Defaults to
false. Colors are customizable [… – see link].
customInspect
- if
false, then custom inspect() functions defined on the objects being inspected won't be called. Defaults to true.
util.format() format-string placeholders (1st argument)
Some of the supported placeholders are:
See the latest Node.js docs for the current, full list.
%s – String. %d – Number (both integer and float). %j – JSON. %% – single percent sign (‘%’). This does not consume an argument.
console.dir, which takes an options object that lets you specify the printing depth, withnullfor unlimited depth:console.dir(yourObject, { depth: null });. The highest voted answers for this question were all great answers back when they were written, but have since become obsolete over the course of a decade of improvements. The modern answer is simply "useconsole.dir".console.dirconsole.diris helpful but not as robust asconsole.log. The latter lets you log things likeconsole.log("a", b, "c"). To get similar output withconsole.diryou'd need to do something likeconsole.log("a"); console.dir(b); console.log("c"). Better yet (?), you could do this:console.log("a", util.inspect(b), "c")require('util').inspect.defaultOptions.depth = 10In my case I have a pretty big project with all sorts of logging variability, like single and multiple parameter logging, strings, objects and all combinations of both. So console.dir wasn't an easy switch. That one-liner solved it. *That code smell a bit as changing inbuilt variables doesn't look right. Nonetheless, it solves the issue without the need to change and maintain the entire project's logging approach. No drawbacks so far. Use at your own risk though. Works in node 20, may break if they change it in future.import { inspect } from "node:util"; inspect.defaultOptions.depth = Infinity;becauseInfinityis a real thing in JS, and does what you expect it to do. Now yourconsole.logwon't redact itself, no matter how deeply nested your data is, nor how much you shouldn't have console logged it. You're in the driving seat.