Frontend Master

JavaScript Curriculum

Remembering Things
+40 XP

Remembering Things

easy
~20 min·40 XP

A Nexus user sets their theme to dark, marks three lessons complete, and closes the browser. When they return tomorrow, everything is remembered. When they open a second tab, it shares the same progress. When they sign in on a new device, their data syncs from the server. Three different storage mechanisms handle these three different needs.

Data that survives the page

By default, JavaScript variables disappear when the page closes. Browser storage APIs provide persistence — data that survives refreshes, tab closes, even browser restarts.

Try the interactive simulator below, then use the comparison table to decide which mechanism fits each use case:

browser storage — interactive simulator

localStorage contents

localStorage

  • Persists forever — survives page closes, browser restarts
  • Scoped to origin (domain + protocol + port)
  • Synchronous — blocks the main thread if reading large data
  • ~5MB limit. Strings only — JSON.stringify for objects
browser storage options — comparison
localStoragesessionStorageCookiesIndexedDB
Capacity~5 MB~5 MB~4 KBHundreds of MB
PersistenceUntil clearedTab closeExpiry dateUntil cleared
Sent to serverNeverNeverEvery requestNever
JS accessibleYesYesYes (if no HttpOnly)Yes
Data typeStrings onlyStrings onlyStrings onlyAny (structured)
API styleSyncSyncdocument.cookieAsync (Promise)
Best useUser prefs, theme, tokenPer-tab temp dataAuth sessionsOffline data, large blobs

localStorage — the workhorse

localStorage persists until explicitly cleared. It's synchronous and stores strings only.

js
// Store localStorage.setItem('theme', 'dark') localStorage.setItem('userId', '42') // Retrieve const theme = localStorage.getItem('theme') // 'dark' const gone = localStorage.getItem('missing') // null // Remove one localStorage.removeItem('userId') // Clear everything localStorage.clear() // How many items? localStorage.length // number of keys

Storing objects — always use JSON

js
const prefs = { theme: 'dark', fontSize: 16, notifications: true } // Save localStorage.setItem('prefs', JSON.stringify(prefs)) // Load const raw = localStorage.getItem('prefs') const loaded = raw ? JSON.parse(raw) : null

A common utility pattern used across every project:

js
function getStored(key, fallback = null) { try { const raw = localStorage.getItem(key) return raw !== null ? JSON.parse(raw) : fallback } catch { return fallback // JSON.parse failed — malformed data } } function setStored(key, value) { localStorage.setItem(key, JSON.stringify(value)) }
⚠️localStorage is synchronous — it blocks
Every read and write on localStorage blocks the main thread. For small values (user preferences, tokens, simple flags) this is imperceptible. For large data, consider IndexedDB which is fully async.

sessionStorage — per-tab temporary storage

Same API as localStorage, but data is cleared when the tab closes. Each tab gets its own isolated sessionStorage — two tabs don't share it.

js
sessionStorage.setItem('draft', JSON.stringify(formData)) const draft = JSON.parse(sessionStorage.getItem('draft') ?? 'null')

Use cases: multi-step form progress within a session, temporary UI state, scroll position, tab-specific filters.


Cookies — when you need the server

Cookies are the oldest browser storage mechanism. Unlike localStorage, cookies are sent to the server with every HTTP request — making them the right choice for authentication sessions.

js
// Set a cookie (JavaScript side — limited control) document.cookie = 'username=Alex; path=/; max-age=86400' // Read — awkward API, always the full cookie string document.cookie // 'username=Alex; theme=dark; ...' // Parse a specific cookie: const getCookie = (name) => { return document.cookie .split('; ') .find(row => row.startsWith(name + '=')) ?.split('=')[1] }

In practice, most applications set authentication cookies from the server using Set-Cookie headers with HttpOnly (invisible to JavaScript, protects against XSS) and Secure (HTTPS only) flags. Never store sensitive data in JavaScript-accessible cookies.


IndexedDB — large structured data

For large datasets, binary files, or offline-first apps, IndexedDB is the answer. It's asynchronous, has no size restriction (browser-dependent, usually hundreds of MB), and stores any JavaScript value.

js
// Open a database const request = indexedDB.open('nexus-db', 1) request.onupgradeneeded = (event) => { const db = event.target.result db.createObjectStore('lessons', { keyPath: 'id' }) } request.onsuccess = (event) => { const db = event.target.result // Write const tx = db.transaction('lessons', 'readwrite') tx.objectStore('lessons').put({ id: 'lesson-01', progress: 100 }) // Read const read = db.transaction('lessons', 'readonly') const getReq = read.objectStore('lessons').get('lesson-01') getReq.onsuccess = () => console.log(getReq.result) }

For IndexedDB, most real projects use the idb library which wraps the callback API in Promises.


Choosing the right storage

NeedUse
User preferences (theme, language)localStorage
Auth token (non-HttpOnly)localStorage with care
Auth session cookieServer-set HttpOnly cookie
Multi-step form statesessionStorage
Per-tab statesessionStorage
Large offline dataIndexedDB
Structured query supportIndexedDB

Your challenge

savePreference and getPreference are the utility pair every real project needs. The key insight: JSON.stringify before saving (so objects survive the string-only constraint), JSON.parse after loading. Guard the get with ?? defaultValue for the missing-key case, and wrap parse in try/catch for malformed data. This pattern appears verbatim in production codebases.

Challenge

Write three functions: savePreference(key, value) that stores a value in localStorage. getPreference(key, defaultValue) that retrieves it — returning defaultValue if it isn't set. clearPreference(key) that removes it. For values that are objects or arrays, use JSON.stringify on save and JSON.parse on retrieval. Test by saving { theme: 'dark', fontSize: 16 } under the key 'ui-prefs', then reading it back.

localStoragesessionStoragecookiesIndexedDBJSON.stringifyJSON.parsebrowser-storagepersistence
Remembering Things | Nexus Learn