JavaScript: Declarative Magic

Feather
8 min readJan 4, 2018

You may have heard about the difference between declarative and imperative code. Yet you are still unclear. By the end of this article you will be declaring yourself an expert!

Declarative code tells the what. Imperative tells the how. Imperative code is more verbose. Anthropomorphized, Auntie Clara is a southern lady who declares things. She exclaims “these biscuits are ever so fluffy!” Auntie Pear used to be a school teacher. Rather than state a fact, she gives instructions. Detailed instructions. After a while your eyes start to cross. Any similarity to your relatives is purely coincidental.

You may have opened up your car’s hood to dig around in the internals once or twice. Still, you may operate a car without knowing how a car works internally. You can also write Ruby code for years without knowing a thing about the C code that lies underneath.

As in many things, there is a spectrum. Declarative code, on one end, tends to be more concise and high-level. Imperative code is often speedier to execute, yet more verbose.

What is the best way? As in most things, there are tradeoffs. If you are optimizing readability, declarative code is your friend. In some cases imperative is better. Usually more low-level code, optimized for fast execution, is more imperative. Generally, the closer you get to the metal, the less you can rely on high-level code. You might spend more time thinking about garbage collection than readability.

You have so many options with JavaScript, which is a beautiful/terrible thing. You can write code that looks a bit like circa 90’s Java. Verbose code rife with for-loops and semi-colons abounds. But, of course, there’s that word prototype everywhere, and no strong types. Single-line factory methods are a more current style. Functions don’t even have to say “function” anymore. Fat arrows and implicit return for single line functions are ES6 features. You can also avoid for-loops by using many of the built-in array methods.

I often go spelunking in Github to see what major libraries are doing with JavaScript. Many of the libraries I use have imperative code in them. Still, if I see a lot of imperative code in a PR I’m reviewing I generally will ask if there might be a cleaner way. As a frontend developer, it is most often the case that we want readability above all else.

And now, without further ado, the canonical example! We replace for loops with nifty JavaScript Array methods reduce(), map() and filter().

The imperative way to sum elements in an Array

Notice our declarative example uses ES6 fat arrow syntax and reduce(). The reduce() function takes a collection and a function as an argument. The function as argument is a pretty common theme when it comes to iterating in a functional way. It’s a succinct way of saying “take each element and do this thing to it”. It’s also called a closure, as the inner function is closing over the variables in the outer function.

This inner function accepts two arguments. These are the current element and the accumulator, (a and b here). Every time you want to take a lot of things and make them into one thing, this is a clean way to do it. You can also pass in the starting point of your reducer. It defaults to 0 so if you pass in nothing, your initial element will be 0. This means you intend to reduce to an integer. But you can also reduce to an Array by passing in an empty Array.

A declarative approach. No return required for a single line function!

Both ways of writing the sumItUp() function give the same results. The 2nd one uses reduce() to reduce the lines of code needed. Underneath reduce() you will likely see a for-loop. Iterating through an Array to produce a single value is a common problem. A smart engineer said “we should make this reusable, then never have to write it again!”

The reduction of a single function to one line of code may not seem like a big deal. Over many lines of code, it will make a big impact. Concise code leaves you more juice to solve the interesting problems. There is a line, though, between elegant and clever. Trying to squeeze everything onto one line is not always going to make it more readable or efficient.

Let’s look at another example. How about flattening an Array?

Flattening an Array with a for loop.

You can reduce that to one line too! Note the empty Array being passed in, so reduce knows what it’s base value is.

Passing in an empty Array as the starting value for the reduce() accumulator

For a multi-dimensional Array, you would still need to flatten it recursively.

Flattening a nested Array with reduce()

Here I’d like to take a small detour. A recursive solution can be elegant. It can also be less efficient. As your input grows in size each recursive pass is gobbling up memory like a hungry ghost. The V8 engine puts limits on memory allocated to each process. With recursion you run the risk of creating the dreaded stack frame exception. More on this another time!

Anyway, we were discussing reduce(), filter() and map().

We’ve talked about reduce(), so let’s now have a look at filter(). You have been giving a simple task. Given a pile of Magicians, select only those who belong to House Hufflepuff.

Using a for loop to filter out all other houses

Or you could use filter() for a one-line solution.

Using filter(), easier than Wingardium Leviosa!

Now let’s discuss map(). This turns out to be a useful abstraction when writing a UI in React. Map() takes each element in a collection and maps it to another value via the inner function.

Map() for doubling each element in an Array

We can also map() some excitement onto our wizards houses.

We are so excited!!!

You can also use map() to pluck items from a larger dataset. Often REST APIs return a comprehensive set of data, but you only need two items. You can map out only the values needed.

Note that map() creates a new Array. This preserves data integrity as it preserves the original Array. Often the trickiest parts of single page apps center around managing state. Data integrity wins.

With streaming data you need both data integrity and efficient memory use. Creating a new Array each time data updates may cause you to run out of memory.

A very common use case of map() in React is attaching JSX to inputs in a template.

We can assign each house a color by mapping a CSS class to it’s element based on house name.

The wizards divs, placed with CSS grids, will resize to fit any container. Check the source on Github to further enjoy the magic.

With map() you need very little code to make a dynamic grid. Here we are using a fixture, or flat file, to mock our data. This basic pattern will work if your data comes from a remote source, too. Remember that you can also use map() to select items out of a large dataset coming from a remote API.

Imagine doing this with JQuery! There would be much selecting and appending. You would have to specify where things got attached, then generate DOM elements with String concatenation. Plus, Bootstrap or many lines of CSS would be necessary to get a responsive grid. So any change in your styles would cause a huge rewrite.

The horrors of old time string concatenation before we got template strings in ES6.

What if you want to add some interactivity to this wizard grid? Let’s add a simple click handler to each div so that something, anything, happens when you click on it. For now we are not too concerned with what happens. Let’s make it a wizard selector. This is an egalitarian wizard society so they take turns being the chosen one. No one should have to carry that burden by themselves!

The event handler
Dynamically adding a class to signify which name was selected

This wizard selector element is a perfect candidate for a stateless functional component. This encapsulates the display logic for that one part of the page into a separate static piece of reusable code. Reuse and simplification are at the heart of declarative code.

Our new component is a function. State management is being handled elsewhere so a component would be overkill. Updated state is as an argument.

We declare our function with a const. Is it immutable, then? In truth, no. We know that with the same inputs, it will return the same output, since we are never modifying state there. When we are hunting for state issues later, we have a narrower area of jungle in our codebase.

Our stateless functional component

Now we can select any wizard to be the new chosen one. We can also add a selected class to their square to visually set them apart. Poof! Map() makes wizard selecting fun again.

What if we want to search the wizards? Earlier we wrote a function to filter out only wizards from Hufflepuff. We can adapt it for a rudimentary search. This is not something I would recommend in a production app!

At the moment we can only search by house. We then add basic feedback for users to tell them there are no results to our map() function. Each time there are no results we need to reset the state to the full set of wizards.

Now we have two event handlers and searchWizards() that handles the form submission.
Our render method with the search form.
Use of a simple ternary operator to either show a set of wizards or show no results.

With my magic ear horn I can hear you thinking, gentle reader. You are correct, this search form should be a separate component. Since you thought it I’ll leave that as an exercise for you.

Well that’s all for today. I hope this was helpful. Feel free to reach out with comments & questions.

--

--

Feather

Thoughts on code, climbing, and DIY. JavaScript, Elixir, and other fun stuff.