JavaScript Essentials¶
The language of the browser — and the only way to make your HTML respond to clicks, fetch your model API, and update results without reloading. The basics below cover what AI demos actually need.
Table of Contents¶
- Installation / Setup
- Core Syntax
- Common Operations
- Practical Examples
- Common Patterns
- Best Practices
- Common Mistakes
- Troubleshooting
- Related Cheat Sheets
- Official Documentation
Installation / Setup¶
<!-- at the end of <body>: -->
<script src="app.js"></script>
<!-- or run directly in the DevTools console (F12) -->
Modern JS also runs on servers (Node.js) — useful for quick API testing. No install needed to follow this sheet; open DevTools console and type along.
Core Syntax¶
Variables & types¶
let count = 0; // mutable
const name = "Ada"; // constant reference (prefer const)
var old = 1; // legacy — avoid
// Types
typeof 42; // "number"
typeof "hi"; // "string"
typeof true; // "boolean"
typeof null; // "object" (historical quirk!)
typeof [1, 2]; // "object"
typeof { a: 1 }; // "object"
Functions¶
function add(a, b) { return a + b; }
const add = (a, b) => a + b; // arrow function (prefer)
const square = x => x * x; // one param: no parens
add(1, 2); // 3
Arrays¶
const nums = [1, 2, 3];
nums.push(4); // [1,2,3,4]
nums.map(x => x * 2); // [2,4,6,8] — transform
nums.filter(x => x > 1); // [2,3,4] — select
nums.reduce((a, b) => a + b, 0); // 10 — fold
nums.find(x => x === 3); // 3 — first match
nums.includes(2); // true
nums.slice(1, 3); // [2,3]
Objects¶
const pred = { label: "positive", score: 0.93 };
pred.label; // "positive"
pred["score"]; // 0.93
const { label, score } = pred; // destructuring
const withMore = { ...pred, source: "model-v2" }; // spread copy
Template strings¶
Common Operations¶
DOM selection & manipulation¶
document.querySelector(".card"); // first match
document.querySelectorAll("tr"); // NodeList (array-like)
document.getElementById("results");
document.createElement("div");
el.textContent = "hello"; // safe text (escape for free)
el.innerHTML = "<b>hi</b>"; // HTML (XSS risk with user data!)
el.style.display = "none"; // hide
el.classList.add("error"); // classes
el.hidden = true;
Events¶
const btn = document.getElementById("run");
btn.addEventListener("click", () => {
console.log("clicked");
});
document.querySelector("form").addEventListener("submit", (e) => {
e.preventDefault(); // stop page reload!
handleForm();
});
// event delegation: one listener for many rows
document.querySelector("table").addEventListener("click", (e) => {
if (e.target.matches("button.delete")) { ... }
});
Async & fetch (the API call)¶
async function predict(text) {
const res = await fetch("/predict", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return await res.json(); // parsed JSON -> JS object
}
// usage with error handling
try {
const data = await predict("Great product!");
console.log(data.label, data.score);
} catch (err) {
console.error("prediction failed:", err);
}
| Promise helper | Use |
|---|---|
fetch(url, options) |
HTTP request |
res.ok, res.status, res.statusText |
response status |
res.json(), res.text(), res.blob() |
parse body |
await / async |
readable async |
Promise.all([...]) |
run requests in parallel |
setTimeout(fn, ms) |
delay |
Practical Examples¶
1. Prediction form wired end-to-end (see html.md for the form)¶
document.getElementById("sentiment-form")
.addEventListener("submit", async (e) => {
e.preventDefault();
const text = document.getElementById("review").value;
const out = document.getElementById("result");
out.textContent = "Analyzing…";
try {
const res = await fetch("/predict", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ text }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
out.textContent = `Sentiment: ${data.label} (${(data.score * 100).toFixed(1)}%)`;
out.className = data.label === "positive" ? "badge ok" : "badge error";
} catch (err) {
out.textContent = `Error: ${err.message}`;
out.className = "badge error";
}
});
2. Parallel model calls (compare two models)¶
const [r1, r2] = await Promise.all([
fetch("/predict", { method: "POST", headers: {"Content-Type": "application/json"},
body: JSON.stringify({ text, model: "v1" }) }).then(r => r.json()),
fetch("/predict", { method: "POST", headers: {"Content-Type": "application/json"},
body: JSON.stringify({ text, model: "v2" }) }).then(r => r.json()),
]);
console.log("v1:", r1.score, "v2:", r2.score);
3. Render predictions into a table¶
function renderTable(rows) {
const tbody = document.querySelector("#scores tbody");
tbody.replaceChildren(); // clear
for (const r of rows) {
const tr = document.createElement("tr");
const tdLabel = document.createElement("td");
tdLabel.textContent = r.label;
const tdScore = document.createElement("td");
tdScore.textContent = (r.value * 100).toFixed(2) + "%";
tr.append(tdLabel, tdScore);
tbody.append(tr);
}
}
Common Patterns¶
// Debounce: wait for the user to stop typing before calling an API
function debounce(fn, ms = 300) {
let t;
return (...args) => { clearTimeout(t); t = setTimeout(() => fn(...args), ms); };
}
input.addEventListener("input", debounce(async () => {
const results = await search(input.value); // autocomplete
}));
// Guard against out-of-order responses (stale results)
let requestId = 0;
input.addEventListener("input", async () => {
const id = ++requestId;
const data = await fetchResults(input.value);
if (id === requestId) render(data); // drop stale replies
});
Best Practices¶
- Prefer
const, thenlet— nevervarin new code. - Use
textContentfor user data,innerHTMLonly for trusted markup — XSS is the top web vulnerability (see Cybersecurity). - Always check
res.okand wrap fetches in try/catch. - Use arrow functions and array methods (
map/filter) over manual loops. - Keep the DOM in sync in one place — render functions beat scattered updates.
- Debounce input-driven API calls; cancel/ignore stale async results.
- Handle loading & error states in the UI, not just the happy path.
- Learn to debug with
console.log, breakpoints, and the Network tab.
Common Mistakes¶
| Mistake | Consequence | Fix |
|---|---|---|
Forgetting await |
Promise {<pending>} / undefined data |
await fetch(...) |
Not calling e.preventDefault() |
Page reloads, state lost | Call it first in submit handlers |
== loose equality |
Surprising coercion ("1" == 1) |
Use === |
| Blocking the main thread with a big loop | Frozen page | Chunk work or move to Web Worker |
innerHTML with user input |
XSS | textContent or escape |
| Attaching listeners before DOM exists | "Cannot read properties of null" | Script at end of body or DOMContentLoaded |
| Mixing sync/async error handling | Unhandled rejections | try/catch around awaits |
| Mutating props/state ad hoc | Hard-to-trace bugs | Immutable updates (spread) |
Troubleshooting¶
| Symptom | Cause | Fix |
|---|---|---|
undefined is not a function |
Typo/import missing | Console shows the call site |
Cannot read properties of null |
Element not found/loaded yet | Check id; defer script |
| CORS error on fetch | Server lacks header | Backend must allow origin (see http.md) |
res.json() fails |
Response isn't JSON (HTML error page) | res.text() first; check Network tab |
Value is [object Promise] |
Missing await | Add await |
| Works in console, not on load | Timing | Wrap in DOMContentLoaded |
| NaN in math | String operands | Number(x) / +x coercion deliberately |
Related Cheat Sheets¶
- html.md — the DOM you manipulate
- css.md — classes/styles you toggle
- http.md — what fetch sends/receives
- json.md — the data format in every
res.json() - APIs — building the endpoints you call
- Home · Central Navigation Index
Official Documentation¶
Last Updated¶
2026-09-06 — Initial version.