DEV Community

Jeet Bhalani
Jeet Bhalani

Posted on

Wanna copy Data Objects? Shallow copy And Deep copy are the ways: In JS

__In JavaScript, Data can be divided into two main categories which are primitivedata types and reference data types. The word data here refers to all the collection of Array, strings and objects which are mostly used to store data in js.

If you don't know what are they no worries here's a link to get some more knowledge ____

1. Primitive data types:

The value assigned to a primitive data type variable is strongly tied. This means that anytime you replicate a basic data type variable, the value is transferred to a new memory address that the new variable points to. It will be a true copy if you make a copy.

2. Reference data types:

Whereas, for reference data type it stores the address of the memory location where the object is stored. There are two types of copying reference data types namely shallow copy and deep copy.

Shallow copy:

A shallow copy just points to the reference address of the original collection structure (object or array) that carries the value in the new variable; that is, only the collection structure is copied, not the element.

When the field value is a reference type it just copies the reference address, no new object will be created. The referenced objects are thus shared.

let Obj1 = {name: "apple", type: "fruit"};
let clonedObj = obj1;
clonedObj.name = ‘orange’;

// Output:
clonedObj = {name: “orange”, type: “fruit”}
obj1 = {name: “orange”, type: “fruit”}
Enter fullscreen mode Exit fullscreen mode

Shallow copy is simple and typically cheap, as they can be usually implemented by simply copying the reference address. Similarly, this can be observed for arrays.

let arr = [1,2,3];
let clonedArr = arr;
clonedArr.push(4);

// Output:
clonedArr = [1,2,3,4]
arr = [1,2,3,4]
Enter fullscreen mode Exit fullscreen mode

However, there are methods for copying objects without referencing them.

1. Spread operator (…)

It is a convenient way to make a shallow copy of an array or object —when there is no nesting, it works great.

It is useful for creating new instances of arrays that do not behave unexpectedly due to old references.

let Obj1 = {name: "apple"};
let clonedObj = {...obj1};
clonedObj.name = ‘orange’;

// Output:
clonedObj = {name: “orange”}
obj1 = {name: “apple”}

Enter fullscreen mode Exit fullscreen mode

2. Object.assign().

It copies enumerable properties from a source object to a target object. Further, this can be used only if the object/array contains primitive type values.

let Obj1 = {name: "apple"};
let clonedObj = Object.assign({}, obj1);
clonedObj.name = ‘orange’;

// Output:
clonedObj = {name: “orange”}
obj1 = {name: “apple”}

Enter fullscreen mode Exit fullscreen mode

3. Slice().

For arrays specifically, using the built-in .slice() method works the same as the spread operator — creating a shallow copy of one level:

let arr = [1,2,3,4,5]
let clonedArr = arr.slice();
clonedArr.push(6);

//Output:
arr = [1, 2, 3, 4, 5]
clonedArr = [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

4. Array.from().

Another method to copy a JavaScript array is using Array.from()which will also make a shallow copy.

let arr = [1,2,3,4,5]
let clonedArr = Array.from(arr);
clonedArr.push(6);

// Output:
arr = [1, 2, 3, 4, 5]
clonedArr = [1, 2, 3, 4, 5, 6]
Enter fullscreen mode Exit fullscreen mode

These techniques will copy up to the first level. Because nested objects are not truly cloned, the internally copied reference type value for any nested object or array will refer to its memory address, causing shallow copies to operate unexpectedly. To overcome this, we must iterate and copy until we reach the final level, whereas this method is costly and not recommended. A deep copy will be required for objects that are deeply nested.

Deep copy

It simply creates a duplicate of all the properties of the source object into the target object. In other words, both the primitive type and reference type properties will be allocated to new memory locations.

Image description

The correct term to use would be cloning, where you know that they both are totally the same, but yet different (i.e. stored as two different entities in the memory space).

It is used to copy JavaScript objects to a new variable NOT by reference.

const nestedArray = [["4"] ,["9"] ,["7"]];

const nestedCopyWithSpread = [...nestedArray];

console.log(nestedArray[0] === nestedCopyWithSpread[0]); 
// true -- Shallow copy (same reference)

const nestedCopyWithJSON = JSON.parse(JSON.stringify(nestedArray));

console.log(nestedArr[0] === nestedCopyWithJSON[0]);
// false -- Deep copy (different references)

Enter fullscreen mode Exit fullscreen mode

The strict equality operator (===)shows that the nested references are the same for shallow copy and different for deep copy.

There are many methods of making a deep copy (or deep clone):

1. JSON.parse/stringify.

It helps in parsing a stringified Object and vice versa.


let originalObj = {name: “apple”, price: {chennai: 120}};

let clonedObj = JSON.parse(JSON.stringify(originalObj));
clonedObj.name =”orange”;

clonedObj.price.chennai = “34”;

// Output:
clonedObj = {name: “orange”, price: {chennai: 100}}
originalObj = {name: “apple”, price: {chennai: 34}}
Enter fullscreen mode Exit fullscreen mode

2. Lodash.

It is a JavaScript library that provides multiple utility functions and one of the most commonly used functions of the Lodash library is the cloneDeep() method. This method helps in the deep cloning of an object and also clones the non-serializable properties which were a limitation in the JSON.stringify() approach.

Of the various copy algorithms, the shallow copies are the fastest, followed by deep copies using a custom function

Conclusion

In JavaScript, it's actually quite simple to avoid having to deep copy if you never nest objects and arrays inside each other. Because in that scenario — where there is no layering and the objects and arrays just contain primitive values — producing a shallow copy using the spread operator (...),.slice(), and.assign() all function perfectly.

However, in the actual world, where objects contain arrays or vice versa, a deep copy will be required.

Top comments (0)