The difference between console.log and console.dir is not that one can print objects and the other cannot. Modern browser DevTools can expand objects printed by console.log. The practical difference is how environments choose to display objects, DOM nodes, and deep structures.
For everyday debugging, start with console.log. Use console.dir when you explicitly want an object-like property tree.
console.log: general output
const user = { name: "Alice", age: 25 }
console.log(user)
console.log("current user", user)
Use it for:
- strings, numbers, and booleans
- quick value checks
- contextual messages
- ordinary object inspection
If you only need to confirm what a value is at a point in code, console.log is usually enough.
console.dir: object structure view
const user = {
name: "Alice",
age: 25,
hobbies: ["reading", "swimming"],
}
console.dir(user)
console.dir emphasizes an expandable property-tree view. It can be helpful for complex objects, class instances, browser objects, and deeply nested configuration.
DOM nodes in browser DevTools
This is where the difference is easier to notice:
const button = document.querySelector("button")
console.log(button)
console.dir(button)
In many browser DevTools:
console.log(button)may show a more element-like DOM representation.console.dir(button)may show the JavaScript object property tree.
If you want to inspect markup and live element state, start with log. If you want properties and methods, try dir.
Node.js usage
In Node.js, there is no browser DOM view. console.dir is useful because it accepts inspection options:
console.dir(config, { depth: null })
This is helpful for deeply nested objects.
Live object reference warning
Console output can show a live object reference. If you expand the object later, you may see its later state, not an exact snapshot from the moment the log statement ran.
For a rough snapshot, serialize:
console.log(JSON.stringify(data))
But this loses functions, undefined, symbols, circular references, and many non-JSON values. Use it only when JSON output is the right representation.
Quick choice table
| Situation | Use |
|---|---|
| quick value check | console.log |
| log with context text | console.log |
| inspect object property tree | console.dir |
| inspect DOM element visual structure | start with console.log |
| inspect deep object in Node.js | console.dir(obj, { depth: null }) |
Related FreeMac guides
- For object behavior, read JavaScript Object Copy: Destructuring, Shallow Copy, and Deep Copy.
- For optional fields, read JavaScript Optional Chaining: When to Use
?.. - For DOM rendering concepts, read DOM and CSSOM: How Browsers Build and Render a Page.
Continue reading
JavaScript Event Loop: Tasks, Microtasks, and Rendering
Understand the browser event loop through the call stack, tasks, microtasks, Promise callbacks, queueMicrotask, async/await, rendering opportunities, and long tasks.
7 min readWhy var and let Behave Differently in for Loops
Use the classic JavaScript closure example to understand why var in a for loop prints 3 3 3, while let creates per-iteration bindings and prints 0 1 2.
8 min readJavaScript var vs let: Function Scope, Block Scope, and Closures
Understand the difference between var and let in JavaScript through function scope, block scope, for loops, closures, and why let avoids the classic 3 3 3 result.
Subscribe to FreeMac
Weekly picks: free Mac software reviews, trusted source updates, alternatives, and low-friction guides.