Intermediate · Async JavaScript, modules and tools · topic 45 of 64 · 35 min
Debugging like a pro: DevTools and VS Code
Explanation
Read the error first
In beginner module 1 you opened the Console and saw red errors. Now read them like a pro. An error has three parts: the type (what kind of problem), the message (what exactly), and the stack trace: the list of function calls that led to it, newest first, each with a file name and line number.
Uncaught TypeError: Cannot read properties of undefined (reading 'price')
at cartTotal (cart.js:5:31)
at updateSummary (main.js:22:17)
at HTMLButtonElement.<anonymous> (main.js:40:5)| Error | Usual cause | Where to look |
|---|---|---|
| TypeError: Cannot read properties of undefined (reading 'price') | You used .price on something that is undefined: a wrong index, a missing await, an empty API answer | The value just before .price |
| ReferenceError: total is not defined | A typo, or a variable used outside its scope | The spelling and where it was declared |
| TypeError: x is not a function | Calling something that is not a function, often a wrong import or method name | What x really is (log it) |
| SyntaxError: Unexpected token | A missing bracket, comma or quote, or a JSON body that is not JSON | The line shown and the line above it |
| Uncaught (in promise) ... | A rejected promise with no catch | Add try/catch or .catch |
const cart = [{ name: 'Rice', price: 60, qty: 2 }, { name: 'Dal', price: 40, qty: 1 }];
console.log({ cart }); // the braces print the name with the value
console.table(cart); // an array of objects as a neat table
console.warn('Stock is low'); // yellow warning
console.error('Payment failed'); // red error, with a stack trace
console.group('Checkout'); // indent related logs together
console.log('step 1: address');
console.groupEnd();
console.time('load'); // measure how long something takes
// ...work...
console.timeEnd('load'); // load: 123 msBreakpoints: pause and look inside
A breakpoint pauses your code at one line, so you can see every variable at that moment. Open DevTools > Sources, open your file (Ctrl+P finds it by name), and click a line number. Reload or click the button, and the code stops there. You can also write the statement debugger; in your code: it pauses there whenever DevTools is open.
| Button (Chrome key) | What it does |
|---|---|
| Resume (F8) | Run until the next breakpoint |
| Step over (F10) | Run this line, including any function it calls, and stop on the next line |
| Step into (F11) | Go inside the function called on this line |
| Step out (Shift+F11) | Finish this function and stop where it was called from |
- Scope pane: every local variable and its value right now. Hover over a variable in the code to see it too.
- Watch: add expressions such as total or items.length; they update after every step.
- Call Stack: how you got here, like the stack trace.
- Conditional breakpoint: right-click a line number and pause only when, say, i === 3.
- Logpoint: right-click a line number to log a value without editing your file.
The Network panel
- Filter by Fetch/XHR to see only API calls. Click one to see its headers, the payload you sent and the response.
- Status column: spot 404s and 500s in red at a glance.
- Time and Waterfall columns: find the slow request.
- Throttling: choose "Slow 4G" to feel the page as a user on a weak mobile network does.
- Disable cache (works while DevTools is open): make sure you see your newest files.
- Preserve log: keep requests when the page reloads or moves to another page.
The Application panel shows what the page stored: Local storage, Session storage and Cookies. You can read, edit and delete values here. "Clear site data" resets everything, which is a quick way to test what a brand-new visitor sees.
Set up VS Code to catch bugs early
- Prettier extension: formats your code the same way every time.
- ESLint extension: underlines likely bugs, such as unused variables or using a variable before it is defined.
- Format on save: turn it on once and never fix spacing by hand again.
- Ctrl+P: open any file by name. Ctrl+Shift+F: search the whole project.
- Multi-cursor: Alt+Click adds cursors; Ctrl+D selects the next match of the word, so you can rename several at once. F2 renames a variable everywhere it is used.
- Integrated terminal: Ctrl+` opens a terminal inside VS Code for npm and git commands.
{
"editor.formatOnSave": true,
"editor.defaultFormatter": "esbenp.prettier-vscode"
}A debugging checklist
- Reproduce it: find exact steps that make the bug happen every time.
- Read the full error and click the first line of your own code in the stack trace.
- Check your guess with values: console.log, or better, a breakpoint.
- Shrink the problem: comment out parts until the bug disappears, then look at the last part removed.
- Check the Network panel for failed requests and the Application panel for old stored data.
- Fix one thing at a time, then test again, including on a phone-sized screen.
Watch the lesson
Debugging like a pro: DevTools and VS Code · 1/7
Every developer writes bugs. Good developers find them fast, with a method, not by guessing.
Prefer a video by a teacher? Find free videos on “chrome devtools javascript debugging breakpoints tutorial” on YouTube ↗
In real life: The cart total that showed NaN
Users of a grocery site reported "Total: Rs NaN" on some phones. The developer opened DevTools, set throttling to Slow 4G and found that the cart drew before the prices API had answered. A breakpoint in cartTotal showed item.price was undefined for one item, and the Watch pane showed the price list was still empty. The bug was a missing await. She fixed it, added a loading state, and wrote a test so it cannot come back.
Practice (0/3 done)
Find and fix the bugs. cartTotal(items) should return the total of price * qty for all items, and take Rs 50 off when that total is more than 500. Example: [{ price: 120, qty: 2 }, { price: 40, qty: 1 }] gives 280, and [{ price: 300, qty: 2 }] gives 550. The starter code has two bugs. Run it, read the error message, fix that line, then run it again to find the second bug.
Practise breakpoints. Put the buggy cartTotal from task 1 (before fixing it) in a small page with a button that calls it and shows the result. In DevTools > Sources, set a breakpoint on the line inside the loop, click the button, and step with F10. Add watch expressions for i, items.length and total. Find both bugs this way, without console.log. Then try a conditional breakpoint that pauses only when i === items.length.
Set up your tools and test like a mobile user. In VS Code, install the Prettier and ESLint extensions and turn on format on save. Then open your fetch page from the fetch topic in Chrome, open the Network panel, tick Disable cache, choose Slow 4G throttling, and reload. Note how long the page takes and whether your loading state shows. Finally, open the Application panel, look at Local storage and use Clear site data.
Quick quiz
Read more (free)
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.