DEV Community

loading...

Early Returns in JavaScript

Jennifer Lyn Parsons
paladin. writer. gen-x. comic geek. tea snob. vegetarian. au‍tistic. | lunastationquarterly.com | selfcare.tech
・4 min read

A couple of articles related to how early returns work crossed my path recently, enough to pique my curiosity. Learning about early returns in JS has been not only a challenging technical exploration, but also pretty fun. In researching the concept, I remembered how much I enjoy learning something for it's own sake, not just as a means to an end. Sure, the information I gathered is useful and the technique is something I'll likely employ in the long run, but it was just as valuable enjoying following the trail of breadcrumbs that led to my final conclusion.

What is an early return?

In short, an early return provides functionality so the result of a conditional statement can be returned as soon as a result is available, rather than wait until the rest of the function is run.

Surprisingly, I hadn't seen this kind of pattern in JS before, though I'm used to seeing it in Ruby, where it's quite common. I was curious as to why that was. A bit of research showed me that returning only after the rest of the code had run, whether it was needed or not, was a holdover from older imperative programming languages where it was required to return at the end of a function to ensure the code ran in the correct order.

The only answer I could really find to why I hadn't run into this pattern before is that even now this is not taught nor talked about enough for folks to start using it regularly, dropping the imperative style. A few newer devs have started the conversation and argue quite strongly that it's clearer to read.

I still had questions

I was unsure about the readability of this style. I'm so used to reading if/else statements with a variable set at the top of the function that gets returned at the end. Having multiple returns or even multiple if statements (rather than if/else) felt like it would be more challenging to understand at a glance.

More important than readability, I wondered how performant it was versus the single point/end of function returns. My gut told me it was probably faster because, in theory, less code was being run. In researching this, I found a pre-2012 article hinting it might actually be less performant but didn't find any information after that supporting one style or the other.

It would be interesting to discover that a single return was faster and if it was, why that was so. I decided to run some benchmarks to see what our winner was.

Benchmarking early returns

Here are my benchmark tests: JavaScript benchmark playground

As you can see when you run the tests, there are only 10s of milliseconds difference in speed between the various options, fairly negligible. While I get slightly different results each time I run the benchmarks, with the old imperitive style comes out on top every time. Not what I was expecting! Generally, it looks like "early return within an if/else" comes in second to "early returns with single statements", though it's pretty much a wash between them.

Conclusion

In comparing these examples, I find I prefer a single if/else for readability, regardless of whether it's an early return or single return. While early returns feels less cumbersome than setting up a variable just to have a return value as in single return, knowing that there's a performance hit as well means I'll be likely sticking with the old style. Additionally, having a series of statements inside a function as in the "early returns with single statements" version abstracts the fact that they're consequentially connected to each other and to me, that's less readable.

All in all I feel like I've gained a deeper grasp on some of JavaScript's inner workings, with the bonus of trying out some benchmarking and learning a bit of programming history as well.

Resources

Discussion (6)

Collapse
nvdweem profile image
Niels van de Weem

When I run your benchmark it shows that the single exit point is twice as slow as the other two options. It isn't accurate though, the single exit point is assigning a global variable (window.value) which the other examples don't. In effect it has a side effect that the others don't have and I'm guessing it means that it's optimized less because of it.
Might be browser dependant though since you describe not having that difference (I'm running Chrome).

Changing "value=''" to "var value" or "var value=''" (or even "let value=''") to remove the global assignment makes all 3 testcases perform roughly the same.

I'm still a fan of early returns though even though there are cases where it's less readable indeed.

Collapse
martinspire profile image
Martin Spierings

Agreed. I've updated it and its about the same:
jsbench.github.io/#d95ae3db82974a3...

I also get different results on different devices. My own CPU does 2 billion on each and 1+3 are green. On my workstation 2+3 (with 0.8 billion) and on my phone its just the first (and 1.2 billion)

Collapse
alainvanhout profile image
Alain Van Hout • Edited

Using early returns can be beneficial or problematic depending on the way that it's used.

Problematic usage typically relates to having return statements in several places across a bundle of loops and conditionals. This makes it very hard to (easily) grasp the flow of the code.

The most beneficial usage that I know of, is checking of things at the very beginning of the method. For example, if you have to combine several sources of data but have to return a certain default value if a specific and easily/efficiently identified condition is met, than it makes sense to add an early return. This is particularly true for validation:

function doThings(input) {
  if (input === null) {
    return null;
  }

  // do the actual things that expect input to not be null
}

(note that this isn't meant as a guideline on null-handling. It's just an easy example)

Collapse
1hko profile image
1hko • Edited

The benefit of "early return" or short-circuit evaluation is that you can skip the evaluation of an entire statement or expression. The skipped portion is performance gain.

Your benchmark isn't setup to show this though and a general comparison is not really possible. To see the benefit of this, you need to look at algorithms that have expensive computations where short-circuit evaluation can save a noticeable amount of space/time.

Imagine a path-finding algorithm, a chess AI, or other kind of solver where millions of computations are being made. In many cases, short-circuit evaluation can be leveraged to trim many possibilities or duplicates in the solution space. Simple algorithms can benefit too, like every and some. A simple if/else if/else doesn't allow one to form any meaningful opinion about the topic.

Collapse
kepta profile image
Kushan Joshi

Great write Jennifer, first step for improving code readability “How can I make this function return early 💃”

Collapse
vshyrokov profile image
Viktor Shyrokov

I think it's pretty useful, because you don't have to go through every condition and in the end send the same result. Who knows what other problems could be there(unit tests, helps to overcome it).