776

When returning an object from an arrow function, it seems that it is necessary to use an extra set of {} and a return keyword because of an ambiguity in the grammar.

That means I can’t write p => {foo: "bar"}, but have to write p => { return {foo: "bar"}; }.

If the arrow function returns anything other than an object, the {} and return are unnecessary, e.g.: p => "foo".

p => {foo: "bar"} returns undefined.

A modified p => {"foo": "bar"} throws SyntaxError: unexpected token: ':'”.

Is there something obvious I am missing?

Sebastian Simon
  • 16,564
  • 7
  • 51
  • 69
Jonathan Schneider
  • 25,414
  • 12
  • 69
  • 99
  • I'm not clear when to use return keyword and when not to use it, JS being very very flexible creates loads of bugs for new users of this language. I wish it was as strict like "Java" language – vikramvi Apr 07 '21 at 10:47

6 Answers6

1320

You must wrap the returning object literal into parentheses. Otherwise curly braces will be considered to denote the function’s body. The following works:

p => ({ foo: 'bar' });

You don't need to wrap any other expression into parentheses:

p => 10;
p => 'foo';
p => true;
p => [1,2,3];
p => null;
p => /^foo$/;

and so on.

Reference: MDN - Returning object literals

str
  • 38,402
  • 15
  • 99
  • 123
alexpods
  • 45,559
  • 10
  • 97
  • 92
  • 11
    I'm curious *why* the parens make a difference. – wrschneider Jan 18 '17 at 02:28
  • 61
    @wrschneider because without parens js parser thinks that its a function body, not an object, and foo is [a label](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/label) – alexpods Jan 18 '17 at 13:31
  • 26
    @wrschneider more specifically, in terms of AST nodes, using parentheses denotes an expression statement, in which an object expression can exist, whereas by default, curly braces are interpreted as a block statement. – Patrick Roberts May 20 '17 at 07:43
  • 6
    No idea why this works, but if you want to use the value of `p` as key for the object literal, this is how you do it: `p => ({ [p]: 'bar' })`. Without the `[]`, it'll either be `undefined` or literally the letter `p`. – DanMan Oct 03 '18 at 23:52
  • 3
    @DanMan It's called [computed properties](https://developer.mozilla.org/pt-PT/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names) and it's a feature of object literals. – D. Pardal May 04 '20 at 15:13
  • why we don't have to use return keyword inside parenthesis ? – vikramvi Apr 07 '21 at 10:46
  • 2
    @vikramvi Because `p => ({ foo: 'bar' })` is the same as `p => { return { foo: 'bar' }; }`. It's a shorthand syntax. – Adrian Wiik Apr 11 '22 at 11:02
73

You may wonder, why the syntax is valid (but not working as expected):

var func = p => { foo: "bar" }

It's because of JavaScript's label syntax:

So if you transpile the above code to ES5, it should look like:

var func = function (p) {
  foo:
  "bar"; //obviously no return here!
}
Petr Odut
  • 1,529
  • 13
  • 7
  • 6
    Labels are such a seldom used and esoteric feature. Do they REALLY have any value? I feel like they should be deprecated and eventually removed. – Kenmore Feb 27 '19 at 21:51
  • 3
    @Kenmore See https://stackoverflow.com/questions/55934490/why-are-await-and-async-valid-variable-names/55934491#55934491 - backwards compatibility. *Browsers will refuse to implement a feature which breaks existing sites* – CertainPerformance Jun 11 '19 at 07:29
  • 3
    @Kenmore you can exit from nested loops if they are labeled. Not often used but definitely useful. – Petr Odut Jun 26 '19 at 14:24
22

If the body of the arrow function is wrapped in curly braces, it is not implicitly returned. Wrap the object in parentheses. It would look something like this.

p => ({ foo: 'bar' })

By wrapping the body in parens, the function will return { foo: 'bar }.

Hopefully, that solves your problem. If not, I recently wrote an article about Arrow functions which covers it in more detail. I hope you find it useful. Javascript Arrow Functions

Paul McBride
  • 298
  • 2
  • 8
  • why we don't have to use return keyword inside parenthesis ? – vikramvi Apr 07 '21 at 10:46
  • Because `p => ({ foo: 'bar' })` is transpiled into `p => { return { foo: 'bar' }; }`. It's a shorthand syntax. – Adrian Wiik Apr 11 '22 at 10:58
  • Arrow functions implicitly return the expression on the right side of the arrow. eg `p => p * 2` will return the result of `p * 2`. The exception to this rule is when the expression on the right side is wrapped in curly braces, then you have to return yourself. – Paul McBride Apr 12 '22 at 11:34
9

Issue:

When you do are doing:

p => {foo: "bar"}

JavaScript interpreter thinks you are opening a multi-statement code block, and in that block, you have to explicitly mention a return statement.

Solution:

If your arrow function expression has a single statement, then you can use the following syntax:

p => ({foo: "bar", attr2: "some value", "attr3": "syntax choices"})

But if you want to have multiple statements then you can use the following syntax:

p => {return {foo: "bar", attr2: "some value", "attr3": "syntax choices"}}

In above example, first set of curly braces opens a multi-statement code block, and the second set of curly braces is for dynamic objects. In multi-statement code block of arrow function, you have to explicitly use return statements

For more details, check Mozilla Docs for JS Arrow Function Expressions

Rusty
  • 3,429
  • 3
  • 30
  • 37
8

ES6 Arrow Function returns an Object

the right ways

  1. normal function return an object

const getUser = user => {return { name: user.name, age: user.age };};

const user = { name: "xgqfrms", age: 21 };

console.log(getUser(user));
//  {name: "xgqfrms", age: 21}

  1. (js expressions )

const getUser = user => ({ name: user.name, age: user.age });

const user = { name: "xgqfrms", age: 21 };

console.log(getUser(user));
//  {name: "xgqfrms", age: 21}

explain

image

refs

https://github.com/lydiahallie/javascript-questions/issues/220

https://mariusschulz.com/blog/returning-object-literals-from-arrow-functions-in-javascript

xgqfrms
  • 7,269
  • 1
  • 50
  • 53
-6

You can always check this out for more custom solutions:

x => ({}[x.name] = x);