JavaScript performance optimization is about making your web applications faster, smoother, and more efficient. It focuses on reducing load times, avoiding unnecessary work, controlling memory usage, and keeping interactions responsive so users experience minimal lag or jank.
Well-optimized JavaScript leads to a better user experience, lower bounce rates, and can even improve SEO because search engines reward fast-loading, responsive pages.
requestAnimationFrame instead of setTimeout or setInterval for smoother animations.scroll and resize.async and defer or lazy loading so scripts do not block page rendering.Debouncing ensures a function runs only after a certain period of inactivity. It is ideal for search boxes, window resize, and scroll tracking where you do not want to run logic on every single event.
Throttling ensures a function runs at most once per defined interval. It is useful for continuous events like scrolling, where updates can happen every 100–200 ms instead of on every pixel move.
Memoization stores function results based on inputs. When the same input appears again, the stored value is returned instantly instead of recalculating, which is helpful for expensive operations.
When including scripts:
async loads the script in parallel and executes it as soon as it is ready.defer loads the script in parallel but executes it after HTML parsing finishes.
// Debounce helper: runs the function only after the user stops scrolling
function debounce(func, delay) {
let timer;
return function() {
clearTimeout(timer);
timer = setTimeout(() => func.apply(this, arguments), delay);
};
}
// Attach a debounced listener so the handler is not called on every scroll event
window.addEventListener('scroll', debounce(() => {
console.log('Scroll event triggered!');
}, 200));
// Simple memoized function that caches results based on the input value
function expensiveOperation(x) {
if (!expensiveOperation.cache) {
expensiveOperation.cache = {};
}
if (!expensiveOperation.cache[x]) {
console.log('Calculating for', x);
expensiveOperation.cache[x] = x * x; // example calculation
}
return expensiveOperation.cache[x];
}
console.log(expensiveOperation(5)); // Calculates and caches
console.log(expensiveOperation(5)); // Returns from cache
// Example of non-blocking script loading using async and defer
<!-- Async: downloads in parallel and executes as soon as ready -->
<script src="script-analytics.js" async></script>
<!-- Defer: downloads in parallel and executes after HTML parsing -->
<script src="script-main.js" defer></script>
Type in the input below. The "Simulated request" text updates only when you stop typing for 500 ms. This mimics how debouncing can reduce the number of API calls.
Waiting for input...
Without debouncing, the handler would run on every keystroke. With debouncing, it runs only after you pause, which is much more efficient.
resize event that logs the new window size only after the user stops resizing.defer or async and measure how it affects initial page load time.