# How to properly clone a JavaScript object

In this article, we'll explore two common approaches to cloning an object: **shallow** cloning and **deep** cloning. We'll explain the differences between these methods, the benefits, and limitations of each, and provide examples of how to implement them in your code. Additionally, we'll discuss a modern, native JavaScript solution to deep cloning objects called `structuredClone`, let’s get into it!

## Shallow cloning

When making a shallow copy of an object, you create a duplicate that shares references with the original. In other words, the properties of the copy point to the same underlying values as those of the original object. As a result, changes made to either the copy or the original can affect the other.

It's worth noting that while shallow copies can be useful for certain purposes, they have some limitations. For example, if the original object contains nested objects or collections, changes to these may not be reflected in the shallow copy. In such cases, you may need to consider using a deep copy, which creates a completely independent duplicate of the original object, including all of its nested components.

Creating a shallow copy of an object it’s pretty straightforward in ES6:

**With Object.assign**

```jsx
const source = { name 'fer-codes' };

const cloned = Object.assign({}, obj);
```

**With the spread operator:**

```jsx
const source = { name 'fer-codes' };

const cloned = { ...source };
```

What if we need the source and the copy to be completely independent?

## Deep cloning an object

When a deep copy is made, the resulting copy behaves entirely independently from the source object. This means that any changes made to the original object will not affect the deep copy, and vice versa.

### **Naive approach - Stringify it!**

Perhaps you've come across the suggestion that a "quick and easy" solution for creating a deep clone of an object is to use `JSON.stringify` :

```jsx
const source = { name: 'fer-codes' }

const cloned = JSON.parse(JSON.stringify(source));

console.log(source === cloned) // false
```

Using JSON.stringify to create a deep clone of an object can be effective, but there are certain limitations and potential issues to be aware of. In particular, this method may not work as expected when dealing with certain data types, such as functions, date objects, undefined values, Infinity, and regular expressions.

To illustrate these limitations, let's take a look at how the method behaves when these values are present:

```jsx
const source = {
  boolean: true,
  string: 'string',
  number: 123,
  und: undefined,  // lost
  foo: () => {},  // lost
  date: new Date(),  // stringified
  inf: Infinity,  // forced to 'null'
}

const clone = JSON.parse(JSON.stringify(a));

console.log(typeof source.date);  // Date object
console.log('cloned', clone.date); // stringified version

console.log(typeof source.foo);  // () => { }
console.log('cloned', clone.foo); // undefined
```

### Modern solution - structuredClone

The `structuredClone` method is a modern, native JavaScript solution for deep cloning objects that simplifies what was once a complex task.

```jsx
const source = { name: 'fer-codes' }

const cloned = structuredClone(source)

console.log(source === cloned) // false
```

Although the `structuredClone` method overcomes many of the limitations associated with `JSON.stringify`, it still has some limitations of its own. Specifically, if the object you're attempting to clone includes a `function` or a non-cloneable data type (such as DOM nodes), `structuredClone` will throw an error.

```jsx
const source: { method: () => {} }

const cloned = structuredClone(source);
// Error: could not be cloned.

const a = document.createElement('a')
const elements = { anchor: a }

const clonedElements = structuredClone(source);
// Error: could not be cloned.
```
