You get a bonus - 1 coin for daily activity. Now you have 1 coin

Optimising events in JavaScript: debouncing and throttling

Lecture



Events in JavaScript play an important role in building dynamic and interactive web pages. They let you perform certain actions in response to user actions or other events on the page. Here are the main concepts and examples of working with events in JavaScript:

Types of events in JavaScript

  • Mouse events:click - a mouse click.dblclick - a double click.mouseover - the mouse pointer moves over an element.mouseout - the mouse pointer leaves an element.mousedown - a mouse button is pressed.mouseup - a mouse button is released.
  • Keyboard events:keydown - a key is pressed.keyup - a key is released.keypress - a key is pressed (deprecated, use keydown or keyup instead).
  • Form events:submit - the form is submitted.change - the value of a form element changes.focus - the element receives focus.blur - the element loses focus.
  • Document events:DOMContentLoaded - the HTML document has fully loaded and the DOM has been built.load - all page resources have fully loaded (including images, styles and so on).resize - the window is resized.scroll - the page is scrolled.

Optimising events in JavaScript: debouncing and throttling

Optimising events

Optimising events in JavaScript is important for improving application performance, especially when you are dealing with a large number of events and DOM elements.

Here are several key optimisation strategies and approaches:


1. Debouncing and Throttling (reducing the call rate)

These techniques help reduce the number of calls to handler functions that may run too often (for example, on the scroll, resize or input).

  • Debouncing: runs the function only after a series of event calls has finished. For example, for a resize of the browser window:
function debounce(func, delay)
{ 
  let timer; 
   return function (...args) {
     clearTimeout(timer); timer = setTimeout(() => func.apply(this, args), delay); 
   }; 
} 

window.addEventListener('resize', debounce(() => { console.log('Window resized!'); }, 300)); 
  • Throttling: limits how often the function runs. For example, on scroll:
function throttle(func, limit)
{ let lastCall = 0; 
return function (...args) {
    const now = Date.now();
   if (now - lastCall >= limit) { lastCall = now; func.apply(this, args); } 
  }; 
} 

window.addEventListener('scroll', throttle(() => { console.log('Scrolling...'); }, 200)); 

2. Event delegation

Instead of binding events to every DOM element, you can use delegation through the nearest common parent.

Example: clicking on list items:

document.querySelector('#list').addEventListener('click', (event) => 
{
  if (event.target && event.target.tagName === 'LI') { console.log('Clicked:', event.target.textContent); }
}); 

3. Removing handlers you no longer need

Remove event handlers once they are no longer needed:

function handleClick() 
{ 
console.log('Button clicked'); 
} 

const button = document.querySelector('button'); 

button.addEventListener('click', handleClick); 

// Remove the handler later
 button.removeEventListener('click', handleClick); 

4. Using passive: true

For events such as scroll and touchstart, enabling the passive flag can improve performance:

window.addEventListener('scroll', () => { console.log('Scrolling...'); }, { passive: true }); 

This lets the browser avoid blocking scrolling, which improves responsiveness.


5. Minimising DOM operations

Do not modify the DOM on every event call. Instead:

  • Use DOM fragments or temporary variables.
  • Apply DOM changes in batches.

Example:

const fragment = document.createDocumentFragment();
 for (let i = 0; i < 100; i++) 
{ 
  const item = document.createElement('div'); 
  item.textContent = `Item ${i}`; 
  fragment.appendChild(item); 
}
 document.querySelector('#container').appendChild(fragment); 

6. Using a single handler per event

Try to avoid adding several handlers to the same event. For example, instead of:

button.addEventListener('click', () => console.log('Handler 1'));
button.addEventListener('click', () => console.log('Handler 2')); 

it is better to combine the logic:

button.addEventListener('click', () => { console.log('Handler 1'); console.log('Handler 2'); }); 

7. Using once: true for one-off events

If an event only needs to be handled once:

button.addEventListener('click', () => { console.log('Button clicked once!'); }, { once: true }); 

8. Handling events in Web Workers (for heavy tasks)

For resource-intensive computation, move the processing into a Web Worker:

const worker = new Worker('worker.js');
worker.postMessage({ type: 'heavyTask' });
worker.onmessage = (event) => { console.log('Result from worker:', event.data); }; 

Applying these approaches lets you minimise the load on the browser, improve interface responsiveness and make the application smoother and more pleasant to use.

Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Scripting client side JavaScript, jqvery, BackBone"

Terms: Scripting client side JavaScript, jqvery, BackBone