Skip to content

JavaScript Tutorial Debugging JavaScript

Debugging with console.log and Friends

Lesson 234 of 258 2 min read By Deepak Paswan Updated Oct 4, 2026

console.log() is the debugging tool every developer starts with, and it is still useful. Used well, it answers the question “what is this value right now?”

Log more than one thing, with labels

script.js
JS
const user = { name: "Maya", age: 28 };
const items = [1, 2, 3];

console.log("user:", user);
console.log("items:", items, "count:", items.length);
console.log({ user, items });        // logs an object with named properties: very handy

The last form, console.log({ variable }), prints the name next to the value, so you do not need to type labels.

Different levels

script.js
JS
console.log("Normal information");
console.info("Informational message");
console.warn("A warning: something looks wrong");
console.error("An error: something failed");

The browser console colours them and lets you filter by level, so errors do not get lost in noise.

console.table: lists of objects

script.js
JS
const people = [
  { name: "Maya", role: "Developer" },
  { name: "Arjun", role: "Designer" },
  { name: "Sam", role: "Writer" }
];

console.table(people);

In a browser console, this displays a real, sortable table. It is the best way to inspect arrays of objects.

Grouping

script.js
JS
console.group("Order #1042");
console.log("Customer: Maya");
console.log("Total: $59");
console.groupEnd();

In the browser, groups can be collapsed. They keep related messages together.

Counting and timing

script.js
JS
for (let i = 0; i < 3; i++) {
  console.count("loop pass");     // loop pass: 1, 2, 3
}

console.time("work");
for (let i = 0; i < 100000; i++) { Math.sqrt(i); }
console.timeEnd("work");          // prints something like: work: 0.8 ms

console.assert

Logs an error only if the condition is false: a quiet check.

script.js
JS
const total = 5;
console.assert(total === 5, "total should be 5");     // nothing printed
console.assert(total === 6, "total should be 6, got", total);   // error on purpose: assertion fails

console.dir and console.trace

console.dir(element) shows an object’s properties (instead of its HTML for DOM elements). console.trace() prints where the current function was called from.

script.js
JS
function inner() { console.trace("who called me?"); }
function outer() { inner(); }
outer();

Log objects carefully

The browser console shows live objects, and displays their current state when you expand them, not the state at log time. If an object changes right after, copy it to see a snapshot:

script.js
JS
const data = { count: 1 };
console.log(JSON.stringify(data));   // → {"count":1}   (a snapshot)
data.count = 2;
console.log(data);                   // → { count: 2 }

Styling and clearing

console.log("%cHello", "color: tomato; font-weight: bold") styles a message. console.clear() clears the console.

Clean up

Remove debugging logs before shipping, or use a tool that strips them. Logs can leak information and slow down busy code. In real projects, use a logging helper you can turn off.

When console.log is not enough

If a bug needs you to watch values change over time, or step through code line by line, use the debugger: Breakpoints and the debugger Statement.

lightbulb
Quick habit
When something is wrong, log the input to the function, the output, and the branch taken (console.log("in the else branch")). Often that is enough to see the problem.