Callback functions and automatic passing of input parameters

Callback functions and automatic passing of input parameters

There are two ways a function can get called in Javascript:

  1. Calling a function by ourselves manually
  2. The Javascript engine calls the function for us automatically as part of event handling or processing an array.
🛑
Ignore the "processing an array" until we reach the "Arrays and Loops" module.

1) Calling a function by ourselves manually

We already know how this works.

We called the alert() function by ourselves manually:

alert("Hurray! 50% Off!");

We called the addTwoNumbers function by ourselves manually:

function addTwoNumbers(firstNumber, secondNumber){
  const result = firstNumber + secondNumber;
  console.log(result);
}

addTwoNumbers(5, 10); //Outputs 15

2) The Javascript engine calls the function for us automatically as part of event handling

We already know how this works, too.

For example, when a button is clicked, the Javascript engine calls the showModal function (event handler) automatically to reveal the modal:

function showModal(){
    let discountModal = document.querySelector("#surprise-discount-modal");
    discountModal.style.display = "block";
}

let showModalButton = document.querySelector(".show-modal-btn");

showModalButton.addEventListener("click", showModal);

Similarly, when the menu icon is clicked, the Javascript engine calls the anonymous function to reveal the off-canvas menu:

menuToggleButton.addEventListener("click", function(){
    document.body.classList.toggle("off-canvas-is-open");
});

In both cases, we do not call the event handler functions by ourselves. We can't do that.

The Javascript engine is responsible for waiting for events to occur and then calling the appropriate functions to perform the task.

If a Javascript engine calls a function for us automatically, we call that function a callback function.

As simple as that.

But why use the term "callback"?

At least once in your lifetime, you might have told someone, "I will call you back later!"

This means you will call them back at a later point in time, right?

The "callback" functions in Javascript work similarly.

Apart from exceptions related to processing arrays, a callback function is never executed immediately after the Javascript engine sees it.

function showModal(){
    let discountModal = document.querySelector("#surprise-discount-modal");
    discountModal.style.display = "block";
}

let showModalButton = document.querySelector(".show-modal-btn");

showModalButton.addEventListener("click", showModal);

For example, in the above snippet, the showModal function is not executed immediately.

The Javascript engine will call the showModal function at a later point in time when a user clicks the button.

Hence the term "callback function".

💡
We didn't learn about arrays yet. We will learn them in a future module to understand how the callback functions behave differently.
🫀
Callback functions are also the heart of asynchronous programming in Javascript. More on this later.

Anyway, now that you understand callback functions, a new question has popped into my head.

When we are calling a function manually by ourselves, we are capable of passing input parameters to them as arguments:

alert("Hurray! 50% Off!");

In the above code, while calling the alert(), we are passing a message as an argument.

function addTwoNumbers(firstNumber, secondNumber){
  const result = firstNumber + secondNumber;
  console.log(result);
}

addTwoNumbers(5, 10);

Similarly, in the above code, we are passing the values 5 and 10 when calling the addTwoNumbers function.

We have the control to pass inputs if the function we are calling supports them or needs them.

In a similar way, when a Javascript engine calls a function as part of event handling, is it capable of passing inputs to that function?

For example, the Javascript engine is calling our showModal function automatically when the button is clicked:

function showModal(){
    let discountModal = document.querySelector("#surprise-discount-modal");
    discountModal.style.display = "block";
}

let showModalButton = document.querySelector(".show-modal-btn");

showModalButton.addEventListener("click", showModal);

So, can the Javascript engine pass any inputs when it calls our showModal function?

The answer is yes.

In fact, every time an event occurs, the Javascript engine calls the associated event handler function by internally passing an event object as an argument to it.

showModal(event);

//This happens internally. We can't see this function call.

Be it a named event handler or an anonymous one, the Javascript engine calls our callback functions by passing them an event object.

We don't know this because accepting the event object as an input parameter is totally optional, and we ignored it because it was not useful during our previous exercises.

But if we are interested in them inside our callback functions, we just have to make the "event" parameter part of our callback function definition to make use of it as part of the event-handling process.

Here is an example of using the "event" parameter as part of our showModal function definition:

function showModal(event){
    let discountModal = document.querySelector("#surprise-discount-modal");
    discountModal.style.display = "block";
}

let showModalButton = document.querySelector(".show-modal-btn");

showModalButton.addEventListener("click", showModal);

Now, we can use the event parameter inside the function body like this:

function showModal(event){
    console.log(event);
    ...
}

let showModalButton = document.querySelector(".show-modal-btn");

showModalButton.addEventListener("click", showModal);

We can do the same with anonymous callback functions, too:

menuToggleButton.addEventListener("click", function(event){
    console.log(event);
    document.body.classList.toggle("off-canvas-is-open");
});

This way, when the Javascript engine calls our callback function and passes the event object as an argument to it, and we can capture it and use it inside our callback function's body.

The event object becomes useful while working on tasks such as:

  1. Disabling the right-click on a web page
  2. Image Gallery
  3. Overriding the default behavior of keyboard shorts
  4. The list goes on and on

This is because the event object contains a lot more information, such as:

  1. On which target HTML element is the event generated? We can use the target property on the event object to answer this question:
event.target;
  1. Where exactly has the user clicked? We can the clientX and clientY properties to answer this question:
event.clientX; //Gets the horizontal coordinates
event.clientY; //Gets the vertical coordinates

On top of that, the event object also has methods to change the behavior of the event that occurred.

For example, there is a method called preventDefault() on the event object that will be extremely helpful to us during the "Disable Right Click" project.

But before working on that project, we need to talk about something important: naming the input parameters, and we will do that in the next lesson.