Callback Functions in JS ft. Event Listeners ๐Ÿ”ฅ

ยท

5 min read

In this blog, we are going to learn about CallBack Functions and event listeners.

Callback Functions :

As we know in javascript functions are First Class Citizen or also known as First Class Function and what that mean is that in javascript we can pass one function into
another function we can return functions from other functions now when you pass one function into another function then that passed function is known as the Callback function.

function x(callBack){
  console.log('Do Magic');
  // Calling the passed callBack function here
   callBack();
}
function callBack(){
  console.log('I am the call back function');
}
x();

In the above example, we have two functions x() and callBack() and we are passing the function callBack() into function x() now it's up to function x() when to execute it and all. Now let's see how these callback functions are useful and give us access to the asynchronous world of javascript even though javascript is a synchronous and single-threaded language. Let's understand it by example.

setTimeout(function () { // Think entire setTimout as line 1
 console.log('I will be called after 5 sec');
},5000)
function x(callBack){
  console.log('Do Magic');  // Line 3
  // Calling the passed callBack function here
   callBack();  // Line 4
}
function callBack(){
  console.log('I am the call back function');
}
x(callBack);  // Line 2

So as soon as we execute the above code javascript will see that we have setTimout and with a timer of 5000 ms so here javascript won't wait for 5000ms and wait for setTimeout to get executed rather it will take that function and register it some other place and will start the timer of 5000ms and then move onto the next line. Now at line 2, it seems that we have invoked the function x() and it executes the function x() and prints "Do Magic" but also see that we are passing one call back function into function x() and at line 4 we are executing it and this will print "I am the call back function". Here first function x() will be on the call stack and inside function x() we are calling function callBack()so javascript will create the execution context for callBack() function and after printing "I am the call back function" it will be popped out from call stack and then function x() also done will all the execution stuff so later it will be also moved out from call stack.

Suppose it took javascript 2000ms to run both functions now after 2000ms our call stack will be empty. So what happens with setTimeout() and this is the important part to learn here is that as soon as the timer finishes 5000ms the function inside setTimeout will be pushed into the call stack and it will print "I will be called after 5 sec" and then it will be moved out from the stack and this entire thing was possible because of callback functions. Now in javascript call stack is also known as the main thread and we heard many times that we should never block the main thread what we mean by that is we should never do any heavy operations which take 10-15 seconds to run the entire function and we should execute those asynchronous.

Do Magic
I am the call back function
I will be called after 5 sec // From setTimout function

Event Listeners: An event listener is a function or piece of code that waits for a specific event to occur and then responds to it. In web development, event listeners are commonly used to detect user actions such as clicks, key presses, or form submissions, and then trigger a specific function or set of functions in response. Let's understand it by example like how they are useful.

// Get the button element
const button = document.querySelector('#my-button');

// Add an event listener to the button
button.addEventListener('click', function seeMe() {
  // Execute some code when the button is clicked
  console.log('Button clicked!');
});

Here we have a click listener for the button and you see are passing one call-back function which is seeMe() this function will be only executed when we pressed the button so when you press the button function seeMe() will be executed and will push into call stack and as soon as it's done with execution it will be popped out so if you pressed button 5 times then call back function seeMe() will be pushed 5 times into call stack. And after setTimeout() Event listeners are the best example to showcase the importance of callback functions.

Let's see one important interview question where we have to increase the count whenever the button is pressed.

// Get the button element
const button = document.querySelector('#my-button');
let count = 0
// Add an event listener to the button
button.addEventListener('click', function seeMe() {
  // Execute some code when the button is clicked
  console.log('Button clicked!',++count);
});

Now one way to do it is we can simply to take the global variable count and whenever we press the button then just increase the count. But taking the global
variable is not good practice if have an idea of the data hiding concept. So apart from
this another way to do it with help of closure all we need to is just wrap the listeners with another function and inside that function take the variable count.

function beNice(){
let count = 0;
button.addEventListener('click', function seeMe() {
  // Execute some code when the button is clicked
  console.log('Button clicked!',++count);
});
}
beNice(); // Line 1

Now as soon as we run the program beNice() function will be executed and it will just register Listener and then it will be popped out from the call stack but javascript understands that variable count is not only used in beNice() function but function seeMe() also using it and that's why javascript won't remove count variable from memory and this way seeMe() function forms a closure and will have access of count even after beNice() function get removed from the call stack.

That's all about Callback Functions in JS ft. Event Listeners. And thanks to Akshay Saini for creating an incredible Namaste Javascript playlist this blog is just whatever learning I had from there.

ย