Part 2 · 2 chapters · ~20 min

Console

The console API by purpose (levels, structure, hierarchy, timing, counting, assert, trace, formats), the settings that hide or show bugs, and the console as a REPL into the page: selection and inspection helpers, monitoring, live expressions, contexts and the caveats.

8

What the console is for

The console is two things: the page's log output, with levels, structure and settings that decide what you see; and a REPL into the running page, with helpers that exist nowhere else. Most people use a tenth of it, and the tenth is console.log with a string. This part is the rest.

the API by purpose
  1. Levels: debug (verbose, hidden by default), log/info, warn (yellow, stack on expand), error (red, stack). The level dropdown filters. Log at the level the message deserves, or nobody can filter; error for a non-error teaches the team to ignore red.
  2. Structure: table(rows, columns?) for arrays of objects; dir(obj) for the property tree (for a DOM node, log shows markup and dir shows properties). Logged objects are live references: expanding later shows now, not then; structuredClone to freeze.
  3. Hierarchy and timing: group/groupCollapsed/groupEnd; time/timeLog/timeEnd for coarse durations (use performance.mark and measure for anything you keep: they show in the Performance panel); count/countReset for "how many times".
  4. Conditions and stacks: assert(cond, ...) prints only on failure and costs nothing otherwise; trace() prints the stack without pausing.
  5. Formats: %c styles the rest of the line (library prefixes); %o keeps an object expandable inside a sentence; template literals cover the rest.
settings that hide or show bugs
  1. Preserve log: off by default, so a reload erases the error that happened just before it. Turn it on when chasing anything that ends in a navigation.
  2. Group similar collapses storms with a count; Show timestamps; Selected context only; Eager evaluation shows results as you type (and calls getters as you type).
  3. The sidebar filters by level and source file; "hide messages from this file" silences a noisy third-party script. The Issues tab beside Console collects the browser's own findings (CORS, cookies, deprecations, CSP) with explanations.
THE CONSOLE API, BY WHAT EACH CALL IS FOR
levels, structure, timing, counting, and the ones that change how you read
swipe the figure sideways, or tap expand for full screen
1/6
levels
Levels: console.debug (verbose, hidden by default), .log and .info (info), .warn (yellow, with a stack on expand), .error (red, with a stack). The level dropdown filters; "Default levels" hides verbose. A library that logs at debug is invisible until you choose Verbose; a page that logs errors for non-errors trains everyone to ignore red.
9

The console as a REPL into the page

the utilities (console only; not page globals)
  1. Selection: $0 to $4 (recently selected elements), $_ (last result), $() and $$() (querySelector, querySelectorAll as a real array), $x() (XPath). "Store as global variable" on any node or object gives temp1.
  2. Inspection: getEventListeners(node), keys/values, inspect(obj) (jump to it in Elements or Sources), copy(obj), and queryObjects(Ctor): every reachable instance of a class, the fastest leak check there is.
  3. Monitoring: monitorEvents(node, "click" | "mouse" | "key"), monitor(fn) logs each call with arguments, debug(fn) breaks on entry without opening the source; each has an un twin.
  4. Live expressions: the eye icon pins an expression that re-evaluates every 250 ms: document.activeElement, $$(".row").length, store.getState().cart.length, performance.memory.usedJSHeapSize / 1e6. A dashboard of the page while you interact.
  5. Context and await: the context dropdown chooses the realm (top, an iframe, a worker, an extension); top-level await works. Sources → Snippets stores scripts to run on any page.
caveats
  1. The utilities do not exist for page code; $$ in a file is a ReferenceError (or jQuery).
  2. Logged objects are live; a getter runs under eager evaluation; console.log in a hot path costs formatting and panel rendering: remove them before measuring anything.
go to the lab
  1. /loop/ordering: run it, then pin a live expression document.visibilityState and switch tabs: the console updates when you return. Add console.trace() inside the microtask in the editor and read the async stack.
  2. /js/detached-list: cycle three times, then in the console run queryObjects(HTMLLIElement).length: 1,500 list items alive for one visible list of 500. Click release and run it again.
  3. /input/div-button: select the real button, run getEventListeners($0); then monitorEvents($0, "click") and press Space on it.
  4. /loop/timers-background: start it, turn on Show timestamps and Preserve log, switch away for a minute, come back and read the gaps.
THE CONSOLE AS A REPL INTO THE PAGE
the utilities, live expressions, and monitoring
swipe the figure sideways, or tap expand for full screen
1/6
$0, $, $$
Selection helpers: $0 is the element selected in Elements, $1 the one before, up to $4; $_ is the last evaluated result; $("sel") and $$("sel") are querySelector and querySelectorAll (returning a real array, so .map works); $x("//xpath"). Right-click a node in Elements → "Store as global variable" gives temp1.