Earlier quoted context omitted.
I vastly prefer functional programming to OOP. But I find my use of `class` in JS increasing for two reasons orthogonal to the paradigm distinction: 1. Particularly in pure JS projects which either haven’t yet or won’t migrate to TypeScript, classes are an excellent way to define data types . They needn’t be stateful, they can be used just like POJOs in otherwise pure functional code. But their shape is clear (or can…
Immutability in JS is painful and tedious, how can you enjoy write functional code in JS?
- Constructing flat POJO values is trivial (spread + define any changed properties).
- Immutable array operations are fairly robust, albeit not as expressive as some may want. Getting comfortable with reduce improves this dramatically.
- Map/Set constructors accept instances to create new values.
- Class instances used as value types are simple to derive, assuming their constructors accept objects in their shape. If they have a consistent shape, deeply nested clones with consistent descendant classes are equally trivial.
- Iterators could play nicer with other native interfaces, but they’re pretty handy even so. Custom iterators are exceedingly handy for shuttling data between types.
- More expressive operations over sequence-like structures is as simple as operating on iterators. This will feel more reasonable if you favor Map over POJO for mapped types.
- Imperative stateful functions are admittedly a pain, but wrapping them in functions which return meaningful state you’ll need later is pretty straightforward.
- Really though, starting from a functional perspective just makes these details a non-issue. If your primary tool is a pure function, any gap in these interfaces can be filled by writing a function and calling it rather than the imperative code.
If some or all of that sounds like it’s a performance nightmare… most of the time it isn’t. But if you have a hot loop where copy on write is a meaningful bottleneck:
- You can take inspiration from Clojure or other functional languages with persistent data structures. There are a ton of libraries.
- You can take inspiration from Clojure or other functional languages with a concept like transients, and isolate your mutable code in a function body. This doesn’t even need a library, it’s just bailing to the imperative code the language ostensibly wants you to write in the first place, and being thoughtful about how it’s encapsulated.
What I do find painful and tedious is trying to follow stateful imperative code which hasn’t been subjected to intense discipline. This is true regardless of the language. It’s true whether the code is “object oriented” or not.