Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 33
Beginner

JavaScript Debugging Tools

Quick debugging one-liners for logging, tracing, timing, and inspecting JavaScript values in any project.

TL;DR

  1. 01Log values with console.log() and inspect with console.dir().
  2. 02Pause execution with the debugger statement in DevTools.
  3. 03Measure performance with console.time() and console.timeEnd() using matching labels.

Tips

  1. 01Use console.table() for arrays of objects, since it shows each property as a column for fast visual scanning.
  2. 02Use the %c format specifier in console.log() to add custom CSS styling to messages, making important output easier to spot.

Warnings

  1. 01Remove debugger statements and console logs before shipping production code, since they slow down your app and expose data.
  2. 02console.log() shows a live reference to objects, so an expanded log can differ from the object's state at log time.
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 34
Beginner

JavaScript Debugging Tools

(continued)

Logging Basics

  • console.log()

    The obvious choice, but several other console methods solve specific logging problems faster.

    console.log('user:', user);
  • Labeled logs

    Label your logs by passing a string prefix as the first argument.

    console.log('typeof myVar:', typeof myVar);
  • console.table()

    Displays an array of objects as a clean, scannable table instead of logs.

    console.table(users);
  • Combined values

    Combine multiple values in one log call to compare them side by side.

    console.log('before:', before, 'after:', after);
  • %o Specifier

    Embeds an inspectable object directly inside a formatted log string.

    console.log('user: %o', user);
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 35
Beginner

JavaScript Debugging Tools

(continued)

Pausing and Tracing

  • debugger;

    A single statement pauses your entire script wherever DevTools is open.

    debugger;
  • console.trace()

    Prints the full call stack leading up to the current line of code.

    console.trace();
  • Conditional debugger

    Pauses only when a condition is true, instead of every single time.

    if (i === 5) debugger; // pause once
  • console.assert()

    Logs a message only when the given condition turns out false.

    console.assert(user.id, 'Missing user id');
  • console.count()

    Counts and logs how many times a labeled line has run.

    console.count('render'); // render: 1
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 36
Beginner

JavaScript Debugging Tools

(continued)

Checking Values

  • Strict equality

    Most "why is this undefined" bugs resolve faster with a strict equality check.

    console.log(myVar === undefined);
  • Nullish coalescing

    Log a fallback when values are missing using the ?? operator.

    console.log(myVar ?? 'fallback');
  • Falsy check

    Detect any falsy value with a simple negation check inside an if.

    if (!myVar) console.log('Falsy!');
  • typeof

    Use typeof when results seem off, to confirm the value's data type.

    typeof 'hi' === 'string'; // true
  • Number.isNaN()

    Checks for NaN without the risky type coercion of the global isNaN().

    Number.isNaN(NaN);  // true
    Number.isNaN('x');  // false
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 37
Beginner

JavaScript Debugging Tools

(continued)

Snapshotting Live Objects

  • JSON.stringify snapshot

    console.log(obj) shows the object's state when expanded, not when logged — this fixes that.

    console.log(JSON.stringify(obj, null, 2));
  • structuredClone()

    Takes a frozen deep copy for logging without mutating the live original.

    console.log(structuredClone(state));
  • console.dir()

    Renders a DOM node as an interactive property tree instead of HTML.

    console.dir(document.querySelector('button'));
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 38
Beginner

JavaScript Debugging Tools

(continued)

Timing and Errors

  • console.time/timeEnd

    A matching label is the only thing connecting console.time() to its console.timeEnd().

    console.time('label');
    // code here
    console.timeEnd('label');
  • console.group()

    Nests related log messages in a collapsible group for easier scanning.

    console.group('info');
    // related logs...
    console.groupEnd();
  • try...catch

    Wrap risky code in a try...catch block to handle errors safely.

    try {
      riskyFunction();
    } catch (e) {
      console.error('Error:', e.message);
    }
  • console.error()

    Prints errors in red with a full, clickable stack trace attached.

    console.error('Failed to save:', err);
  • console.warn()

    Flags non-fatal issues in yellow so they still catch your eye.

    console.warn('Approaching API rate limit');
Notes
Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 39
Beginner

JavaScript Debugging Tools

(FAQ)

FAQ

console.log() prints a string representation of a value and is best for primitives and quick output. console.dir() renders an interactive property tree instead, which is far more useful for inspecting DOM nodes or complex objects. Use console.dir() when you need to drill into nested properties.

Add the debugger statement directly in your code. When DevTools is open and execution reaches that line, it pauses automatically. From there you can step through the call stack, inspect variables, and evaluate expressions in the console.

Wrap the code with console.time('label') before it runs and console.timeEnd('label') after. The browser logs the elapsed milliseconds to the console using the matching label. This identifies which measurement the output belongs to.

console.log() captures a live reference to objects, so expanding the output later shows the current state, not the logged state. Use console.log(JSON.stringify(obj)) or console.dir() to snapshot the value at the moment of logging.

In DevTools, open the Sources panel and enable 'Pause on exceptions' (the stop-sign icon). The debugger automatically breaks at the exact line that throws. This lets you inspect the local scope and call stack without manually adding breakpoints.

Useful Cheatsheetsusefulcheatsheets.com
JavaScript Debugging Tools
Chapter 04 · Page 40
Beginner

JavaScript Debugging Tools

(In Practice)
In Practice

Debugging a Slow Data Fetch

Combines console.time, console.table, and try/catch to time a fetch call, inspect its output, and catch failures.

  1. 01console.time('loadUsers') starts a labeled timer right before the fetch begins.
  2. 02console.table(users) renders the array of user objects as a scannable table instead of a nested log.
  3. 03The try/catch block logs a clear error message if the fetch or parsing fails.
  4. 04finally guarantees console.timeEnd('loadUsers') runs and reports the elapsed time either way.
async function loadUsers() {
  console.time('loadUsers');
  try {
    const res = await fetch('/api/users');
    const users = await res.json();
    console.table(users);
    return users;
  } catch (error) {
    console.error('Failed to load users:', error.message);
    return [];
  } finally {
    console.timeEnd('loadUsers');
  }
}

loadUsers();
// logs a table of users, then "loadUsers: 42.3ms"
Takeaway

Pair console.time/timeEnd with try/catch so you always see how long code took, even when it fails.