Twenty constructs cover nearly everything
You can read most generated JavaScript with a small vocabulary. Here is essentially all of it.
const total = 500 // a value that will not be reassigned
let count = 0 // one that will
function slotIsFree(a, b) { return a.end <= b.start }
const slotIsFree = (a, b) => a.end <= b.start // the same thing
const booking = { id: 71, name: 'Anita' } // an object: named fields
const bookings = [b1, b2, b3] // an array: an ordered list
bookings.map(b => b.name) // transform each, same length
bookings.filter(b => b.status === 'confirmed') // keep some
bookings.find(b => b.id === 71) // first match, or undefined
if (!booking) return // guard clause: leave early
booking?.customer?.name // safe if either is missing
name ?? 'Guest' // fallback if null or undefined=== compares without type coercion and == does not. '1' == 1 is true and '1' === 1 is false. Always use the triple form, and treat a double one in a diff as something to look at.
Async is where the real bugs live
Anything touching a network or a database takes time, and JavaScript does not wait unless told.
const rows = await db.select().from(bookings) // waits
const rows = db.select().from(bookings) // does notThe second gives you a Promise: an object representing work in progress. Print it and you get Promise { <pending> }. Treat it as an array and you get nothing, or undefined where a value should be, usually with no error at all.
The common shapes to recognise:
async function getBookings() { // any function using await
const rows = await db.select() // must be marked async
return rows
}
await Promise.all([a(), b(), c()]) // run three, wait for all
try {
await save(booking)
} catch (e) {
// handle it, or the request dies silently
}A missing await produces a specific and confusing symptom: it works on your fast local database and fails on the slower production one, because the timing changed.
Where the code runs
In a modern framework the same-looking file may run on the server, in the browser, or both. This is the distinction that decides whether a secret is exposed.
'use client' // this file runs in the browserA file with that line at the top is shipped to the user’s device. Anything it imports is shipped too. An API key referenced anywhere in that import chain is public.
So when reviewing, ask of any file touching secrets or the database: does this run on the server? If it says use client, or it lives in a component that one imports, the answer is no.
Six smells worth stopping on
catch (e) {}: a failure discarded. The user sees success.
console.log left in production code. Harmless until it prints a user’s data into your host’s logs, which is a real privacy problem and a very common one.
any in TypeScript. It disables checking for that value. A model that could not work out a type will reach for it, and every guarantee downstream is now unenforced.
// TODO or // In a real app you would…: the model marking work it did not do. Search for both after any large generated change.
setTimeout used to wait for something. A one-second delay hoping data has arrived is not synchronisation; it fails on a slow connection and looks fine on yours.
Mutation of something shared. bookings.push(x) inside a function that was supposed to only read is how state changes in places nobody expects.
The four questions again, applied
For any function in a diff: what goes in, what comes out, what does it change that outlives the request, and what happens when it fails.
That third question is the one JavaScript makes easy to miss, because a database write and a variable assignment look almost identical on the page. Look for insert, update, delete, fetch, writeFile, and any await at all: those are the lines with consequences.
Learn by tracing, not by tutorials
The fastest way to reach the level this lesson describes is to take one feature in your own app and read every line of it, asking the model to explain anything you cannot follow. Twenty minutes on real code you care about beats a week of exercises about shopping carts, because you already know what the code is supposed to do, and that is what makes reading it possible.
Every lesson here is open. Your progress is recorded once you pass the Building with AI exam.
Check your understanding
A query works locally but returns undefined in production. Which explanation fits the pattern best?
Pick the one you would defend. Your answer stays private.
Stuck on something?Ask Beatriz, your AI tutor
