Home > Back-end >  syntax explanation for copying object array and add new property
syntax explanation for copying object array and add new property

Time:02-13

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).

CodePudding user response:

  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.

CodePudding user response:

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.

  • Related