tldr;

Return as soon as you know your method cannot do any more meaningful work

Reduce indentation by using if/return instead of a top-level if/else

instead of a top-level Try keep the “meat” of your method at the lowest indentation level.

Error handling is noise.

Programmers are often taught to have a ‘single exit point’ in their methods, i.e. only return from a single location.

function () { var result; if () { result = x } else { if () { result = y } else { result = z } } return result // this return is single and lonely }

This is a poor guideline in my opinion:

“assign a result” doesn’t explain the intent: “this is the final value, processing stops here”

Leaves question open “is the result object finished? can it be modified? by whom?”

Allows accidental modification of the result

Encourages “happy path” to be wrapped in one or more if/else statements

Example if/else refactoring

Consider this typical node callback code:

function(err, results) { if (!err) { doOtherStuff() doMoreStuff() // ... etc // ... etc } else { handleError(err) } }

There’s a few problems here. First, our error handling is dangling off the end of the method. If the “happy path” is many lines long, it can easily become unclear what the else even refers to.

Let’s try keep the “meat” of the code at the bottom of the method, and keep any special cases together at the top:

function(err, results) { if (err) { handleError(err) } else { doOtherStuff() doMoreStuff() // ... etc // ... etc } }

It’s very easy to get unweildy levels of indentation in JavaScript, so we should strive to reduce any unnecessary nesting.

In this case, we can remove the else indentation around our “happy path” by replacing the else with a return:

function(err, results) { if (err) { handleError(err) return } doOtherStuff() doMoreStuff() // ... etc // ... etc }

Not only does this unindent a bunch of code, it also moves the method’s main purpose/intention/meat to indentation level 0.

We often don’t care about return values in non-promise-based async JS, so we can futher compact the method vertically by putting the return first, removing a whole line and more braces:

function(err, results) { if (err) return handleError(err) doOtherStuff() doMoreStuff() // ... etc // ... etc }

2018 edit: To more clearly signal that the return value is unimportant you can use the void operator:

function(err, results) { if (err) return void handleError(err) // ... }

It also obeys the “one logical statement per line” guideline, compacting the error detection and handling noise to a single line.

Another benefit is that the return keyword is generally syntax highlighted, so all exit points become very clear, as opposed to hidden inside result = something assignments.

This final form has:

Method at lowest indentation level

No unecessary indentation.

Many fewer lines

Rebecca Murphey has also written about this

The end.

2018 edit: As with any programming practice, one shouldn’t see this as a hard rule that must be obeyed at all times. Early returns make little difference for small functions, and may even increase the cognitive load. However, I find the logic-flattening benefits of early returns become increasingly compelling as the size and complexity of a function increases.

Lots of discussion about this post: