Learn Hard the Code Way: Functional Programming
Jenn Schiffer
1072

Jenn kindly asked me to nitpick this piece from a year ago. As nice as it is to feel wanted, I’m not going to. Rather, I’m going to share some real-world functional JavaScript.

Everything that I’m going to show you is real, shipping code. In fact, if you’ve ever written anything in JavaScript, you’ve probably shipped some of it!

For my first example, here’s part of the popular jQuery library. I’ve reformatted it for readability, but otherwise this is the actual code. Here’s the “add” method for a callback object:

( function add( args ) {
jQuery.each( args, function( _, arg ) {
if ( jQuery.isFunction( arg ) ) {
if ( !options.unique || !self.has( arg ) ) {
list.push( arg );
}
} else if ( arg && arg.length
&& jQuery.type( arg ) !== “string” ) {
// Inspect recursively
add( arg );
}
} );
} )( arguments );

Now I know what you’re thinking. jQuery is a general-purpose library, and all that type introspection stuff is only relevant if you’re writing that sort of thing. So this looks more complex than it really is.

No, dear reader, that is not the part I wanted you to look at. It’s the first and last lines. Let’s see that again with the detail omitted:

( function add( args ) {
// Do something with args
} )( arguments );

This code creates a function, and then calls it straight away! Functional programming!

Silly imperative programmers are probably wondering why you couldn’t just write this:

// Do something with arguments

Or this, if brevity is important:

var args = arguments;
// Do something with args

But, of course, this code wouldn’t work if you did it that way.

“All right, wise guy”, I hear you say. “The arguments thing is low-level magic that nobody writing normal code has to deal with.”

All right, fair enough. So let me show you, instead, the “all” method from the ES6 extensions to JavaScript promises. I’ve elided the body of the “res” function for brevity, but you can see for yourself that there’s no magic “arguments” or anything in there:

Promise.all = function (arr) {
var args = Array.prototype.slice.call(arr);
return new Promise(function (resolve, reject) {
if (args.length === 0) return resolve([]);
var remaining = args.length;
function res(i, val) {
// Do stuff with i and val
}
for (var i = 0; i < args.length; i++) {
res(i, args[i]);
}
});
};

The clever programmer made a function, called “res”, which only has one call site. Functional programming!

Inferior imperative-thinking programmers might wonder why we couldn’t just write this:

for (var i = 0; i < args.length; i++) {
var val = args[i];
// Do stuff with i and val
}

But, of course, we know better. Once again, this code wouldn’t work if you did it that way.

And that, ladies and gentlemen, is why JavaScript is such a simple language.

On a personal note…

I once spent two whole days trying to track down a bug in some real JavaScript code that I wrote when I was just starting in node.js. The fix was to transform code which looked something like this:

for (var v in some_array) {
// Do something with v
}

Into this:

for (var v in some_array) {
(function(value) {
// Do something with value
})(v);
}

I learned a lot about JavaScript in those two days.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.