JavaScript

ES2021 features we're actually using in production

JS

Every year brings a handful of small JavaScript additions that don't make headlines but end up saving real keystrokes. ES2021 was a quiet release, no headline feature on the level of async/await or optional chaining, but a few of its additions have already worked their way into our day-to-day code and even into our internal style guide.

Logical assignment operators, `||=`, `&&=`, and `??=`, cut down a surprising amount of boilerplate in our config-merging and default-value code. Where we used to write `config.timeout = config.timeout || 5000`, we now write `config.timeout ||= 5000`, and the nullish variant `??=` has been especially useful for distinguishing an intentionally falsy value like `0` or `false` from one that's genuinely missing, which the plain `||=` form gets wrong. It's a small syntactic change, but it reads closer to intent than the equivalent ternary or if-statement did.

`String.prototype.replaceAll` finally removes the need to reach for a regular expression with a global flag just to replace every occurrence of a substring. It's a minor addition on paper, but it eliminates a class of subtle bugs we'd see occasionally, where someone would forget the `/g` flag on a regex-based replace and only catch it in code review, or worse, in production when only the first match got replaced. Numeric separators, the ability to write `1_000_000` instead of `1000000`, are a small quality-of-life win for anyone reading large constants in financial or scientific code, and we've adopted them as a lint rule for any literal over five digits.

We also looked at `Promise.any`, which resolves as soon as the first of several promises succeeds rather than waiting for all of them or failing on the first rejection. It's useful for racing multiple redundant data sources, for example querying two CDN edge nodes and taking whichever responds first, but we've been more cautious about adopting it broadly, since it needs a polyfill on the older Safari versions a couple of our client projects still have to support. Rolling it out selectively, only in code paths where we control the runtime environment, has kept it from becoming a support headache.

None of these features individually justify writing a blog post, but taken together they're a reminder that not every meaningful improvement to a language shows up as a framework or a paradigm shift. Sometimes it's just fewer characters and fewer places for a small mistake to hide, and this year's crop of additions has quietly earned a permanent spot in our style guide.

← Back to the journal

Have a project in mind?
Let’s talk.

Tell us where you are and where you want to go. We'll map the fastest route between the two.

Currently accepting new clients