JSTAcademy
0 XP
Dashboard
Crash Courses
Browser APIs, Storage & Performance
12 min
PhD+200 XP
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 close

Security: 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()
  }
}
0%