Create a copy of a Map or a Set in JavaScript

avatar
Borislav Hadzhiev

Last updated: Mar 3, 2024
8 min

banner

# Table of Contents

  1. Create a Deep Copy of a Map in JavaScript
  2. Create a Deep Copy of a Map using lodash
  3. Create a shallow copy of a Map in JavaScript
  4. Create a shallow copy of a Map using Map.forEach
  5. Create a shallow Copy of a Set in JavaScript
  6. Create a shallow Copy of a Set using a for...of loop
  7. Create a deep copy of a Set in JavaScript
  8. Create a deep copy of a Set using lodash

# Create a Deep Copy of a Map in JavaScript

To create a deep copy of a Map object:

  1. Convert the Map to an array.
  2. Use the JSON.stringify() method to stringify the array.
  3. Use the JSON.parse() method to parse the JSON string.
  4. Pass the result to the Map() constructor.
index.js
const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); const deepCopy = new Map( JSON.parse( JSON.stringify(Array.from(existingMap)) ) ); // ๐Ÿ‘‡๏ธ {'address' => {street: 'Example'}, 'numbers': [1, 2, 3]} console.log(deepCopy);

create deep copy of map

The code for this article is available on GitHub

If you need to create a copy of a Set, click on the following subheading.

We used the Array.from() method to convert the Map object to a two-dimensional array.

index.js
const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); // ๐Ÿ‘‡๏ธ [['address', {street: 'Example}], ['numbers', [1, 2, 3]]] console.log(Array.from(existingMap));

The next step is to use the JSON.stringify() method to convert the array to a JSON string.

index.js
const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); // ๐Ÿ‘‡๏ธ '[["address",{"street":"Example"}],["numbers",[1,2,3]]]' console.log(JSON.stringify(Array.from(existingMap)));
Converting the array to a JSON string makes all the nested arrays and objects lose their reference.

We then used the JSON.parse() method to parse the string back into an array.

index.js
const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); // ๐Ÿ‘‡๏ธ [ [ 'address', { street: 'Example' } ], [ 'numbers', [ 1, 2, 3 ] ] ] console.log(JSON.parse(JSON.stringify(Array.from(existingMap))));

The last step is to pass the two-dimensional array to the Map() constructor.

The trick here is to stringify the array, using the JSON.stringify method, so that all nested objects lose their reference.

If we then try to mutate the array in the new Map, it wouldn't affect the existing Map.

index.js
const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); const deepCopy = new Map(JSON.parse( JSON.stringify(Array.from(existingMap)) )); deepCopy.get('numbers').pop(); // ๐Ÿ‘‡๏ธ {'address' => {street: 'Example'}, 'numbers' => [1, 2]} console.log(deepCopy); // ๐Ÿ‘‡๏ธ {'address' => {'street':'Example'},'numbers' => [1, 2, 3]} console.log(existingMap);
The code for this article is available on GitHub

We used the pop method to mutate the array in the deep copy, however, the array in the existing Map wasn't affected.

The nested arrays in the Maps have a different reference and location in memory because we used the JSON.stringify method.

If you have to create deep copies of Map objects often, define a reusable function.

index.js
function deepCopyMap(map) { return new Map(JSON.parse(JSON.stringify(Array.from(map)))); } const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); const copy = deepCopyMap(existingMap); // ๐Ÿ‘‡๏ธ Map(2) { 'address' => { street: 'Example' }, 'numbers' => [ 1, 2, 3 ] } console.log(copy);

The function takes a Map object as a parameter and returns a deep copy of the Map.

# Create a Deep Copy of a Map using lodash

You can also use the lodash library to create a deep copy of a Map object.

First, install the lodash module if you haven't already.

shell
# ๐Ÿ‘‡๏ธ initialize a package.json file npm init -y npm install lodash

You can now import and use the lodash.cloneDeep() method.

index.js
import _ from 'lodash'; const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); const deepCopy = _.cloneDeep(existingMap); // ๐Ÿ‘‡๏ธ Map(2) { 'address' => { street: 'Example' }, 'numbers' => [ 1, 2, 3 ] } console.log(deepCopy);

create deep copy of map using lodash

The code for this article is available on GitHub

The cloneDeep method takes a value and recursively clones it, returning the deep cloned value.

Mutating the array property in the cloned Map doesn't mutate the property in the original Map.

index.js
import _ from 'lodash'; const existingMap = new Map([ ['address', {street: 'Example'}], ['numbers', [1, 2, 3]], ]); const deepCopy = _.cloneDeep(existingMap); deepCopy.get('numbers').pop(); // ๐Ÿ‘‡๏ธ {'address' => {street: 'Example'}, 'numbers' => [1, 2]} console.log(deepCopy); // ๐Ÿ‘‡๏ธ {'address' => {'street':'Example'},'numbers' => [1, 2, 3]} console.log(existingMap);

We used the pop method to mutate the array in the deep copy, however, the array in the existing Map wasn't affected.

# Create a shallow copy of a Map in JavaScript

To create a shallow copy of a Map:

  1. Pass the existing Map as a parameter to the Map() constructor.
  2. The Map() constructor takes an iterable, such as another Map, and adds the key-value pairs of the iterable to the new Map.
index.js
const oldMap = new Map([ ['name', 'bobby hadz'], ['country', 'Chile'], ]); // ๐Ÿ‘‡๏ธ Map(2) { 'name' => 'bobby hadz', 'country' => 'Chile' } console.log(oldMap); const copy = new Map(oldMap); // ๐Ÿ‘‡๏ธ Map(2) { 'name' => 'bobby hadz', 'country' => 'Chile' } console.log(copy);

create shallow copy of map

The code for this article is available on GitHub

We used the Map() constructor to create a shallow copy of an existing Map.

The only parameter the constructor takes is an iterable, such as an array, or another Map.

The elements in the iterable should be key-value pairs, e.g. a two-dimensional array or another Map object.

index.js
const example1 = [ ['name', 'Tom'], ['country', 'Chile'], ]; const example2 = new Map([ ['name', 'Tom'], ['country', 'Chile'], ]);

Each key-value pair gets added to the new Map.

The new Map object has a completely different reference and location in memory.

Adding key-value pairs to it does not interact with the existing Map.

index.js
const oldMap = new Map([ ['name', 'bobby hadz'], ['country', 'Chile'], ]); // ๐Ÿ‘‡๏ธ Map(2) { 'name' => 'bobby hadz', 'country' => 'Chile' } console.log(oldMap); const copy = new Map(oldMap); // ๐Ÿ‘‡๏ธ Map(2) { 'name' => 'bobby hadz', 'country' => 'Chile' } console.log(copy); copy.set('age', 30); // ๐Ÿ‘‡๏ธ Map(3) { 'name' => 'bobby hadz', 'country' => 'Chile', 'age' => 30 } console.log(copy); // ๐Ÿ‘‡๏ธ Map(2) { 'name' => 'bobby hadz', 'country' => 'Chile' } console.log(oldMap);

The code sample shows that adding key-value pairs to the copy doesn't add key-value pairs to the original Map object.

You can also use the Map.forEach() method to create a shallow copy of a Map object.

# Create a shallow copy of a Map using Map.forEach

This is a three-step process:

  1. Declare a new variable and initialize it to an empty Map.
  2. Use the Map.forEach() method to iterate over the existing Map.
  3. Use the Map.set() method to add each key-value pair to the new Map.
index.js
const oldMap = new Map([ ['name', 'bobby hadz'], ['country', 'Chile'], ]); const copy = new Map(); oldMap.forEach((value, key) => { copy.set(key, value); }); // ๐Ÿ‘‡๏ธ Map(2) { 'name' => 'bobby hadz', 'country' => 'Chile' } console.log(oldMap);

create shallow copy of map using foreach

The code for this article is available on GitHub

We used the Map() constructor to create an empty Map object.

The function we passed to the Map.forEach method gets called with each key-value pair of the Map object.

On each iteration, we use the Map.set() method to add the current key-value pair to the new Map object.

# Create a shallow Copy of a Set in JavaScript

To create a shallow copy of a Set, pass the original Set as a parameter to the Set() constructor, e.g. const cloned = new Set(oldSet).

The Set() constructor takes an iterable, such as another Set, and adds all of the elements of the iterable to the new Set.

index.js
const set1 = new Set(['bobby', 'hadz', 'com']); const cloned = new Set(set1); console.log(cloned); // ๐Ÿ‘‰๏ธ Set(3) { 'bobby', 'hadz', 'com' }

create shallow copy of set

The code for this article is available on GitHub

We used the Set() constructor to create a shallow copy of a Set.

The only parameter the Set() constructor takes is an iterable, such as an array, string, or another Set.

Once the iterable is passed to the constructor, all of the unique values from the iterable are added to the new Set.

The new Set object has a completely different location in memory and adding elements to it wouldn't add elements to the original Set.

index.js
const set1 = new Set(['one', 'two', 'three']); const cloned = new Set(set1); console.log(cloned); // ๐Ÿ‘‰๏ธ {'one', 'two', 'three'} cloned.add('four'); console.log(cloned); // ๐Ÿ‘‰๏ธ {'one', 'two', 'three', 'four'} console.log(set1); // ๐Ÿ‘‰๏ธ {'one', 'two', 'three'}

The code sample demonstrates that adding elements to the copy doesn't add elements to the original Set object.

You can also use a simple for...of loop to create a shallow copy of a Set.

# Create a shallow Copy of a Set using a for...of loop

To create a shallow copy of a Set:

  1. Declare a new variable and initialize it to an empty Set.
  2. Use a for...of loop to iterate over the original Set.
  3. Use the add() method to add each element to the new Set object.
index.js
const set1 = new Set(['bobby', 'hadz', 'com']); const cloned = new Set(); for (const element of set1) { cloned.add(element); } console.log(cloned); // ๐Ÿ‘‰๏ธ Set(3) { 'bobby', 'hadz', 'com' }

create shallow copy of set using for of loop

The code for this article is available on GitHub

We declared a new variable and initialized it to an empty set using the Set() constructor.

The for...of statement is used to loop over iterable objects like arrays, strings, Map, Set and NodeList objects and generators.

On each iteration, we use the Set.add() method to add the current element to the new Set.

The Set.add() method inserts a new element with the supplied value into a Set object, if the value is not already in the Set.

The new Set object is stored at a completely different location in memory.

# Create a deep copy of a Set in JavaScript

To create a deep copy of a Set:

  1. Convert the Set to an array.
  2. Use the JSON.stringify() method to stringify the array.
  3. Use the JSON.parse() method to parse the string back into an array.
  4. Pass the result to the Set() constructor.
index.js
const existingSet = new Set([[1, 2, 3]]); const deepCopy = new Set(JSON.parse( JSON.stringify(Array.from(existingSet)) )); console.log(deepCopy); // ๐Ÿ‘‰๏ธ {[1, 2, 3]}
The code for this article is available on GitHub

We used the Array.from() method to convert the Set to a two-dimensional array.

index.js
const existingSet = new Set([[1, 2, 3]]); // ๐Ÿ‘‡๏ธ [ [1, 2, 3] ] console.log(Array.from(existingSet));

The next step is to use the JSON.stringify() method to convert the array to a JSON string.

index.js
const existingSet = new Set([[1, 2, 3]]); // ๐Ÿ‘‡๏ธ '[[1,2,3]]' console.log(JSON.stringify(Array.from(existingSet)));
Converting the array to a JSON string makes all of the nested arrays or objects lose their reference.

Then, we used the JSON.parse method to parse the string back into an array.

index.js
const existingSet = new Set([[1, 2, 3]]); // ๐Ÿ‘‡๏ธ [ [ 1, 2, 3 ] ] console.log(JSON.parse(JSON.stringify(Array.from(existingSet))));

The last step is to pass the two-dimensional array to the Set() constructor.

The trick here is to stringify the array, using the JSON.stringify method, so that all nested objects lose their reference.

If we then try to mutate the array in the new Set, it wouldn't affect the existing Set.

index.js
const existingSet = new Set([[1, 2, 3]]); const deepCopy = new Set(JSON.parse( JSON.stringify(Array.from(existingSet)) )); // ๐Ÿ‘‡๏ธ Mutate the nested array for (const item of deepCopy) { item.pop(); } console.log(deepCopy); // ๐Ÿ‘‰๏ธ {[1, 2]} console.log(existingSet); // ๐Ÿ‘‰๏ธ {[1, 2, 3]}

We used the pop method to mutate the array in the deep copied Set. However, notice that the array in the existing Set wasn't affected.

The nested arrays in the Sets have a different reference and location in memory because we used the JSON.stringify method.

# Create a deep copy of a Set using lodash

You can also use the lodash library to create a deep copy of a Set object.

First, install the lodash module if you haven't already.

shell
# ๐Ÿ‘‡๏ธ initialize a package.json file npm init -y npm install lodash

You can now import and use the lodash.cloneDeep() method.

index.js
import _ from 'lodash'; const existingSet = new Set([[1, 2, 3]]); const deepCopy = _.cloneDeep(existingSet); // ๐Ÿ‘‡๏ธ Set(1) { [ 1, 2, 3 ] } console.log(deepCopy);
The code for this article is available on GitHub

The cloneDeep method takes a value and recursively clones it, returning the deep cloned value.

If we then try to mutate the array in the new Set, it wouldn't affect the existing Set.

index.js
import _ from 'lodash'; const existingSet = new Set([[1, 2, 3]]); const deepCopy = _.cloneDeep(existingSet); for (const item of deepCopy) { item.pop(); } console.log(deepCopy); // ๐Ÿ‘‰๏ธ {[1, 2]} console.log(existingSet); // ๐Ÿ‘‰๏ธ {[1, 2, 3]}

The nested arrays in the Sets have a different reference and location in memory, so mutating the array in the copy doesn't mutate the array in the original Set.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.

Copyright ยฉ 2024 Borislav Hadzhiev