3 Ways To Combine JavaScript Objects

Using the assign method, loops, and the spread operator

Corey Butler
Better Programming

--

Code
Photo by Luca Bravo on Unsplash.

Objects are a powerful part of JavaScript. They are the inspiration for JSON (JavaScript Object Notation). As a fundamental component of application development, there are many ways to work with them.

This short guide offers insights into JavaScript objects and how to combine them using plain JavaScript. None of the examples or demonstrated concepts require special libraries, frameworks, or other code. These techniques will work in standard JavaScript runtimes. The merits of each technique are also described.

Upon completion, readers should have a good understanding of which techniques are available and how to choose the most appropriate technique for any given use case.

Note: The examples in this guide can be run directly in your browser while you read. Use the DevTools console to run the examples. For help opening DevTools, see the guides for Chrome, Edge, Firefox, or Safari.

JavaScript Objects

First, a JavaScript object is a collection of key-value pairs. Values themselves can be JavaScript primitives (string/text, number, boolean, etc.) or other objects. Since objects can be infinitely nested within objects, it is possible to create significant data structures.

Example of JavaScript object
Example of JavaScript object

The syntax is important. This is a JavaScript object used within JavaScript code. It is not JSON, which requires quotes around keys.

Example of JSON
Example of JSON

A note about ECMAScript

ECMAScript (ES) is the specification for JavaScript (i.e. the blueprint). It is maintained by ECMA International by a governing body known as TC39. For years, the specification remained relatively unchanged. That changed in 2015 when a new wave of JavaScript was released with ECMAScript 6 (ES6).

One of the major efforts of ES6 was new native functions designed to work with JavaScript objects. This guide covers several of those features as well as practices used in prior generations of the ECMA specification.

Combining Objects With Object.assign()

Object.assign() was first released in ES2015, so it won’t be found in legacy code bases, but it is commonplace amongst modern JavaScript runtimes.

The code is straightforward:

Basic Object.assign()
Basic Object.assign()

Here is the result:

Basic Object.assign() result
Basic Object.assign() result

Object.assign() supports any number of object parameters, so it is possible to combine many objects at once, such as Object.assign(obj_a, obj_b, obj_c). This is a straightforward approach for combining objects, but there are also some unexpected behaviors.

Caveat: Overwriting attributes

Sometimes different objects share key names, which creates a potential conflict. Which key value should be honored?

Object.assign() with conflicting key names
Object.assign() with conflicting key names

When should I use Object.assign()?

This approach is best in situations where the key names are known not to conflict or overwriting values is preferred.

A common use case where overwriting conflicting values is preferable is the use of default values. Consider the creation of a vehicle class where the default vehicle has four wheels and four doors. The defaults may work for most sedans, but a coupe only has two doors. In this case, overriding the default “four-door” value is preferable.

Code
Code
Result
Result

Combining Objects With Loops

Objects can also be combined with loops. This is a more manual process that provides greater control over how the objects are combined.

Consider the same objects used in the Object.assign() example, but notice that a simple for loop is used to append objects from one to the other.

Combining objects with a for loop
Combining objects with a for loop

The result of this is exactly the same as the result of Object.assign(). The major difference between the two approaches is control over how the merging occurs (lines 16-18).

Code

When should I use for loops to combine objects?

This approach can be effective whenever greater control of the merging process is necessary.

Custom processing

Aside from preventing conflicting names from overwriting each other, there are many other data modifications that can be made. For example, data can be replaced or substituted.

Replacing values
Replacing values

There are many other data manipulations that can be achieved during merges thanks to the flexibility of JavaScript objects.

Legacy code

If you work with older code, such as code that must run in Internet Explorer and other older browsers, this approach is one of the better options. These browsers use ECMAScript 5, an older standard. Object.assign is not available in ECMAScript 5.

Enumerability (hidden properties)

Each property of a JavaScript object is defined with four underlying configuration properties: enumerable, writable, configurable, and value (see Object.defineProperty() for detail). The enumerability of an object loosely translates to “hidden attribute.” Non-enumerable object properties are not returned in the Object.keys(), Object.assign(), or other similar functions. This means the attribute is still there, but it isn’t easy to see or use.

If you need to merge non-enumerable attributes into a different JavaScript object, it is necessary to do so using a custom merge operation. The code for such an operation may look like this:

Object.getOwnPropertyNames() instead of Object.keys()
Object.getOwnPropertyNames() instead of Object.keys()

Combining Objects With the Spread Operator

The spread syntax was released in ECMAScript 6 (ES6). It was not exclusively designed for the purpose of merging objects, but it does allow for a unique technique similar to Object.assign().

Combining objects with the spread operator
Combining objects with the spread operator

There isn’t a difference in the outcome between this approach and Object.assign().

When should I use spread operators to combine objects?

Using spread operators isn’t typically the first choice for combining data objects, but it can be used in edge cases when it seems appropriate.

Try not to use this just because the syntax may be more pleasing. It works, but this approach is much less common. Even some experienced developers who don’t work with JavaScript every day may not be familiar with the spread syntax. Some experienced developers may not even be familiar with Object.assign() if they don’t use JavaScript every day, but it’s much easier to tell that it’s a method. Ask yourself how easy it is to Google three dots () and their meaning — especially if you don’t know JavaScript has spread operators.

Deep merging

Object.assign() and the spread operator are both shallow merging techniques. Shallow merging only combines attributes at the first level of the object. Deep merging combines objects at the first level but also merges nested attributes and objects.

There isn’t a convenient way to perform deep merging with plain JavaScript. There are libraries that implement deep merging. In this author’s experience, the need for deep merging is infrequent. Oftentimes, it is unnecessary to include a deep merging library in a code base when simpler techniques will offer sufficient capability.

Conclusion

This guide has covered the fundamental ways to combine JavaScript objects. Working with data in JavaScript objects can be simple. It can also be complex with advanced data structures. There are tools for both kinds of tasks.

Combining JavaScript data objects is straightforward. Data objects aren’t the only object type in JavaScript, though.

The JavaScript language itself uses prototypal inheritance. In super-simplistic/crude terms, this means everything is an object. Every object has a non-enumerable[[Prototype]] (__proto__) attribute exposing many of the inner workings of a JavaScript object. Describing prototypal inheritance is beyond the scope of this article, but it is worth exploring. Why? These techniques can be used to merge any JavaScript object — not just data.

This article was based on an original Quora answer.

--

--

I build communities, companies, and code. Cofounder of Metadoc.io. Created Fenix Web Server & NVM for Windows.