on
Easing into Functional Programming in JavaScript
This article is intended to help you methodically incorporate Functional Programming (FP) techniques into your everyday JavaScript.
It will not try to convince you that FP is a good idea (if you want to be convinced, read anything Eric Elliott has ever written on the subject) nor will it detail FP concepts or how to implement them. For an introduction on the problems and solutions outlined here, watch Brian Lonsdorf's talk, of which this article is tightly based on. In fact, this article is basically an outline of his talk, but with some practical advice and dank memes sprinkled in. Let's get started!
🚨🚨🚨 Update: I finished a real-world project where I put these practices to use. Check it out and let me know what you think!
Level 1 — Eliminate Loops
The easiest way to get started with FP is by using functions the language already provides for you. Namely: map, filter, and reduce. Replace all for loops and mutating forEachs with their functional alternatives.
If you've been writing JavaScript for more than a few months then you probably haven't written a
forloop for a long, long time. Still, it's worth branching out from the nativeArraymethods to avoid re-writing a bunch of utility code in every project. Ramda is a great library when you need this extra horsepower. It's like a functional-by-design lodash.
Level 2 — Eliminate Useless Assignment
pipe or compose functions together to avoid unnecessary intermediate variable declarations. (Giving names to values is still a good idea, however.)
Level 3 — Eliminate null and undefined
null is a billion dollar mistake. It leads to all kinds of preventable runtime exceptions and breaks function contracts. And JavaScript has two of them (#sadlol)! Use the Maybe monad to codify the concept of nothingness.
Level 4 — Eliminate Exceptions
You have two options here. If you are using TypeScript or a static type analyzer such as Flow, I recommend #1. If not, go with #2.
- Return
Errors instead. Thefunctionin this case will have a union/variant return type e.g.Int | Error. - Use the
Eithermonad.
Level 5 — Eliminate Conditional Statements
The problem with conditionals in most languages is that they are statements, not expressions. This means you can't save the result of an if/switch statement to a value and you are left using temporary variables or wonky IIFEs instead.
Wait for the pattern matching proposal to hit stage 4? :D In the meantime, use the Either monad.
Level 6 — Eliminate Callbacks
Use Promises instead (or better yet, Futures).
You almost certainly already do this one.
Level 7 — Eliminate Side-Effects
Use the IO Monad.
It should be noted that FP isn't about merely eliminating things. It's about making your code more reasonable and composable. When you are given more powerful abstractions, you need fewer of them.