When should I use a return statement in ES6 arrow functions

JavascriptEcmascript 6Arrow Functions

Javascript Problem Overview


The new ES6 arrow functions say return is implicit under some circumstances:

> The expression is also the implicit return value of that function.

In what cases do I need to use return with ES6 arrow functions?

Javascript Solutions


Solution 1 - Javascript

Jackson has partially answered this in a similar question:

> Implicit return, but only if there is no block.

> * This will result in errors when a one-liner expands to multiple lines and the programmer forgets to add a return. > * Implicit return is syntactically ambiguous. (name) => {id: name} returns the object {id: name}... right? Wrong. It returns undefined. Those braces are an explicit block. id: is a label.

I would add to this the definition of a block:

> A block statement (or compound statement in other languages) is used to group zero or more statements. The block is delimited by a pair of curly brackets.

Examples:

// returns: undefined
// explanation: an empty block with an implicit return
((name) => {})() 

// returns: 'Hi Jess'
// explanation: no block means implicit return
((name) => 'Hi ' + name)('Jess')

// returns: undefined
// explanation: explicit return required inside block, but is missing.
((name) => {'Hi ' + name})('Jess')

// returns: 'Hi Jess'
// explanation: explicit return in block exists
((name) => {return 'Hi ' + name})('Jess') 

// returns: undefined
// explanation: a block containing a single label. No explicit return.
// more: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label
((name) => {id: name})('Jess') 

// returns: {id: 'Jess'}
// explanation: implicit return of expression ( ) which evaluates to an object
((name) => ({id: name}))('Jess') 

// returns: {id: 'Jess'}
// explanation: explicit return inside block returns object
((name) => {return {id: name}})('Jess') 

Solution 2 - Javascript

I understand this rule-of-thumb ...

> For functions that are effectively transforms (one-line-manipulations of arguments), return is implicit.

Candidates are:

// square-root 
value => Math.sqrt(value)

// sum
(a,b) => a+b

For other operations (more than one-liners that require a block, return has to be explicit

Solution 3 - Javascript

There's another case here.

When writing a functional component in React, you can use parentheses to wrap implicitly returned JSX.

const FunctionalComponent = () => (
  <div>
    <OtherComponent />
  </div>
);

Solution 4 - Javascript

Here's another case that gave me some trouble.

// the "tricky" way
const wrap = (foo) => (bar) => {
  if (foo === 'foo') return foo + ' ' + bar;
  return 'nofoo ' + bar;
}

Here we define a function returning an anonymous function.The "tricky" bit is that the function body for the outer function (the part begining with (bar) => ...) visually looks like a "block", but it's not. Since it's not, implicit return kicks in.

Here's how wrap would execute:

// use wrap() to create a function withfoo()
const withfoo = wrap('foo');
// returns: foo bar
console.log(withfoo('bar'));

// use wrap() to create a function withoutfoo()
const withoutfoo = wrap('bar');
// returns: nofoo bar
console.log(withoutfoo('bar'));

The way I unpacked this to make sure I understood it was to "unarrowify" the functions.

Here's the semantic equivalent of the first code block, simply making the body of wrap() do an explicit return. This definition produces the same results as above. This is where the dots connect. Compare the first code block above with the one below, and it's clear that an arrow function itself is treated as an expression, not a block, and has the implied return.

// the explicit return way
const wrap = (foo) => {
  return (bar) => {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  }
}

The fully unarrowified version of wrap would be like this, which while not as compact as the fat arrowed up version, seems a lot easier to comprehend.

// the "no arrow functions" way
const wrap = function(foo) {
  return function(bar) {
    if (foo === 'foo') return foo + ' ' + bar;
    return 'nofoo ' + bar;
  };
};

In the end, for others that may have to read my code, and future me, I think I'd prefer to go the non arrow version which can be comprehended visually at first glance, rather than the arrow one which takes a fair bit of thought (and in my case experimentation) to grok.

Solution 5 - Javascript

Arrow functions allow you to have an implicit return: values are returned without having to use the return keyword.

It works when there is a on-line statement in the function body:

const myFunction = () => 'test'

console.log(myFunction()) //'test'

Another example, returning an object (remember to wrap the curly brackets in parentheses to avoid it being considered the wrapping function body brackets):

const myFunction = () => ({value: 'test'})

console.log(myFunction()) //{value: 'test'}

Solution 6 - Javascript

Omitting the brackets {} and return keyword from an arrow function are ok if: (1) You wouldn't have any code (e.g. assignment statements) before the return statement and (2) You would be returning a single entity [Note: The single entity can be multiple lines. If so, then all you need are regular parentheses() like the example below:

posts.map(post => (
  <li key={post.id}>
    {post.title}
  </li>
))

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJess TelfordView Question on Stackoverflow
Solution 1 - JavascriptJess TelfordView Answer on Stackoverflow
Solution 2 - JavascriptAmarshView Answer on Stackoverflow
Solution 3 - JavascriptDeciView Answer on Stackoverflow
Solution 4 - JavascriptgrayjohnView Answer on Stackoverflow
Solution 5 - JavascriptFlavio CopesView Answer on Stackoverflow
Solution 6 - Javascriptrob_abcbaView Answer on Stackoverflow