• Skip to primary navigation
  • Skip to main content
  • Skip to primary sidebar

Justin Joyce

Practical tips and tutorials about software development.

  • Standing Invitation
  • Featured Posts
  • Latest
  • About

Copy an object in Javascript

Posted Oct 14, 2023 โ€” Updated Jan 10, 2024

There are several ways to copy an object in Javascript, and they fall into two categories: shallow copies and deep copies. Before going deeper, it might be helpful to define the two:

  • Shallow copy: a copy of an object which shares references with the original. Modifying properties on either object might affect both.
  • Deep copy: a copy of an object which is entirely independent from the original. Modifying either object will not affect the other.

If you’re copying a simple Javascript object with top-level properties only, all copies will be deep copies, regardless of what method you use. If you have an object with nested properties, however, then you need to be more careful.

Let’s see some examples using a very common shallow-copying method, spread syntax:

// Simple, top-level properties only
const original = { name: "justin", age: 100 };
const copied = { ...original };

// These changes will not affect the original
copied.name = "frank";
copied.age = 50;

console.log(original);
// { name: "justin", age: 100 }

The two objects above are independent. Changing one has no effect on the other because those are all “top-level” properties; there are no nested values.

Here’s a more complicated example, where the objects are not independent:

// The "first" name property is now nested inside another object
const original = { name: { first: "justin" }, age: 100 };
const copied = { ...original };

// This change will affect both objects, this property is nested
copied.name.first = "frank";

// This change will NOT affect both, it isn't a nested property
copied.age = 50;

console.log(original);
// {name: {first: "frank"}, age: 100}

cosole.log(copied);
// {name: {first: "frank"}, age: 50}

In this example, changing a value on a nested property changed the value for both objects. That’s because when copying nested objects, javascript copies them by reference1, rather than creating entirely new objects.

Note: this holds true for Javascript Arrays also, since arrays are just objects. An array containing only top-level numbers or strings will always be deep copied. An array containing objects (or sub-arrays) will have each of those nested objects passed by reference unless you explicitly deep copy them.

Now that we have that explained, let’s move on to common copying methods.

Shallow Copies

Here are the common ways people shallow copy objects in JS:

Spread syntax

This is by far the most commonly-used method:

const original = { name: "justin", job: "dev" };
const copy = { ...original };

// You'll often see this with some properties overridden
const copyTwo = {...original, name: "joyce" };

// You can combine multiple objects
const copyThree = {
  ...original,
  ...another,
  ...somethingElse,
};

Object.assign

const original = { name: "justin", job: "dev" };
const copy = Object.assign({}, original)

// You override properties here too
const copyTwo = Object.assign({}, original, { name: "joyce" });

// You can combine multiple objects this way also
const copyTwo = Object.assign({}, original, another, somethingElse);

Array.concat

const one = [1];
const two = [{ two: 2 }];

// merged will be shallow
const merged = one.concat(two); // [ 1, { two: 2} ]

// this change will affect array 'two' also
merged[1].three = 3;

console.log(two); // [{ two: 2, three: 3 }]

The other common array methods also create shallow copies: Array.from() and Array.prototype.slice().

Deep Copies

The only surefire way to create a deep copy in javascript (without a library) is via the built-in JSON module.

const original = { name: { first: "justin", last: "joyce" }};
const copy = JSON.parse(JSON.stringify(original));

// 'copy' is now a completely independent object
// changing it will not affect the original
copy.name.first = "Tom";

console.log(original.name.first);
// "justin"

The JSON method requires that your original object is fully string-serializable, which is not always the case. Functions, for example, cannot be serialized via JSON, and won’t be copied this way:

const original = { func: () => console.log("hi"), name: "justin" };
const copy = JSON.parse(JSON.stringify(original));

// The 'func' param will be lost
console.log(copy);
// { name: "justin" }

In cases like this one, you might want to use a library function like lodash cloneDeep.


Helpful Links

  • For more on the limitations of deep-copying via JSON, head over to the Moz Docs.

Notes

  1. It’s essentially passing a pointer reference โ†ฉ๏ธŽ

Filed Under: Javascript

Primary Sidebar

Recent Posts

  • Every Built-In Vim Color Scheme (with screenshots)
  • Reverse a string in Python
  • Meeting Cost Calculator
  • Vim find and replace
  • What makes an effective development team

Categories

  • Arrays (5)
  • Command Line (9)
  • Dates (3)
  • Featured (7)
  • Git (7)
  • Golang (5)
  • Javascript (8)
  • Productivity (8)
  • Projects (4)
  • Python (15)
  • Regex (2)
  • Ruby (3)
  • Shell (2)
  • Thoughts (2)
  • Tips (11)
  • Tools (3)
  • Tutorials (1)
  • Vim (4)

Archives

  • July 2024 (1)
  • February 2024 (1)
  • January 2024 (1)
  • December 2023 (1)
  • November 2023 (1)
  • October 2023 (4)
  • September 2023 (1)
  • August 2023 (2)
  • July 2023 (5)
  • June 2023 (3)
  • May 2023 (6)
  • April 2023 (5)
  • March 2023 (5)
  • February 2023 (10)
  • January 2023 (6)
  • December 2022 (7)

Copyright © 2025 ยท Contact me at justin [at] {this domain}

  • Privacy Policy