Introduction
Two things separate a practice script from a real app. First: real apps survive mistakes — bad input, broken data, a failed calculation — instead of dying on the first error. Second: real apps remember — close the page, press refresh, and the data is still there.
This lesson delivers both: try/catch/finally and throw for surviving, and localStorage — the browser's small permanent drawer — for remembering. (Roman Urdu: Achi app galti par marti nahi, sambhalti hai — aur localStorage ki wajah se refresh ke baad bhi data yaad rehta hai.)
Key points
tryholds code that can fail — put the risky lines insidetry { ... }. If any line inside throws an error, the rest of thetryblock is skipped at once.catch (error)receives the error object — the program lands here instead of dying, and it survives. The error object carrieserror.message— the human-readable line that explains what went wrong. Show it, log it, or decide with it.(Roman Urdu: catch woh jaal hai jo error ko pakar leta hai — program girta nahi, aage chalta rehta hai.)finallyruns either way — success or failure, thefinally { ... }block always runs last. It is the place for cleanup: hiding a loading spinner, closing what you opened, resetting a button.throwraises your own error —throw new Error("Name cannot be empty");stops the current function and throws, exactly like a built-in error. Use it for validation with teeth: input that is impossible (dividing by zero, an empty name) gets refused loudly, not silently turned into nonsense.JSON.parseis the perfect live demo — parsing broken JSON text throws a real error every time. In atryblock,catchcatches it and the app continues — in the open, the same line kills the script.localStorageis a small permanent drawer for this site, in this browser —localStorage.setItem(key, value)saves,localStorage.getItem(key)reads back (ornullif the key is not there),localStorage.removeItem(key)deletes one key,localStorage.clear()empties the whole drawer.- Values are strings only —
localStoragecannot hold an object or an array directly. Objects travel as JSON:JSON.stringifyon the way in,JSON.parseon the way out — Lesson 3.18 paying off.(Roman Urdu: localStorage mein sirf text jata hai — object ko JSON bana kar rakho, nikaal kar wapas parse karo.) - Honest limits — about 5 MB of space, saved in this browser on this device only (nothing syncs to a server or another phone), and it is easy for anyone with the browser to read — so never store passwords or secret data in it.
Code examples
Example 1 — try, catch, finally, and your own throw
function divide(a, b) {
if (b === 0) {
throw new Error("Cannot divide by zero");
}
return a / b;
}
try {
const result = divide(10, 0);
console.log("Result: " + result);
} catch (error) {
console.log("Caught an error: " + error.message);
} finally {
console.log("Division attempt finished");
}
console.log("Program still running");What it does: divide refuses impossible input with its own throw. The call sits inside try, so the thrown error jumps straight to catch, which prints the error's message. finally runs after that, and — the whole point — the program carries on to its last line instead of dying at the bad division.
What you will see: three lines, in this order: Caught an error: Cannot divide by zero, then Division attempt finished, then Program still running. The Result: line never appears, because the error skipped the rest of the try block. Change the call to divide(10, 2) and run again: now you see Result: 5, then Division attempt finished, then Program still running — finally and survival on both paths.
Example 2 — JSON.parse on broken text: the app survives
const brokenText = "this is not json";
try {
const data = JSON.parse(brokenText);
console.log("Parsed name: " + data.name);
} catch (error) {
console.log("The data could not be read.");
console.log("Reason: " + error.message);
}
console.log("The app continues with default settings");What it does: It tries to parse text that is not JSON at all. JSON.parse throws — parsing broken text is impossible, and it says so. The catch block turns that crash into a calm decision: tell the user the data could not be read, show the reason, and let the app continue with defaults.
What you will see: first line: The data could not be read. Second line: Reason: followed by the browser's own JSON error message — the exact wording of this line differs a little between browsers, because each browser writes its parse errors in its own words. Third line: The app continues with default settings. Remove the try/catch and run the parse alone: the script dies on that line and the last message never appears — that difference is the whole lesson.
Example 3 — localStorage: the refresh-restore page
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Remember My Name — Code Scope</title>
</head>
<body>
<h1 id="greeting">Hello, guest</h1>
<input type="text" id="nameInput" placeholder="Write your name">
<button id="saveBtn">Save name</button>
<button id="removeBtn">Forget name</button>
<script>
const greeting = document.getElementById("greeting");
const nameInput = document.getElementById("nameInput");
function showSavedName() {
const savedName = localStorage.getItem("username");
if (savedName !== null) {
greeting.textContent = "Hello, " + savedName;
} else {
greeting.textContent = "Hello, guest";
}
}
document.getElementById("saveBtn").addEventListener("click", () => {
const name = nameInput.value.trim();
if (name === "") {
alert("Please write a name first");
return;
}
localStorage.setItem("username", name);
showSavedName();
});
document.getElementById("removeBtn").addEventListener("click", () => {
localStorage.removeItem("username");
showSavedName();
});
showSavedName();
</script>
</body>
</html>What it does: On every page load, the script reads the username key from localStorage and greets that name — or guest if nothing is saved. The Save button stores the typed name with setItem; the Forget button deletes just that key with removeItem and the greeting falls back to guest. No variable holds the name between loads — the drawer does.
What you will see: open the page: Hello, guest. Type Ali and click Save name: the heading changes to Hello, Ali. Now press F5 to refresh — the heading still says Hello, Ali. A normal variable would have died with the refresh; localStorage did not. Click Forget name: the heading returns to Hello, guest, and a refresh now keeps it as guest, because the key itself is gone.
Quick recap
tryholds risky code,catch (error)receives the error (readerror.message) and the program survives,finallyruns either way for cleanup;throw new Error("...")raises your own error for impossible input.localStoragesaves per site, in this browser, across refreshes:setItem,getItem,removeItem,clear.- Values are strings only — objects go in with
JSON.stringifyand come out withJSON.parse. About 5 MB, this browser only, never passwords.
Common mistakes
- Putting the whole program inside one giant
try— when everything is "protected", thecatchcannot tell you what failed, and real bugs get quietly swallowed. The fix: wrap only the specific risky lines, and always useerror.messagein thecatchso failures stay visible. - Saving an object straight into localStorage —
localStorage.setItem("user", userObject)stores the useless text[object Object], and your data is gone. The fix:setItem("user", JSON.stringify(userObject))in,JSON.parse(getItem("user"))out. - Trusting
getItemto always find the key — on the first ever visit, the key does not exist andgetItemreturnsnull, which crashes code that expects text or an object. The fix: check fornullfirst (or useJSON.parse(localStorage.getItem("tasks")) || []for a safe default, as the Todo project does).
Practice
- Write a
setAge(age)function that throwsnew Error("Age cannot be negative")when the age is below 0, and otherwise returns the age. Call it insidetry/catchwith-5and then with25, and print a message fromfinallyboth times. - Build a tiny page with one colour button: clicking it saves
"dark"under the keythemeinlocalStorageand paints the page background dark. On load, read the key — if it says"dark", start dark. Refresh the page and prove the choice survived. Add a second button that removes the key and returns the page to light.