Merge Object Properties with the Spread Operator

By  on  

Last week I wrote 6 Great Uses of the Spread Operator, a post detailing how awesome the spread operator (...) is for working with arrays and other iterable objects.  As always my readers chimed in with a few other great uses and which you should check out in the comments.  And of course as soon as I publish the post I find another great use of the spread operator while I tinker with Babel and React:  merging multiple objects' properties into one object!

The JavaScript

Wrap any objects you'd like merged into one with braces ({}):

const person = { name: 'David Walsh', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };

const summary = {...person, ...tools};
/*
Object {
  "computer": "Mac",
  "editor": "Atom",
  "gender": "Male",
  "name": "David Walsh",
}
*/

A new object is created containing all properties and values from the objects provided with the rest operator.  Also note that you can provide any number of objects to merge:

const person = { name: 'David Walsh', gender: 'Male' };
const tools = { computer: 'Mac', editor: 'Atom' };
const attributes = { handsomeness: 'Extreme', hair: 'Brown', eyes: 'Blue' };

const summary = {...person, ...tools, ...attributes};
/*
Object {
  "computer": "Mac",
  "editor": "Atom",
  "eyes": "Blue",
  "gender": "Male",
  "hair": "Brown",
  "handsomeness": "Extreme",
  "name": "David Walsh",
}
*/

In the case of a key collision, the right-most (last) object's value wins out:

const person1 = { name: 'David Walsh', age: 33 };
const person2 = { name: 'David Walsh Jr.', role: 'kid' };

const merged = {...person1, ...person2}
/*
Object {
  "name": "David Walsh Jr.",
  "age": 33,
  "role": "kid",
}
*/

I love how easy merging objects is using the spread operator.  You can use Object.assign to accomplish the same feat but the spread operator makes things a bit shorter if you don't mind a slightly less descriptive syntax!

Note:  This syntax is not yet support by all browsers but you can use Babel with the transform-object-rest-spread plugin to enable object merging with the spread operator.

Recent Features

  • By
    CSS Filters

    CSS filter support recently landed within WebKit nightlies. CSS filters provide a method for modifying the rendering of a basic DOM element, image, or video. CSS filters allow for blurring, warping, and modifying the color intensity of elements. Let's have...

  • By
    5 HTML5 APIs You Didn’t Know Existed

    When you say or read "HTML5", you half expect exotic dancers and unicorns to walk into the room to the tune of "I'm Sexy and I Know It."  Can you blame us though?  We watched the fundamental APIs stagnate for so long that a basic feature...

Incredible Demos

  • By
    Create a Simple Dojo Accordion

    Let's be honest:  even though we all giggle about how cheap of a thrill JavaScript accordions have become on the web, they remain an effective, useful widget.  Lots of content, small amount of space.  Dojo's Dijit library provides an incredibly simply method by which you can...

  • By
    Create a Spinning, Zooming Effect with CSS3

    In case you weren't aware, CSS animations are awesome.  They're smooth, less taxing than JavaScript, and are the future of node animation within browsers.  Dojo's mobile solution, dojox.mobile, uses CSS animations instead of JavaScript to lighten the application's JavaScript footprint.  One of my favorite effects...

Discussion

  1. Fred

    Excellent tip! Thank you.

  2. MaxArt

    To be precise, only Chrome 58 at the moment supports the object spread operator, behind a flag too. But I’ve been using it with great satisfaction with Babel behind.

    It’s very expressive, and also helps adopting an immutable pattern in your code, as opposed to Object.assign it creates a new object every time.

  3. Rob David

    Sweet! Nice tip :)

  4. gocho

    Object’s key now has order, so

    ({...{b: 1, a: 2}, ...{d: 3, c: 4}})

    will result in

    {b: 1, a: 2, d: 3, c: 4}
  5. var __assign = (this && this.__assign) || Object.assign || function(t) {
        for (var s, i = 1, n = arguments.length; i < n; i++) {
            s = arguments[i];
            for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
                t[p] = s[p];
        }
        return t;
    };
    var person = { name: 'David Walsh', gender: 'Male' };
    var tools = { computer: 'Mac', editor: 'Atom' };
    var summary = __assign({}, person, tools);
    
  6. This code above is an TypeScript translation to ES5

  7. Stefano

    And what about common properties? What does the sprea operator manage the merge?

  8. Fred

    Thanks Bigismall, I didn’t know about Object.assign. Here is the MDN doc with the polyfill and the browser support:

    https://developer.mozilla.org/pl/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

  9. A word of warning, spread operator object merging should be used only on one level deep objects, meaning objects won’t be deeply merged.

    • Joao Pedro Furtado Lourenco

      Yeah. Is there any nice way to have deep merge in es6 or typescript.

  10. Con

    What about deep merge? Is there a builtin method via ECMAScript?

  11. Phillip Hall

    Be aware that merging objects with undefined properties may result in unexpected objects as in the following example;

    const defaults = {prop1: 'prop1', prop2: 'prop2', prop3: 'prop3'};
    const params = {prop1: 'overridden', prop2: undefined}
    const result = {...defaults, ...params};
    // Might expect result = {prop1: 'overridden', prop2: 'prop2', prop3: 'prop3'}
    // But result = {prop1: 'overridden', prop2: undefined, prop3: 'prop3'}
    
    • Atul

      In the case of a key collision, the right-most (last) object’s value wins

    • craig

      delete to the rescue.

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!