How Superman Can Teach You About JavaScript Events
Intro
Ok, so while this post will specifically use JavaScript’s Backbone library to facilitate the discussion of JavaScript events, the main goal is to help you understand more about events in general. In fact, I’ll discuss a generalized solution towards the end of this post which will hopefully take away some of the “magic” behind what Backbone is doing with events.
So at this point you might be wondering:
“What the heck is a JavaScript event?!”
JavaScript actually provides lots of examples of this via the browser environment. For example, clicking a button on a website triggers a “click” event behind the scenes for JavaScript. At its most basic level, an event is really just some sort of trigger that other parts of your code will listen for and then respond to.
Example
I know, I know — you want an example right? Well, you’re in luck — Superman to the rescue!
var LoisLane = {
name: "Lois",
occupation: "Reporter"
};var Superman = {
name: "Kal-El",
occupation: "Superhero",
saveLois: function () {
console.log("Don't worry, Lois! I got you!");
}
};/* The code below gives the Lois object extra properties in addition to name and occupation - specifically, the extend function enables the Lois object to "trigger" different events - say, the "I'm in danger" event! It also grants the Lois object with the ability to have other objects (like Superman) "listening" for her "I'm in danger" event. *//* Note: In order for the code below to work, you must have Backbone included in the file you're working with! */
_.extend( LoisLane, Backbone.Events );/* So what do I mean by Lois triggering an "I'm in danger" event? Well, let's give it a try! */
LoisLane.trigger( 'danger' );/* The Lois object now has the "trigger" property by virtue of extending Backbone.Events and she's triggering the "danger" event. But what do you think happens right now? Absolutely nothing! But more importantly why does nothing happen? Well, it's because Superman hasn't been set up to listen for her screams of danger! Let's set that up now! */LoisLane.on( 'danger', Superman.saveLois );
/* So what does this code do? In laymen's term, it's saying "On Lois triggering the 'danger' event, execute the Superman.saveLois function." You might be wondering whether the above line of code actually does anything right now. And if you tried it yourself, you'd realize that nothing happens yet either! But this is expected - all you did with the above line of code is do the prep work necessary for the Superman.saveLois function to get executed whenever Lois triggers the "danger" event. So let's go ahead and put Lois in a dangerous situation and have her trigger her "danger" event! */LoisLane.trigger( 'danger' );
/* If you're following along in your JavaScript file, you'll immediately notice how this time the trigger function produces a different result than last time. Specifically, you'll see the response: "Don't worry, Lois! I got you!". Go ahead and have Lois trigger the danger event a couple of more times - Superman will come to the rescue every time! */
Who Cares?!
At this point, you might be saying:
“Whoop-dee-doo, what’s the big deal about events? So what if Superman responds to Lois every time?”
If we can forget about the example for a second and think about JavaScript events at a higher level, isn’t it pretty cool that we just wrote some code that is essentially telling another part of our code to LISTEN for something to happen first, and then REACT to it? Think of it another way — we just wrote code to register some actions in advance (like Superman.saveLois) without executing it until some event happens later. And while it might seem cumbersome to set up this behavior in advance, once it’s been set up, we don’t have to worry about executing it ourselves — our program will always be listening for that event and then whenever a trigger happens, it’ll automatically run the actions we’ve set up! Pretty sweet! For those of you who want to dig further into this “paradigm”, take a look here.
Demystifying the Backbone “Magic”
Hopefully, I’ve been able to convince you about how cool JavaScript events are so far! But for some of you, you might be thinking that this is only cool because of Backbone — and while it’s true that Backbone is a pretty awesome library, we can totally replicate this Events functionality without Backbone! Let’s take a look at one possible implementation:
var addEventSystem = (function () {
var allEvents = {};
return function (target) {
target.on = function (event, callback, context) {
var boundFxn;
allEvents[event] = allEvents[event] || [];
context = context || null;
boundFxn = callback.bind(context);
allEvents[event].push(boundFxn);
};
target.trigger = function (event) {
var args = Array.prototype.slice.call(arguments, 1);
var specificEvent = allEvents[event];
for (var i = 0; i < specificEvent.length; i += 1) {
specificEvent[i].apply(null, args);
}
};
};
})();var LoisLane = {
name: “Lois”,
occupation: “Reporter”
};var Superman = {
name: “Kal-El”,
occupation: “Superhero”,
saveLois: function () {
console.log(“Don’t worry! “ + this.name + “ is going to save you!”);
}
};/* Custom JavaScript that mimics calling _.extend( LoisLane, Backbone.Events ) */
addEventSystem(LoisLane);/* Similar to before where we are setting up the LoisLane object to have a function Superman.saveLois get called when the LoisLane object triggers a "danger" event */
LoisLane.on("danger", Superman.saveLois, Superman);LoisLane.trigger("danger"); /* We get the following: "Don't worry! Kal-El is going to save you!" */
While I won’t go into details of the “addEventSystems” function I wrote above, I hope it’s clear that the function is simply pure JavaScript and there’s no “magic” in it (well, unless you consider writing JavaScript magical!)
Thanks for reading and keep on JavaScriptin’ !
My name is Willson Mock and I’m a software engineer at Palantir working on building awesome products for our clients. I’m also passionate about web technology and enjoy teaching JavaScript!