Merging Multiple Objects in JavaScript

Hero image for Merging Multiple Objects in JavaScript. Image by Eric Prouzet.
Hero image for 'Merging Multiple Objects in JavaScript.' Image by Eric Prouzet.

In JavaScript development, merging objects is a fairly common task, whether you're combining configuration settings, updating application state, or consolidating data. In this article, I hope to explore various ways of merging multiple objects in JavaScript. I'll cover traditional methods and ES6 features like the spread operator, and we can briefly discuss upcoming proposals that might change these suggestions. By the end, you should understand how to merge objects efficiently whilst maintaining code clarity and performance.


What Does It Mean to Merge Objects?

Merging objects involves combining the properties of two or more objects into a single object. If properties share the same key, the value from the latter object typically overwrites the former, for example:

const obj1 = { a: 1, b: 2 };const obj2 = { b: 3, c: 4 };// Merged resultconst merged = { a: 1, b: 3, c: 4 };

Using Object.assign() (ES6)

Introduced in ES6 (2015), Object.assign() is a widely supported method for merging objects together:

const obj1 = { a: 1, b: 2 };const obj2 = { b: 3, c: 4 };const merged = Object.assign({}, obj1, obj2);console.log(merged);  // Output: { a: 1, b: 3, c: 4 }

Key Points About Object.assign()

  • It mutates the target object (the first argument).
  • To prevent mutation, you need to pass an empty object {} as the first argument.
  • It only performs a shallow copy, which means that nested objects are not deeply cloned:
const obj1 = { a: { value: 1 } };const obj2 = { a: { value: 2 } };const merged = Object.assign({}, obj1, obj2);console.log(merged);  // Output: { a: { value: 2 } }

Using the Spread Operator (Es2018)

The object spread syntax, introduced in ES2018, offers a cleaner and more concise way to merge objects, although browser support can still be a little patchy in older browsers. Using spread syntax looks like this:

const obj1 = { a: 1, b: 2 };const obj2 = { b: 3, c: 4 };const merged = { ...obj1, ...obj2 };console.log(merged);  // Output: { a: 1, b: 3, c: 4 }

Advantages of the Spread Operator

  • Readability:

    The syntax is fairly concise and intuitive.
  • Immutability:

    Like Object.assign(), it doesn't mutate the original objects.
  • Shallow Merge:

    Similar to Object.assign(), it doesn't deeply clone nested objects.

Nested Objects and Shallow Merging

const obj1 = { a: { value: 1 } };const obj2 = { a: { value: 2 } };const merged = { ...obj1, ...obj2 };console.log(merged);  // Output: { a: { value: 2 } }

In this example, the a property from obj2 completely overwrites the a property from obj1.


Merging Objects Without ES6 Features

For environments where we don't yet have support for ES6 features (like older browsers), you can merge objects using loops.

Using a for...in Loop

const mergeObjects = (...objects: any[]): any => {  const result: any = {};  objects.forEach(obj => {    for (const key in obj) {      if (Object.prototype.hasOwnProperty.call(obj, key)) {        result[key] = obj[key];      }    }  });  return result;};const obj1 = { a: 1, b: 2 };const obj2 = { b: 3, c: 4 };console.log(mergeObjects(obj1, obj2));  // Output: { a: 1, b: 3, c: 4 }

This will do much the same as the more modern offerings from .assign() and the spread operator, but will also be supported by all those pesky browsers you still need to support, even though they are thoroughly out of date.

The fact that I've used ES6 arrow syntax to share this example with you has not passed me by either. You'll probably not want to use it in quite this form if you are targeting browsers that don't support ES6!

Considerations for Older Methods

  • More verbose compared to modern alternatives and perhaps harder to maintain.
  • Requires hasOwnProperty checks to avoid copying inherited properties.
  • Still only performs a shallow merge.

Wrapping up

Merging objects in JavaScript can be achieved through one of several methods, each suited to different environments and use cases. From traditional loops to ES6's Object.assign() and the concise spread operator in ES2018, JavaScript offers flexible ways to handle object merging tasks.

Key Takeaways

  • Use Object.assign() for reliable, shallow merging in ES6 environments.
  • The spread operator (...) introduced in ES2018 offers cleaner syntax and avoids mutation.
  • For older browsers, for...in loops provide a compatible, albeit verbose, solution.
  • Deep merging isn't natively supported (as of 2018); consider libraries like Lodash for complex data structures.

Understanding these techniques ensures you can merge objects effectively, regardless of the JavaScript environment you're working in.


Categories:

  1. Development
  2. Front‑End Development
  3. Guides
  4. JavaScript