🚀

How to Optimize JavaScript Performance

JavaScriptIntermediate

Techniques for faster JavaScript code.

Code Example

JavaScript
// 1. Debounce expensive operations
function debounce(func, delay) {
  let timeoutId;
  return function(...args) {
    clearTimeout(timeoutId);
    timeoutId = setTimeout(() => func.apply(this, args), delay);
  };
}

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

// 2. Throttle frequent events
function throttle(func, limit) {
  let inThrottle;
  return function(...args) {
    if (!inThrottle) {
      func.apply(this, args);
      inThrottle = true;
      setTimeout(() => inThrottle = false, limit);
    }
  };
}

const handleScroll = throttle(() => {
  console.log('Scrolling');
}, 100);

// 3. Memoization
function memoize(fn) {
  const cache = new Map();
  return function(...args) {
    const key = JSON.stringify(args);
    if (cache.has(key)) {
      return cache.get(key);
    }
    const result = fn.apply(this, args);
    cache.set(key, result);
    return result;
  };
}

const fibonacci = memoize((n) => {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});

// 4. Lazy loading
function loadImage(src) {
  return new Promise((resolve) => {
    const img = new Image();
    img.onload = () => resolve(img);
    img.src = src;
  });
}

// 5. Virtual scrolling (concept)
class VirtualList {
  constructor(container, items, itemHeight) {
    this.container = container;
    this.items = items;
    this.itemHeight = itemHeight;
    this.visibleCount = Math.ceil(container.clientHeight / itemHeight);
  }
  
  render(scrollTop) {
    const startIndex = Math.floor(scrollTop / this.itemHeight);
    const endIndex = Math.min(
      startIndex + this.visibleCount + 1,
      this.items.length
    );
    
    const visibleItems = this.items.slice(startIndex, endIndex);
    // Render only visible items
  }
}

// 6. Efficient DOM updates
function updateList(items) {
  const fragment = document.createDocumentFragment();
  items.forEach(item => {
    const li = document.createElement('li');
    li.textContent = item;
    fragment.appendChild(li);
  });
  list.appendChild(fragment); // Single reflow
}

// 7. RequestAnimationFrame for animations
function animate() {
  // Animation logic
  requestAnimationFrame(animate);
}
requestAnimationFrame(animate);

// 8. Avoid memory leaks
function setupEventListeners() {
  const handler = () => console.log('clicked');
  button.addEventListener('click', handler);
  
  // Cleanup when done
  return () => {
    button.removeEventListener('click', handler);
  };
}

// 9. Use appropriate data structures
// Set for unique values
const unique = new Set([1, 2, 2, 3]); // O(1) lookup

// Map for key-value pairs
const cache = new Map(); // O(1) lookup

// 10. Batch DOM operations
function batchUpdates() {
  // Bad: Multiple reflows
  element.style.width = '100px';
  const width = element.offsetWidth; // Forces reflow
  element.style.height = '100px';
  
  // Good: Single reflow
  element.style.width = '100px';
  element.style.height = '100px';
  const width = element.offsetWidth; // Single reflow
}

// 11. Use Web Workers for heavy computation
// Move CPU-intensive tasks to background thread

// 12. Code splitting
// Dynamic imports for lazy loading
async function loadModule() {
  const module = await import('./heavy-module.js');
  module.init();
}

Explanation

Debounce/throttle for frequent events. Memoize expensive functions. Use DocumentFragment for batch DOM updates. requestAnimationFrame for animations. Web Workers for CPU tasks. Choose right data structures.

Related Tutorials