5 ways to merge two objects in JavaScript

Sep 09, 2023#javascript#how-to

In JavaScript, merging objects is a fundamental operation that allows developers to combine the properties and values of multiple objects into a single, cohesive entity. This process is crucial for managing data and creating more complex data structures, enabling the composition of objects with different attributes and functionalities.

Shallow merging combines the top-level properties of objects, but it does not deeply traverse nested objects. Deep merging, on the other hand, combines objects while recursively traversing their nested structures.

  1. Using the spread operator (...) to shallow merge

A syntax that allows you to expand an iterable object, such as an array or a string, into its individual elements. You can use the spread operator to merge two or more objects in JavaScript by creating a new object that contains all the properties from the source objects.

If there are properties with the same name in the source objects, the spread operator will overwrite the values in the new object with the latest source object’s values.

let obj1 = { name: "Alice", age: 25 };
let obj2 = { name: "Bob", city: "New York" };
let obj3 = { ...obj1, ...obj2 };
console.log(obj3); // { name: "Bob", age: 25, city: "New York" }
  1. Using Object.assign() to shallow merge

This is a way to copy all enumerable own properties from one or more source objects to a target object. The target object will receive the properties of the source objects, and return the modified target object. If there are properties with the same name in the source objects, Object.assign() will overwrite the values in the target object with the latest source object’s values.

let obj1 = { name: "Alice", age: 25 };
let obj2 = { name: "Bob", city: "New York" };
let obj3 = Object.assign(obj1, obj2);
console.log(obj3); // { name: "Bob", age: 25, city: "New York" }

The difference between Object.assign() and spread operator is that Object.assign() modifies the target object in place, while the spread operator creates a new object.

let obj1 = { name: "Alice", age: 25 };
let obj2 = { city: "New York", hobby: "reading" };
let obj3 = Object.assign(obj1, obj2);
console.log(obj3); // { name: "Alice", age: 25, city: "New York", hobby: "reading" }
console.log(obj1); // { name: "Alice", age: 25, city: "New York", hobby: "reading" }

Another difference is that the spread operator always gives you a plain object back, while Object.assign() can preserve the prototype of the target object. There are some other minor differences such as how they handle getters and setters, symbols, and non-enumerable properties.

  1. Using Lodash’s merge() function to deep merge

This is a utility used for deep merging objects, recursively combine properties from multiple objects, including nested properties, to create a new merged object. It’s useful when working with complex data structures or when you need to ensure that all levels of properties are merged correctly.

const _ = require('lodash');

const obj1 = { a: 1, nested: { x: 2 } };
const obj2 = { b: 3, nested: { y: 4 } };
const obj3 = _.merge(obj1, obj2);
console.log(obj3); // { a: 1, nested: { x: 2, y: 4 }, b: 3 }
  1. Writing your own shallow merge function

The following shallowMerge function is useful when you want to quickly create a new object that has all the properties from two or more objects, and you don’t care about the nested objects or arrays. However, if you want to merge objects more deeply and preserve the nested objects or arrays, you need to use a different function or a library like Lodash.

// Define a function that takes two objects as parameters
function shallowMerge(obj1, obj2) {
  // Create a new object to store the merged result
  let result = {};
  // Loop through the keys of the first object
  for (let key in obj1) {
    // Copy the value of the key from the first object to the result object
    result[key] = obj1[key];
  }
  // Loop through the keys of the second object
  for (let key in obj2) {
    // Overwrite the value of the key from the second object to the result object
    result[key] = obj2[key];
  }
  // Return the result object
  return result;
}

let obj1 = { name: "Alice", age: 25, skills: ["JavaScript", "HTML", "CSS"] };
let obj2 = { city: "New York", hobby: "reading", skills: ["Python", "React"] };
let obj3 = shallowMerge(obj1, obj2);

console.log(obj3);
// {
//   name: 'Alice',
//   age: 25,
//   skills: [ 'Python', 'React' ],
//   city: 'New York',
//   hobby: 'reading'
// }
  1. Writing your own deep merge function

There are different ways to write a deep merge function in JavaScript, depending on the desired behavior and logic. The key idea is to call the deep merge function recursively on those properties and assign the result to the merged object.

function deepMerge(target, source) {
  const isObject = (obj) => obj && typeof obj === 'object';

  if (!isObject(target) || !isObject(source)) {
    return source;
  }

  Object.keys(source).forEach(key => {
    const targetValue = target[key];
    const sourceValue = source[key];

    if (Array.isArray(targetValue) && Array.isArray(sourceValue)) {
      target[key] = targetValue.concat(sourceValue);
    } else if (isObject(targetValue) && isObject(sourceValue)) {
      target[key] = mergeDeep(Object.assign({}, targetValue), sourceValue);
    } else {
      target[key] = sourceValue;
    }
  });

  return target;
}

let obj1 = { name: "Alice", age: 25, skills: ["JavaScript", "HTML", "CSS"] };
let obj2 = { city: "New York", hobby: "reading", skills: ["Python", "React"] };
let obj3 = deepMerge(obj1, obj2);

console.log(obj3);
// {
//   name: 'Alice',
//   age: 25,
//   skills: [ 'JavaScript', 'HTML', 'CSS', 'Python', 'React' ],
//   city: 'New York',
//   hobby: 'reading'
// }