JavaScript Performance
Fast code starts with measuring, not guessing. A few habits make the biggest difference in real applications.
On this page · 5 min · Advanced
On this page
- Learning objectives
- Explanation
- Code example
- Step by step
- Real-world use
- Common mistakes
- Best practices
- Remember this
- Practice exercise
- Mini quiz
- Related topics
- My notes
- Reading time
- 5 min
- Difficulty
- Advanced
- Updated
- Oct 27, 2026
Related tutorials
Learning objectives#
- Measure code with performance.now
- Choose data structures for fast lookups
- Batch DOM updates
- Know when to debounce, lazy-load and split code
Explanation#
Measure first: performance.now() gives precise timestamps; the DevTools Performance panel shows where time really goes.
Data structures matter: Array.includes checks items one by one; Set.has jumps straight to the answer.
The DOM is slow compared to plain JavaScript. Build elements off-page (DocumentFragment or one innerHTML/replaceChildren call) and insert once.
Reading layout (offsetHeight) right after writing styles forces the browser to recalculate layout repeatedly — “layout thrashing”. Group reads, then writes.
Code example: Array.includes vs Set.has#
const ids = Array.from({ length: 100_000 }, (_, i) => i);
const idSet = new Set(ids);
const lookups = Array.from({ length: 2_000 }, () => Math.floor(Math.random() * 200_000));
let t = performance.now();
lookups.filter(x => ids.includes(x));
const arrayMs = performance.now() - t;
t = performance.now();
lookups.filter(x => idSet.has(x));
const setMs = performance.now() - t;
console.log(`Array.includes: ${arrayMs.toFixed(1)} ms`);
console.log(`Set.has: ${setMs.toFixed(1)} ms`);
console.log('Set is faster:', setMs < arrayMs);
Array.includes: 95.3 ms Set.has: 0.4 ms Set is faster: true (your exact timings will differ)
Step-by-step explanation#
- Both approaches answer the same question for 2,000 lookups.
- includes may scan up to 100,000 items for each lookup.
- Set.has finds each answer almost instantly.
- Measuring proves the difference instead of guessing.
Real-world use case#
Filtering thousands of products, checking permissions, and rendering long lists smoothly all depend on these habits.
Common mistakes#
Guesses are often wrong. Profile first, then fix the slowest part.
Thousands of separate appends trigger repeated work. Build a fragment and append once.
Best practices#
- Measure with DevTools and performance.now
- Use Set/Map for frequent lookups
- Batch DOM writes and avoid layout thrashing
- Debounce/throttle frequent events; lazy-load heavy code with dynamic import()
Remember this#
Measure → change → measure again.
Lots of lookups? Use a Set or Map.
Touch the DOM as rarely as possible — build, then insert once.
Practice exercise#
Your task: Render 1,000 <li> elements efficiently into a <ul> using a DocumentFragment.
Show solution
const frag = document.createDocumentFragment();
for (let i = 1; i <= 1000; i++) {
const li = document.createElement('li');
li.textContent = `Item ${i}`;
frag.append(li);
}
list.append(frag); // one DOM insertion
Mini quiz#
What is the first step in performance tuning?
Want more? Practise all JavaScript MCQs · JavaScript interview questions
My notes#
Saved in this browser.