Crash Courses · PhD
Browser APIs, Storage & Performance
Use Web APIs, manage client-side storage, and write JS that performs in the browser.
12 min read+200 XP on completionCert: JavaScript Crash Course
Tap any word in the text below to start reading from there.
Browser APIs, Storage & Performance
The browser has a rich API surface. Using these correctly is what separates code that works from code that performs.
Client-Side Storage
// localStorage — persists across sessions
localStorage.setItem('theme', 'dark')
localStorage.getItem('theme')
// Store objects
localStorage.setItem('user', JSON.stringify({ id: 1, name: 'Jordan' }))
const user = JSON.parse(localStorage.getItem('user') ?? 'null')
// Always try/catch — throws in private browsing or when full
function safeGetLocal(key, fallback = null) {
try {
const item = localStorage.getItem(key)
return item ? JSON.parse(item) : fallback
} catch {
return fallback
}
}
sessionStorage.setItem('step', '2') // cleared on tab closeSecurity: never store JWTs, passwords, or API keys. Any JS on the same origin can read it.
Intersection Observer
// Wrong — fires thousands of times per scroll
window.addEventListener('scroll', () => {
if (element.getBoundingClientRect().top < window.innerHeight) revealElement()
})
// Correct — fires only when visibility changes
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible')
observer.unobserve(entry.target)
}
})
}, { threshold: 0.1 })
document.querySelectorAll('.animate-in').forEach(el => observer.observe(el))Debounce
function debounce(fn, delay) {
let timer
return (...args) => {
clearTimeout(timer)
timer = setTimeout(() => fn(...args), delay)
}
}
const searchAPI = debounce(async (query) => {
const results = await api.search(query)
render(results)
}, 300)
input.addEventListener('input', e => searchAPI(e.target.value))requestAnimationFrame for Animations
// Wrong — forced synchronous layout
setInterval(() => {
element.style.left = (parseFloat(element.style.left) + 1) + 'px'
}, 16)
// Correct
let x = 0
function animate() {
x += 1
element.style.transform = `translateX(${x}px)`
if (x < 300) requestAnimationFrame(animate)
}
requestAnimationFrame(animate)transform and opacity are GPU-composited. Animating width, height, top, left triggers layout recalculation every frame — significantly slower.
Clipboard API
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text)
showToast('Copied!')
} catch {
// fallback for older browsers
const ta = document.createElement('textarea')
ta.value = text
document.body.appendChild(ta)
ta.select()
document.execCommand('copy')
ta.remove()
}
}Reading progress
0% read
In this module
localStorage
sessionStorage
Intersection Observer
Debounce
0%