logologo
  • AI Tools

    DB Query GeneratorMock InterviewResume BuilderLearning Path GeneratorCheatsheet GeneratorAgentic Prompt GeneratorCompany ResearchCover Letter Generator
  • XpertoAI
  • MVP Ready
  • Resources

    CertificationsTopicsExpertsCollectionsArticlesQuestionsVideosJobs
logologo

Elevate Your Coding with our comprehensive articles and niche collections.

Useful Links

  • Contact Us
  • Privacy Policy
  • Terms & Conditions
  • Refund & Cancellation
  • About Us

Resources

  • Xperto-AI
  • Certifications
  • Python
  • GenAI
  • Machine Learning

Interviews

  • DSA
  • System Design
  • Design Patterns
  • Frontend System Design
  • ReactJS

Procodebase © 2024. All rights reserved.

Level Up Your Skills with Xperto-AI

A multi-AI agent platform that helps you level up your development skills and ace your interview preparation to secure your dream job.

Launch Xperto-AI

JavaScript Performance Optimization Techniques

author
Generated by
Abhishek Goyan

22/10/2024

JavaScript

Sign in to read full article

JavaScript is an incredibly versatile language that is primarily used for building interactive web applications. However, as applications grow in size and complexity, performance optimization becomes crucial. In this article, we will explore key performance optimization techniques for vanilla JavaScript, complete with clear examples and explanations.

1. Minimize DOM Manipulations

The Document Object Model (DOM) is a programming interface for web documents, and interactions with it can be slow. To enhance performance, batch DOM manipulations instead of executing them one by one.

Example:

Instead of updating the DOM in a loop:

for (let i = 0; i < 1000; i++) { const newElement = document.createElement('div'); newElement.textContent = `Item ${i}`; document.body.appendChild(newElement); // DOM access in each iteration }

You can create a fragment and append it once:

const fragment = document.createDocumentFragment(); for (let i = 0; i < 1000; i++) { const newElement = document.createElement('div'); newElement.textContent = `Item ${i}`; fragment.appendChild(newElement); // Create in memory } document.body.appendChild(fragment); // Append to DOM once

2. Use Event Delegation

Instead of adding event listeners to each individual element, you can use event delegation. This technique attaches a single event listener to a parent element that can handle events from its child elements.

Example:

Instead of this:

const buttons = document.querySelectorAll('.btn'); buttons.forEach(button => { button.addEventListener('click', () => { console.log('Button clicked'); }); });

Use event delegation:

document.body.addEventListener('click', (event) => { if (event.target.matches('.btn')) { console.log('Button clicked'); } });

This approach is more efficient, especially for dynamic content, as it reduces the number of event listeners required.

3. Throttle and Debounce Events

When dealing with events like scrolling or resizing, frequent event firing can lead to performance issues. Throttling and debouncing are two techniques to optimize event handling.

Throttling Example:

function throttle(fn, delay) { let lastCall = 0; return function(...args) { const now = Date.now(); if (now - lastCall >= delay) { lastCall = now; fn.apply(this, args); } }; } window.addEventListener('scroll', throttle(() => { console.log('Scrolled!'); }, 200));

Debouncing Example:

function debounce(fn, delay) { let timer; return function(...args) { clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } window.addEventListener('resize', debounce(() => { console.log('Resized!'); }, 300));

4. Optimize Loops

Loops can introduce performance bottlenecks if not optimized properly. Use techniques like caching the length of the loop and opting for for...of or forEach instead of for loops when possible.

Example:

// Inefficient for (let i = 0; i < array.length; i++) { console.log(array[i]); } // Optimized const len = array.length; for (let i = 0; i < len; i++) { console.log(array[i]); } // Using forEach array.forEach(item => { console.log(item); });

5. Use Web Workers for Heavy Computation

If your application does heavy computations that can block the main thread, consider using Web Workers. Web Workers allow you to run scripts in background threads, enabling parallel execution.

Example:

// main.js const worker = new Worker('worker.js'); worker.onmessage = (e) => { console.log('Result:', e.data); }; worker.postMessage('Start'); // worker.js self.onmessage = (e) => { let result = heavyComputation(); postMessage(result); }; function heavyComputation() { // Simulate heavy computation let sum = 0; for (let i = 0; i < 1e8; i++) { sum += i; } return sum; }

6. Utilize Efficient Data Structures

Choosing the right data structure can greatly affect performance. For example, using Sets for unique values or Maps for key-value pairs can be more efficient than arrays.

Example:

// Using an array to track unique values - is inefficient for large data const uniqueValues = []; array.forEach(item => { if (!uniqueValues.includes(item)) { uniqueValues.push(item); } }); // Using a Set is more efficient const uniqueSet = new Set(array);

7. Avoid Global Variable Pollution

Global variables can lead to memory leaks and other performance issues. Minimize their use by encapsulating your code within functions or modules.

Example:

// Not recommended let globalVar = 'Hello'; function greet() { console.log(globalVar); } // Better approach using IIFE (function() { const localVar = 'Hello'; function greet() { console.log(localVar); } greet(); })();

8. Lazy Loading Assets

To improve load times, consider lazy loading images and other heavy assets. This ensures that content is only loaded when it comes into the viewport.

Example:

Using the native loading attribute:

<img src="large-image.jpg" loading="lazy" alt="A large image">

For more control, you can use Intersection Observer API:

const images = document.querySelectorAll('img[data-src]'); const imgObserver = new IntersectionObserver((entries, observer) => { entries.forEach(entry => { if (entry.isIntersecting) { const img = entry.target; img.src = img.dataset.src; // Load the image imgObserver.unobserve(img); } }); }); images.forEach(image => { imgObserver.observe(image); });

By implementing these techniques, you can significantly boost the performance of your vanilla JavaScript applications, ensuring a smoother user experience. Focus on optimizing elements like DOM interactions, event handling, looping, and asset loading while taking advantage of modern JavaScript features and best practices to maintain a high-performing codebase.

Popular Tags

JavaScriptPerformance OptimizationVanilla JS

Share now!

Like & Bookmark!

Related Collections

  • JavaScript Mastery: From Basics to Advanced Techniques

    15/10/2024 | VanillaJS

  • JavaScript Interview Mastery: 20 Essential Concepts

    22/10/2024 | VanillaJS

  • JavaScript Coding Challenges for Interviews

    14/09/2024 | VanillaJS

Related Articles

  • Understanding JavaScript Scope Chain

    22/10/2024 | VanillaJS

  • An In-Depth Guide to Function Currying in Vanilla JavaScript

    22/10/2024 | VanillaJS

  • Understanding JavaScript WeakMap and WeakSet

    22/10/2024 | VanillaJS

  • Flatten a Nested Array Without Using the Flat Function

    14/09/2024 | VanillaJS

  • Exploring Micro tasks vs Macro tasks in JavaScript

    25/07/2024 | VanillaJS

  • Creating a Promise-Based API Request Function

    14/09/2024 | VanillaJS

  • Build a Deep Clone Utility for Objects in JavaScript

    14/09/2024 | VanillaJS

Popular Category

  • Python
  • Generative AI
  • Machine Learning
  • ReactJS
  • System Design