28

According to the docs, the latest node (Node 5+) should support the spread operator by default, like so:

const newObj = {
        ...oldObj,
        newProperty: 1
      }

And I have node 5.10.1 installed (e.g. that's what 'node -v' tells me). But I am still getting this error:

c:\[myprojectfolder]>node index.js
c:\[myprojectfolder]\index.js:21
            ...oldObj,
            ^^^

SyntaxError: Unexpected token ...
    at exports.runInThisContext (vm.js:53:16)
    at Module._compile (module.js:387:25)
    at Object.Module._extensions..js (module.js:422:10)
    at Module.load (module.js:357:32)
    at Function.Module._load (module.js:314:12)
    at Function.Module.runMain (module.js:447:10)
    at startup (node.js:146:18)
    at node.js:404:3

What am I missing?

batjko
  • 992
  • 2
  • 13
  • 29

3 Answers3

51

The array spread syntax is supported, but the object spread syntax is not - this is most likely due to it not being finalized as part of the ECMAScript spec yet (it was originally planned for inclusion in ES7/ES2016, but it got bumped back, if I recall correctly).

Your options in the meantime are either to use a transpiler (such as Babel, with the transform-object-rest-spread plugin), or if that feels like overkill, you can use the new built-in Object.assign function. The object spread syntax is effectively just syntax sugar around Object.assign - the example in your question could be expressed like so:

const newObj = Object.assign({}, oldObj, {
    newProperty: 1
});

Note the empty object as the first argument; the properties from the rest of the passed objects get merged into it, with those furthest to the right of the function call taking priority. It may seem more intuitive to simply have oldObj as the first argument, but this doesn't have quite the same effect - it would mutate the existing oldObj as well as returning it. Having an empty object as the target leaves oldObj unchanged.


Update: As of Node 8.6, object spread syntax is supported.

Update 2: Object spread syntax has finally made its way through the proposal process, and will be part of the ES2018 spec.

Joe Clay
  • 33,401
  • 4
  • 85
  • 85
  • 4
    Ah! The docs should really reflect that distinction. It only lists "Spread operator" as supported. Ok thank you! I'll go with the Object.assign() method. – batjko Apr 16 '16 at 16:31
  • 2
    @batjko - The node.js docs are missing millions of things. It's a great project with crummy documentation. In fairness, the link node.js has for the spread operator points to the MDN documentation for spread which does NOT mention the object spread syntax at all. So, the node.js doc does not really say that the object spread syntax is supported. You kind of jumped to that conclusion because of the same name. – jfriend00 Apr 16 '16 at 16:32
  • 1
    @batjko: They really should clarify that, you're right! – Joe Clay Apr 16 '16 at 16:32
  • @batjko: You can generally assume that *proposals* are not implemented / supported. – Felix Kling Apr 18 '16 at 05:42
  • 2
    @Felix I understand that. What I wasn't aware of (because I don't have the time to stay on top of it) is that there is a difference between object and array spread operators and that the former is still in the proposal stage. I know now, though. – batjko Apr 18 '16 at 12:29
3

What you tried to use is called object spread and is not part of the es2015 specification. Node only supports the regular spread in function calls and array literals. Unfortunately not even array destructuring is supported yet, although they link to the MDN page which describes both structuring and destructuring use of ....

You can use Object.assign instead:

const newObj = Object.assign({}, oldObj, {
  newProperty: 1
});
Tamas Hegedus
  • 28,755
  • 12
  • 63
  • 97
1

That's works in Node.js 8.5.0.

Example:

var oldObj = {
    oldProperty: 0
}

var newObj = {
    ...oldObj,
    newProperty: 1
}

console.log('Old Object: ' + JSON.stringify(oldObj, null, '    '))

console.log('New Object: ' + JSON.stringify(newObj, null, '    '))

Output:

Old Object: {
    "oldProperty": 0
}
New Object: {
    "oldProperty": 0,
    "newProperty": 1
}

Screenshot from IDE Debug Console:

enter image description here

Mikhail
  • 11,067
  • 7
  • 28
  • 53