Debugging JavaScript
Reading error messages, using browser DevTools, breakpoints, console methods, and systematic debugging techniques.
console.log("user: " + user) looks like it should print the user, but + converts the object to a string before console.log ever sees it. Plain objects become the useless [object Object], and arrays lose their brackets, so ["pen", "book"] prints as pen,book and you can't tell one item with a comma from two items. The log you added to find a bug hides the very thing you wanted to see.
const user = { name: "Asha", cart: ["pen", "book"] };
console.log("user: " + user); // + turns the object into a string first
console.log("cart: " + user.cart);
// user: [object Object]
// cart: pen,bookReading errors and using the console
Step 1: Read the error message
// Every JavaScript error tells you three things:
// 1. The ERROR TYPE
// 2. The MESSAGE (what went wrong)
// 3. The STACK TRACE (where in your code it happened)
// Example error:
// TypeError: Cannot read properties of undefined (reading 'name')
// at getUsername (app.js:15:22)
// at handleLogin (app.js:8:18)
// at HTMLButtonElement.onclick (index.html:23)
// Reading it:
// TypeError — type of error (wrong type being used)
// "reading 'name'" — you tried to access .name on something undefined
// app.js:15:22 — line 15, column 22 of app.js ← GO HERE FIRST
// The rest shows what called what (call stack, bottom-to-top = oldest to newest call)Common errors and what they mean
// TypeError — wrong type
// "Cannot read properties of null (reading 'X')" → something is null
// "X is not a function" → you're calling something that isn't a function
// "Cannot set properties of undefined" → parent object doesn't exist
// ReferenceError — variable doesn't exist
// "X is not defined" → the variable was never declared, or you misspelled it
// (using a let/const before its line gives "Cannot access 'X' before initialization" instead)
// SyntaxError — invalid code
// "Unexpected token" → missing bracket, comma, or typo in the code itself
// RangeError — value out of valid range
// "Maximum call stack size exceeded" → infinite recursion!
// Solving them:
const user = null;
// user.name → TypeError: Cannot read properties of null
const safeName = user?.name ?? "Anonymous"; // fix: use optional chainingPass values to console.log as separate arguments, with a comma rather than +, as the suspectFunction example in the Intermediate tab does. The console then shows the real object, which you can expand in DevTools. When you do need a single string (for a log file, say), serialise it deliberately:
const user = { name: "Asha", cart: ["pen", "book"] };
console.log("user:", user); // a comma passes the object itself
console.log("cart:", user.cart);
console.log(`user: ${JSON.stringify(user)}`); // or serialise it on purpose
// user: { name: 'Asha', cart: [ 'pen', 'book' ] }
// cart: [ 'pen', 'book' ]
// user: {"name":"Asha","cart":["pen","book"]}console methods beyond console.log
// Different severity levels (show differently in DevTools):
console.log("info message");
console.warn("warning — check this"); // yellow in DevTools
console.error("error — something wrong"); // red, includes stack trace
// console.table — perfect for arrays of objects:
console.table([
{ name: "Alice", score: 95 },
{ name: "Bob", score: 87 },
]);
// console.group — organise related logs:
console.group("Checkout process");
console.log("Cart validated");
console.log("Payment processed");
console.log("Email sent");
console.groupEnd();
// console.time — measure how long something takes:
console.time("my operation");
// ... code ...
console.timeEnd("my operation"); // "my operation: 12.3ms"Using browser DevTools (the most powerful tool)
// Open DevTools: F12 or Ctrl+Shift+I (Cmd+Option+I on Mac)
// Console tab:
// - See all errors (red), warnings (yellow), logs
// - Type JS directly — access your page's variables and functions
// - Click the filename in errors to jump to the code
// Sources tab — the debugger:
// - Find your JS file, click a line number to add a BREAKPOINT
// - Reload the page — execution stops at your breakpoint
// - Inspect all variable values at that moment
// - Step through code line by line with F10 (step over) or F11 (step into)
// Network tab:
// - See all HTTP requests your page makes
// - Check status codes, request/response bodies
// - Perfect for debugging fetch() calls
// The 'debugger' statement — set a breakpoint from code:
function processOrder(order) {
debugger; // DevTools will pause here (only when DevTools is open)
return order.items.reduce((sum, item) => sum + item.price, 0);
}Official Sources
- Chrome DevTools Documentation
- MDN Web Docs — Debugging JavaScript
- Node.js Debugging Guide
- MDN Web Docs — console
The Codex links only to official documentation and the ECMAScript specification. No third-party tutorials.