JavaScript Performance Optimization

Difficulty: Advanced

Question

What are common JavaScript performance optimization techniques? Explain debouncing and throttling.

Answer

Key performance techniques:

Debounce: delays execution until a pause in events. Use for search input, window resize - runs once after the user stops.

Throttle: limits execution to at most once per N ms. Use for scroll events, mousemove - ensures consistent rate.

requestAnimationFrame: schedules visual updates in sync with the browser's repaint cycle (~60fps). Avoids jank.

Web Workers: runs CPU-intensive code on a background thread, keeping the UI thread responsive.

Virtual scrolling: only renders visible rows. Code splitting & lazy loading: load only what is needed.

Code examples

Debounce and Throttle

function debounce(fn, delay) {
  let timer;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

function throttle(fn, interval) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      lastTime = now;
      return fn.apply(this, args);
    }
  };
}

const onSearch = debounce((query) => {
  console.log('Searching for:', query);
}, 300);

onSearch('r');
onSearch('re');
onSearch('react');
// After 300ms: Searching for: react

const onScroll = throttle(() => {
  console.log('Scroll handler at:', Date.now());
}, 200);

Debounce groups rapid events into one. Throttle limits frequency. Both prevent excessive callback execution.

requestAnimationFrame and Web Workers

function animate(element, targetX) {
  let currentX = 0;
  function step() {
    currentX += (targetX - currentX) * 0.1;
    element.style.transform = `translateX(${currentX}px)`;
    if (Math.abs(targetX - currentX) > 0.5) {
      requestAnimationFrame(step);
    }
  }
  requestAnimationFrame(step);
}

const workerCode = `
  self.onmessage = function(e) {
    const result = e.data.reduce((sum, n) => sum + n, 0);
    self.postMessage(result);
  };
`;

const blob = new Blob([workerCode], { type: 'application/javascript' });
const worker = new Worker(URL.createObjectURL(blob));

worker.onmessage = (e) => {
  console.log('Sum:', e.data);
  worker.terminate();
};

worker.postMessage(Array.from({ length: 100 }, (_, i) => i + 1));

performance.mark('start');
performance.mark('end');
performance.measure('op', 'start', 'end');
console.log(performance.getEntriesByName('op')[0].duration);

rAF batches DOM updates with the browser paint cycle. Web Workers move CPU work off the main thread.

Key points

Concepts covered

Debounce, Throttle, requestAnimationFrame, Web Workers