Performance Optimization
Performance optimization in JavaScript is the practice of making code run faster and feel more responsive by reducing wasted work, minimizing costly DOM updates, managing memory carefully, and avoiding blocking the main thread.
Part of the free JavaScript course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.
Performance testing requires a real browser environment. Download Node.js to run JavaScript, use Chrome DevTools Performance tab for profiling, or create a .html file to test DOM operations.
Master event loop mechanics, DOM optimization, memory management, and production-grade performance patterns.
What You'll Learn
- Avoiding main thread blocking
- Debouncing & throttling
- DOM optimization patterns
- GPU-accelerated animations
- Memoization & data structures
- Memory leak prevention
The Golden Rule: Avoid Blocking the Main Thread
JavaScript runs on a single-threaded event loop . Any task longer than 50ms is considered "slow" and causes frame drops. The key is breaking heavy work into smaller chunks.
Debouncing & Throttling Events
Events like scroll, resize, and input can fire hundreds of times per second. Debounce waits for activity to stop; Throttle limits execution rate.
DOM Optimization — The DOM is Slow
DOM operations are some of the slowest parts of JavaScript. Batch updates, use DocumentFragment, and minimize layout calculations.
Layout Thrashing — The Silent Killer
Alternating between reading and writing layout properties forces the browser to recalculate layout on every operation. This can make code 20-100× slower.
GPU-Accelerated Animations
Animating transform and opacity runs on the GPU and is incredibly fast. Animating top , left , width triggers expensive layout.
Memoization — Cache Expensive Results
If something is expensive, compute it once and cache the result. Memoization can turn exponential time complexity into linear.
Efficient Data Structures
Choosing the wrong data structure can cause massive performance loss. Use Map for key-value, Set for membership testing.
Memory Management & Leak Prevention
Memory leaks cause apps to slow down and crash. Always clean up event listeners, clear timers, and avoid capturing large data in closures.
Microtasks vs Macrotasks
Understanding the event loop is crucial for performance. Microtasks (Promises) run before rendering; macrotasks (setTimeout) run after.
Lazy Loading & Virtual Scrolling
Only load what the user needs right now. Dynamic imports, lazy images, and virtual scrolling can dramatically improve perceived performance.
Performance Profiling & Measurement
You can't optimize what you can't measure. Use the Performance API, console.time, and Chrome DevTools to find bottlenecks.
⚡ Performance Mastery Summary
- Main Thread: Keep tasks under 50ms, break heavy work into chunks
- Debounce/Throttle: Control event frequency for scroll, resize, input
- DOM: Batch updates, use DocumentFragment, avoid layout thrashing
- Animations: Use transform/opacity for GPU acceleration
- Memoization: Cache expensive calculations
- Data Structures: Use Map/Set for O(1) operations
- Memory: Clean up listeners, timers, and closures
- Event Loop: Use setTimeout to yield to rendering
- Lazy Loading: Load only what's needed, virtualize long lists
- Profiling: Measure before optimizing with DevTools
Practice quiz
According to the golden rule, any task longer than how many milliseconds is considered slow and causes frame drops?
- 10ms
- 500ms
- 50ms
- 5000ms
Answer: 50ms. Chrome considers tasks over 50ms as slow; break heavy work into chunks.
How does the lesson keep a heavy computation from blocking the UI?
- Break it into chunks and yield to the event loop (e.g. setTimeout)
- Run it twice
- Use a bigger loop
- Disable rendering
Answer: Break it into chunks and yield to the event loop (e.g. setTimeout). Splitting work into chunks and yielding lets the UI update between chunks.
Debounce is best used for which scenarios?
- scroll and game loops
- GPU animation
- garbage collection
- search, resize, and validation
Answer: search, resize, and validation. Debounce waits for activity to stop, ideal for search, resize, and validation.
Which DOM approach causes only ONE layout update for 1000 elements?
- appendChild one by one
- Using a DocumentFragment
- Reading offsetWidth each time
- Calling getBoundingClientRect
Answer: Using a DocumentFragment. A DocumentFragment batches the additions into a single update.
What causes layout thrashing?
- Alternating layout reads and writes in a loop
- Using const
- Caching results
- Using transform
Answer: Alternating layout reads and writes in a loop. Interleaving reads (offsetWidth) and writes forces repeated layout recalculation.
Which CSS properties are GPU-accelerated and best for animation?
- top and left
- width and height
- transform and opacity
- margin and padding
Answer: transform and opacity. transform and opacity only trigger compositing on the GPU; layout properties are slow.
Memoizing fibonacci changes its time complexity from O(2^n) to what?
- O(n^2)
- O(n)
- O(1)
- O(log n)
Answer: O(n). Caching subresults turns exponential O(2^n) into linear O(n).
Which runs BEFORE the next render: microtasks or macrotasks?
- Macrotasks (setTimeout)
- Neither
- Both equally
- Microtasks (Promise callbacks)
Answer: Microtasks (Promise callbacks). Microtasks like Promise callbacks run before rendering; macrotasks like setTimeout run after.
What technique renders only the visible rows of a very long list?
- Eager loading
- Virtual scrolling
- Inlining
- Layout thrashing
Answer: Virtual scrolling. Virtual scrolling renders just the visible items, e.g. 10,000 items as ~20 DOM nodes.
Which is a memory leak the lesson warns about?
- Returning a value
- Using Map
- A closure capturing large data that can't be garbage collected
- Calling performance.now()
Answer: A closure capturing large data that can't be garbage collected. Closures capturing huge data (and uncleared listeners/timers) prevent garbage collection.
Continue this course
- Previous: WebSockets
- Next: Final Project