Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ES6 Fat Arrow and Parentheses `(...) => ({...})` [duplicate]

I've been working through some Graph QL/React/Relay examples and I ran into some strange syntax.

When defining the fields in Graph QL Objects the following syntax is used:

const xType = new GraphQLObjectType({
  name: 'X',
  description: 'A made up type for example.',
  fields: () => ({
    field: {/*etc.*/}
  })
});

From what I gather this is just defining an anonymous function and assigning it to xType.fields. That anonymous function returns the object containing the field definitions.

I'm assuming with however the Graph QL schema mechanism works this has to be defined as a function returning an object rather than simply an object. But the part that has me confused is the parenthesis around the curly braces.

Is this to differentiate an object definition from a function definition? Is it for clarity's sake for the reader?

The only similar syntax a google search has found is in the airbnb style guide where it seems to be a readability/clarity thing.

Just looking for confirmation or an explanation beyond my assumptions as I start to play around with Graph QL a little more.

like image 835
Tim Hope Avatar asked Dec 11 '16 23:12

Tim Hope


2 Answers

fields: () => ({
  field: {/*etc.*/}
})

is a function that implicitly returns an object (literal). Without using () JavaScript interpreter interprets the {} as a wrapper for the function body and not as an object.

Without using parens: (), the field: ... statement is treated as a label statement and the function returns undefined. The equivalent syntax is:

fields: () => { // start of the function body
   // now we have to define an object 
   // and explicitly use the return keyword
   return { field: {/*etc.*/} }
}

So parents are not there for clarity. It's there for using implicit-returning feature of arrow functions.

like image 98
undefined Avatar answered Nov 09 '22 06:11

undefined


It's for clarity's sake for the compiler as well as for the reader. The field: syntax in your example appears to be an unambiguous giveaway that this is an object literal, but take this code for instance:

let f = () => {
  field: 'value'
}

console.log(f()) //=> undefined

You would expect this to log an object with field set to 'value', but it logs undefined. Why?

Essentially, what you see as an object literal with a single property, the compiler sees as a function body (denoted by opening and closing curly braces, like a typical function) and a single label statement, which uses the syntax label:. Since the expression following is it just a literal string, and it is never returned (or even assigned to a variable), the function f() effectively does nothing, and its result is undefined.

However, by placing parentheses around your "object literal," you tell the compiler to treat the same characters as an expression rather than a bunch of statements, and so the object you desire is returned. (See this article on the Mozilla Development Network, from the comments section.)

let g = () => ({
  field: 'value'
})

console.log(g()) //=> { field: 'value' }
like image 31
gyre Avatar answered Nov 09 '22 06:11

gyre