Anonymous functions, the art of the callback. I’m going to propose that you never write a callback again using an anonymous function, and I’ll sell you the idea now.

Firstly, what is an anonymous function? Something like this:

Table of contents Passing parameters

document . querySelector ( ' .menu ' ). addEventListener ( ' click ' , function ( event ) { // we're inside the anon callback, btw... if ( ! this . classList . contains ( ' active ' )) { this . classList . add ( ' active ' ); } event . preventDefault (); }, false );

Here’s a few reasons why you should stop doing this… anonymous functions:

Are more difficult to debug

Cannot be reused

Cannot be tested easily

Do not describe the role of the function

Make code lack structure

Create messier/unclear code

Documentation will suffer (things like jsDoc)

Let’s investigate. Based on our above code example, I can see a click event was bound and it executes a function which adds a class . But what for? So far (apart from an educated guess), I can only assume that it toggles a tab or a menu. So why are we so reliant on using anonymous functions instead of helping ourselves write better code?

“But what does this code do?”. At this point, you remove your headphones, peer over to your colleague who wrote the code and ask him what the hell it adds a class to. He then gets agitated because you’ve stopped his code flow and he’s paused his Beyonce remix only to tell you the answer. This could have all been avoided if he’d written some more classy code:

function toggleMenu ( event ) { if ( ! this . classList . contains ( ' active ' )) { this . classList . add ( ' active ' ); } event . preventDefault (); } document . querySelector ( ' .menu ' ). addEventListener ( ' click ' , toggleMenu , false );

Now, doesn’t that look better? And hey, if we introduce another element, we can bind the same function again without causing grief:

document . querySelector ( ' .menu ' ). addEventListener ( ' click ' , toggleMenu , false ); document . querySelector ( ' .myclass2 ' ). addEventListener ( ' click ' , toggleMenu , false );

This also prevents those lazier developers to copy the entire contents of the anonymous functions and pasting it again, only to avoid moving it into a function and refactoring it for reuse.

⚡️ FREE eBook: 🔥 ForEach, Map, Filter, Reduce, Some, Every, Find “This book is straight to the point, syntax exploration, comprehensive guide, real-world examples, tips and tricks - it covers all you need Todd Motto, author of Exploring JavaScript Array Methods

Abstraction.

A beautiful word. Let’s use it more and abstract our code into more reusable components and parts, to make our lives much easier. How about at this stage we also abstract our selector?

var menu = document . querySelector ( ' .menu ' ); function toggleMenu ( event ) { if ( ! this . classList . contains ( ' active ' )) { this . classList . add ( ' active ' ); } event . preventDefault (); } menu . addEventListener ( ' click ' , toggleMenu , false ); // oozing with awesomeness

I really encourage this setup, because we’re abstracting into three different sections, the selector , event and method . I say death to the one-liner of jQuery-chaining rubbish that’s littering the web - just because you can doesn’t mean you should. Chaining methods creates more complex and often lesser quality code. Chaining sidesteps a problem of abstracting your methods into reusable parts and littering functions with them.

So let’s revisit our above code, and highlight the selector , event and method :

// selector var menu = document . querySelector ( ' .menu ' ); // method function toggleMenu ( event ) { if ( ! this . classList . contains ( ' active ' )) { this . classList . add ( ' active ' ); } event . preventDefault (); } // event menu . addEventListener ( ' click ' , toggleMenu , false );

This opens up many benefits. Let’s say that menu also took an onchange event, we could simply extend what we’ve written so easily:

// selector var menu = document . querySelector ( ' .menu ' ); // method function toggleMenu ( event ) { if ( ! this . classList . contains ( ' active ' )) { this . classList . add ( ' active ' ); } event . preventDefault (); } // events menu . addEventListener ( ' click ' , toggleMenu , false ); menu . addEventListener ( ' onchange ' , toggleMenu , false );

Based on this setup, you’ve probably guessed how I (on a very basic level) structure my JavaScript files that manipulate the DOM. Here’s what a typical file might look like (with production ready in mind):

// keep things outside the global scope plz ( function ( window , document , undefined ) { ' use strict ' ; /** * Selectors */ var menu = document . querySelector ( ' .menu ' ); var users = document . querySelectorAll ( ' .user ' ); var signout = document . querySelector ( ' .signout ' ); /** * Methods */ function toggleMenu ( event ) { if ( ! this . classList . contains ( ' active ' )) { this . classList . add ( ' active ' ); } event . preventDefault (); } function showUsers ( users ) { for ( var i = 0 ; i < users . length ; i ++ ) { var self = users [ i ]; self . classList . add ( ' visible ' ); } } function signout ( users ) { var xhr = new XMLHttpRequest (); // TODO: finish signout } /** * Events/APIs/init */ menu . addEventListener ( ' click ' , toggleMenu , false ); signout . addEventListener ( ' click ' , signout , false ); showUsers ( users ); })( window , document );

This also has many other benefits, including caching your selectors, your team knowing the exact format in which you’re writing your code, and not littering the file with random scripts here, there, everywhere, and making future changes incredibly easy.

You’ll also notice I wrap all my code inside an IIFE, (function () {...})(); , this keeps all your code outside of the global scope and helps reduce more headaches.

Passing parameters

You may have noticed that I haven’t passed in any parameters to any of the above code examples, this is because the way addEventListener was added to JavaScript was nearly done well, but missed a vital piece of functionality, so we need to look closer and understand what’s happening. You might think you can do this:

element . addEventListener ( ' click ' , toggleMenu ( param1 , param2 ), false );

…But this will invoke the function as soon as the JavaScript engine hits the function, which is bad news. So what we can do is use the ECMAScript 5 addition Function.prototype.bind (modern browsers only) which sets up the values without invoking the function. This is similar to .call() and .apply() but doesn’t invoke the function:

element . addEventListener ( ' click ' , toggleMenu . bind ( null , param1 , param2 ), false );

You can read more about .bind() here and here. You can grab the .bind() polyfill here so that all browsers can use .bind() (as it’s current IE9+ and all modern browsers).

If you don’t want to polyfill and go “oldschool” then you’ll need to wrap it inside a function:

element . addEventListener ( ' click ' , function () { toggleMenu ( param1 , param2 ); }, false );