Now in previous lessons, we saw how JavaScript allows us to create Higher Order Functions.
When we talk about Higher Order Functions, we're referring to the function that's able to take functions
as inputs.
So in this case the addEventListener is a Higher-order function, as it takes the respondToKey function
as an input.
Now what about the other side? What about the function that gets passed in as an input?
Well this is actually called a Callback function because it allows us to wait for something to finish
happening,
for example waiting for a click event, and then the callback function gets called back and executed.
So previously, when our button detects a click it calls the callback function,
and in this case, when the document or the entire web page detects a keypress then the document will
call this function respondToKey.
Now when that happens, we can get it to send us some information that it'll only know once the event
happens, namely say which button was clicked, or which keyboard key was pressed.
So if we head into our Wikipedia page again, and we inspect on our JavaScript object, and we again gain
access to the h1 using the $0 sign.
Now we know that we can add an event listener by simply saying $0.addEventListener say, "click".
And once that does happen let's call this anonymous function and we can console.log() something.
Now in this case all that we're doing is saying that attach this event listener to $0, which of course
is this h1,
and get it to listen for click events.
When it detects those click events get it to call this function.
Now, this is a very simple form of the event listener,
but as we saw in the last lesson, we can also get the event that triggered this function,
passed back through the callback function.
So instead of console logging simply "I got clicked",
we can actually console.log() the actual event that triggered the function.
So in this case, if I hit Enter and I click on this JavaScript, h1, then you can see that it's console
logging the event that triggered the click.
So in this case, it was a mouse click and you can see all of these properties that are associated with
that mouse event, for example, which part of the screen did I click on, what was the type of the event, and a
whole bunch of other things.
Now when you're creating this anonymous function, you can call this parameter anything you want.
You'll commonly see it as e or evt for event.
It'll work exactly the same.
Now the reason for this is because, say if we create a function called sayHi, and we give the name of
the input as "to", and then we say console.log "Hello" plus whatever input we got.
So now we can call this function saying, sayHi to Tom, and it'll say "Hello, Tom".
Now we can also create a function sayHi, and, instead of calling our input "to", we call it "name".
So now we're saying hi to "name",
and again it does exactly the same thing which says, "Hello..." to the input that we pass in which is name.
So now we can again say sayHi("Tom"), and it'll still say "Hello, Tom".
So the name that you give the input really doesn't matter.
It's the same as when you create a variable called "name", or you create a variable called "to",
it's completely up to you what you call it.
So this is why when we create an event listener and we give that input any name, say e, it will still
work exactly the same, passing in the event that triggered the callback function.
But the slightly crazy part is that this callback function is not called by us, but it's called by the
object that experienced the click.
And when that happens, we can get it to send us some information that it'll only know once the event
happens.
For example, in our drumkit then that's which button got clicked by the user.
So this callback function can be a little bit confusing and a little bit mysterious.
So again, as before, I want to show you both sides of the coin.
So let's pretend to create the function addEventListener, but so that it's not confusing we'll call
it anotherAddEventListener.
And as we know it takes two inputs, the first being the type of event and the second being the callback.
So this addEventListener will do a number of complex things that detects when an event happens, but when
an event does happen, then it'll create an event object, and let's call that object eventThatHappened,
just so that we're clear.
So let's say that we pressed a key on the keyboard, then the event object that gets created will capture
a number of things about that event,
for example what was the event type.
In this case, it was a keypress event. And it might have another property such as, well, which key then.
Let's say that we pressed the p key to generate this event.
And it might have other things like duration of keypress, and let's say this was equal to two seconds.
So when the event happens, namely pressing a key on the keyboard, then this object gets created based
on that event.
And now we can pass that object back through the callback method so that the programmer, if they wish, they
can get the event object and use it to see what event triggered this event listener.
But of course we know that our callback doesn't get called for all types of events,
right?
So in fact our addEventListener might check to see if eventThatHappened.eventType is actually
equal to the type of event that the programmer was looking to detect,
and then, and only then, do we actually trigger the callback function.
So if this is our function, addEventListener, and this is the part that we can't really see, then the
part that we do see and the part that we write is actually just calling the addEventListener, and we
pass in a number of inputs, right?
Say we pass in that we're looking to detect the keypress event, and when that happens we want it to
trigger an anonymous function that essentially just does some console logging.
So console.log()...
And what we want to log is the event that triggered the callback.
So now if I hit Enter then you can see that when the event gets triggered by say a key press on the
keyboard,
and if the type of event was equal to the type that we were looking for, namely keypress, then we trigger
the callback. And the callback can send us that event object which now gets logged in our console.
So you can see this output looks really similar.
Say if we were simply using proper code, not our simplified code, and we said document.addEventListener
to listen for keypress and once you do detect that keypress then call the anonymous function passing
in the event that triggered the keypress, and then we're simply just going to console.log that event object.
So now when I hit Enter and I press any key on the keyboard then you can see we get back this object
called KeyboardEvent, and it has a number of properties including things like, for example, the key that
was pressed to trigger this event.
So again, I find that it usually helps to understand what exactly is going on here by using the debugger
and stepping through each step of the way.
So let's try this again but this time we're going to use the debugger to see what's happening.
So again, I'm going to call anotherAddEventListener, passing in the type of event that we're looking
to detect,
and also the callback that should happen when it does get detected.
But just above, I'm also going to add the debugger keyword so that when I hit Enter I enter the debug
mode.
So now I'm going to step through our function calls, and we begin by calling anotherAddEventListener,
passing in these two inputs.
So that takes us to where that function was declared and we step through each of the lines of code.
The first thing that happens is we're waiting to detect an event.
And this part of the code waits to detect an event.
Let's say that in this imaginary world, I press the p key on the keyboard.
Now at that point then this eventThatHappened object gets created and it captures a lot of the information
about my keypress,
namely that the event type was of the key press type, the key that I pressed was p, and I pressed on it
for two seconds.
So now that we have this event object created after I triggered the event then our code will check if
the type of the event that happened is equal to the type that the program was looking for then it will
go ahead and trigger the callback function.
And if we step through then you can see that the callback function is of course this part, the function
that we used as an input.
And it goes ahead and tries to log the event object.
And this is when we see that event show up down here.
And that is how we came about getting hold of this event object.
Now callbacks are notoriously difficult concept to grasp, and even some developers who've been working
for a number of years struggle with this particular concept.
So don't worry if this is the first time you've come across it and it seems a little bit confusing. What
I encourage you to do is to recreate our addEventLlistener function and just go through the motions of
what I did in this lesson without having to watch the video. Play around with the code and also play
around with the debugger and see how the code works behind the scenes.
Now, we're going to come back to this topic of callbacks many many more times in the coming lessons,
so this is not the only time that you'll come across it.
And for all the difficult concepts I try to sprinkle in plenty of repetition so that I make sure that
you really, really do get it because it is a really important concept that we'll come to rely on when
we're creating more and more complex web apps.