1

Can someone explain to me why this is the only version I've tried that works for copying state with es6 and adding another field, out of the other ways tried that are listed below? :

const values = [{key: "1", val: "one"}, {key: "2", val: "two"}];

var works = values.map(v => {
    return {
       ...v,
       extra: "stuff"
   }
})

And all of these produce these errors:

//Unexpected token '...'
var notWorks1 = values.map(v => ...v, extra: "stuff"); 

// Rest parameter must be last formal parameter
var notWorks2 = values.map(v => {...v, extra: "stuff"}) 

// Rest parameter must be last formal parameter
var notWorks3 = values.map(v => {
  {
   ...v, 
   extra: "stuff"
  }
}) 

// unexpected token 'return'
var notWorks4 = values.map(v => 
   return {
    ...v, 
    extra: "stuff"
   }
) 
// unexpected 'return'
var notWorks5 = values.map(v => return ...v, extra: "stuff");

I thought the arrow was implicit return (see first 3 attempts).

Is that first way the only syntax that can be used? If there are any others, I'd like to know as I'm trying to practice and learn multiple options.. and I want the most terse, smallest option (one line).

VLAZ
  • 26,331
  • 9
  • 49
  • 67
MattoMK
  • 609
  • 1
  • 8
  • 25
  • 7
    If you want to have `return` in an arrow function, you need to surround the body in `{ }` e.g., `() => { return {foo: "bar"} }`. And if you want [a single line arrow function that returns an object](https://stackoverflow.com/questions/28770415/ecmascript-6-arrow-function-that-returns-an-object) you need to surround the object in `( )` e.g., `() => ({ foo: "bar"})` – VLAZ Feb 12 '22 at 21:03
  • 1
    Missed the edit window of the comment, so here is a link about the first one: [When should I use a return statement in ES6 arrow functions](https://stackoverflow.com/q/28889450) – VLAZ Feb 12 '22 at 21:10

2 Answers2

2

The answer of @Bulent is correct, but I'd like to add some more information:

//Unexpected token '...'
var notWorks1 = values.map(v => ...v, extra: "stuff");

This syntax doesn't make sense. As @Bulent says, the spread syntax (...) can only be used inside object literals ({ ...v }), array literals ([ ...v ], only if v is an array) or function calls (f( ...v ), again only if v is an array).

// Rest parameter must be last formal parameter
var notWorks2 = values.map(v => {...v, extra: "stuff"})

The problem here is that in JavaScript braces ({, }) have two functions: either for object literals, as you are trying to use here, but also for code blocks, for example around the body of a function. In this case JavaScript is expecting the braces to be the body of the arrow function. What needs to be done is change the context so that an expression (which an object literal is) is expected. This can for example be done by putting the object literal in round brackets:

var notWorks2 = values.map(v => ({...v, extra: "stuff"}))
// Rest parameter must be last formal parameter
var notWorks3 = values.map(v => {
  {
   ...v, 
   extra: "stuff"
  }
})

Again the first pair of braces is consider a (function body) block, and inside a block braces are again expected to be another block. This time wrapping the object literal in round brackets wouldn't do anything, because an expression alone does nothing inside a function body. Instead you have to use return.

// unexpected token 'return'
var notWorks4 = values.map(v => 
   return {
    ...v, 
    extra: "stuff"
   }
)

Arrow functions can consist of either an expression (no braces) or a function body block (with braces). A return statement isn't an expression, so this doesn't work. return statements can only be used inside a function body block.

One final point: Avoid using var. It is outdated. Use const or let instead.

RoToRa
  • 37,635
  • 12
  • 69
  • 105
  • thanks for all the detail, mostly makes sense first read through. yeah, i normally use const/let but I was in the browser console and for some reason I'm trained to use var there (muscle memory i guess). – MattoMK Feb 13 '22 at 02:03
1
  1. spread syntax is used in an array or object. So you have to put it between {} or [].

  2. {} are compiled as if they belong to the arrow function, not an object.

  3. When you put your code in {}, you need to return the result.

  4. In order to use return in arrow function, you need the put it between {}

  5. The same as 4.

Bulent
  • 3,307
  • 1
  • 14
  • 22
  • *"spread operator is used in an array or object. So you have to put it between {} or []."* Please don't call it operator. It's not an operator, otherwise you could actually use it in arbitrary expressions. It's a special "syntax" provided by object and array literals (as well as parameter definitions and call expressions). – Felix Kling Feb 12 '22 at 21:27
  • Alright, I'll update my answer. – Bulent Feb 12 '22 at 21:29