8 Ways to Clone Vue Object and Make It Non Reactive
Today, we are going to learn how to clone a reactive object into a non-reactive one, so we can use it in our application without worrying about its reactiveness.
Without further ado, let’s jump right in.
Table of Contents
What is Shallow Clone?
If you have a primitive data type let’s say, let x = 3, when you make a copy of it let y = x, that copy value ( 3 ) will point into a new memory address, which y variable pointing into.
Shallow clone is not going to create a real copy of reference data types. ( Object, Array, Function )
What is Deep Clone?
Deep clone simply duplicates all primitive and reference properties of the source object, and puts them into the target object. Cloned properties of the target object will point into a new memory address, which is going to be a real copy.
Shallow Clone vs Deep Clone
If you have an object that consists of only primitive data types ( String, Number, Boolean, undefined, BigInt, Symbol ), then you can shallow clone it to remove its reactivity.
Conversely, if you have an object consists of reference types, you can’t shallow clone it to remove its reactivity because it’s going to point to the same reference address in memory.
Think of it this way ( and excuse my terrific drawing skills ), if you have an original key (an object that consists of reference types ) that belongs to car1 ( reference address in the memory ) if you make a copy of it ( shallow clone ) that key is still going to belong into car1 ( same reference address in the memory ).
In other words, car1 will react to the cloned key, which is not what we want.
In that case, you should use a deep clone to remove the reactivity of your object. Which duplicates all properties of your object ( primitive and reference types ) and puts them into the target object, that target object will point into a new address in the memory.
Now that we took a glance at what shallow clone and deep clone are, let’s jump right into examples.
Shallow Clone Methods
Spread Operator
Using a spread operator is one of the easiest ways to clone our reactive object into a non-reactive one.
Object
const originalData = {item1: "one", item2: "two", item3: 3}
const clonedData = {...originalData}
Array
const originalData = ["one", 2, "three"]
const clonedData = [...originalData]
Object.assign()
With Object.assign( target, …sources ) we pass target object as a first parameter and source object ( or objects, we can put multiple objects as a source parameter,see here ), as a second parameter to achieve the expected result.
Object syntax
const originalData = {item1: "one", item2: "two", item3: 3}
const clonedData = Object.assign({}, originalData)
Array syntax
const originalData = ["one", 2, "three"]
const clonedData = Object.assign([], originalData)
slice() method
We can make use of slice method to return a shallow clone of our data without mutating it. This method only applies to arrays.
Array syntax
const originalData = ["one", 2, "three"]
const clonedData = originalData.slice();
Lodash library clone() method
Another way to copy our data is to use lodash library. This library is usually preferred for handling arrays, objects, numbers, strings, etc. operations and makes it easier to duplicate data.
Object syntax
const originalData = {item1: "one", item2: "two", item3: 3}
const clonedData = clone(originalData)
Array syntax
const originalData = ["one", 2, "three"]
const clonedData = clone(originalData)
JQuery.extend() method
Another alternative is to use JQuery.extend() method, although it is not commonly used, you might still consider it in your workflow.
Object syntax
const originalData = {item: "one", item2: "two", item3: "three"}
const clonedData = JQuery.extend({}, originalData)
Array syntax
const originalData = ["one", "two", "three"]
const clonedData = JQuery.extend([], originalData)
Deep Clone methods
Lodash library cloneDeep() method
Lodash library has cloneDeep() method to copy complex objects. Additionally, it copies with existing methods that the data includes.
const originalData = [
{
shoe: "Nike",
colors: {color1: "red", color2: "black", color3: "white"},
prices: [100, 125, 150],
logo: new Function(),
stock: 1000
},
{
shoe: "Adidas",
colors: {color1: "blue", color2: "green", color3: "pink"},
prices: [110, 135, 160],
logo: new Function(),
stock: 1500
},
{
shoe: "New Balance",
colors: {color1: "black", color2: "yellow", color3: "orange"},
prices: [100, 115, 150],
logo: new Function(),
stock: 1200
}
];
const clonedData = cloneDeep(originalData)
JSON.parse(JSON.stringify()))
If you want to use native JavaScript method, you can use JSON.parse(JSON.stringify()) method. But be warned, this approach is going to work as expected if your data consists of supported JSON data types. These are:
- String
- Number
- Boolean
- Null
- Object
- Array
Let’s take a look at working example.
const originalData = [
{
shoe: "Nike",
colors: {color1: "red", color2: "black", color3: "white"},
prices: [100, 125, 150],
stock: 1000,
warranty: true,
season: null
},
{
shoe: "Adidas",
colors: {color1: "blue", color2: "green", color3: "pink"},
prices: [110, 135, 160],
stock: 1000,
warranty: false,
season: null
},
{
shoe: "New Balance",
colors: {color1: "black", color2: "yellow", color3: "orange"},
prices: [100, 115, 150],
stock: 1000,
warranty: true,
season: null
}
];
const clonedData = JSON.parse(JSON.stringify(originalData));
console.log(clonedData)
As we can see, JSON.parse(JSON.stringify()) method works smoothly with supported data types.
For other data types, this approach could yield unexpected results.
Let’s see it in an example.
First, we are setting a Map object to diversify our example.
const mapInstance = new Map();
mapInstance.set({shoe: "Nike"}, 1000)
mapInstance.set( "stock", 1000)
mapInstance.set("logo", "blue")
This is what an experimental object looks like.
const testObject = {
item1: "ice cream", // String
item2: 2, // Number
item3: false, // Boolean
item4: null, // null
item5: { item: "one", item2: "two", item3: "three" }, // Object
item6: ["one", "two", "three"], // Array
item7: new Set([1, 2, 3, 4]), // Set Object
item8: undefined, // undefined
item9: Infinity, // Infinity
item10: new Function(), // Function
item11: new Date(), // Date Object
item12: mapInstance, // Map Object
item13: Symbol("mac and cheese") // Symbol
};
Here’s how it looks on a console.
If we try to clone it with JSON.parse(JSON.stringify()) method.
const clonedTest = JSON.parse(JSON.stringify(testObject))
console.log(clonedTest)
This is what we’re going to get as a result.
As we can see unsupported data types ignored completely or mutated unexpectedly.
JSON.parse(JSON.stringify()) method can be useful within certain scenarios, so use it with caution.
JQuery.extend(deep) method
If we use JQuery.extend() method with giving true as the first parameter, it’s going to deep clone the object.
Object syntax
const originalData = {
shoe: "Nike",
colors: {color1: "red", color2: "black", color3: "white"},
prices: [100, 125, 150],
logo: new Function(),
stock: 1000
}
const clonedData = JQuery.extend(true, {}, originalData);
Array syntax
const originalData = [
{
shoe: "Nike",
colors: {color1: "red", color2: "black", color3: "white"},
prices: [100, 125, 150],
logo: new Function(),
stock: 1000
},
{
shoe: "Adidas",
colors: {color1: "blue", color2: "green", color3: "pink"},
prices: [110, 135, 160],
logo: new Function(),
stock: 1500
},
{
shoe: "New Balance",
colors: {color1: "black", color2: "yellow", color3: "orange"},
prices: [100, 115, 150],
logo: new Function(),
stock: 1200
}
];
const clonedData = JQuery.extend(true, [], originalData);
Conclusion
As you can see, there’s plenty of ways to clone our reactive object into a non-reactive one. Use whichever works best for you.
Although, we can write a native script to deep clone our object. it’s the topic of another post.
Thank you for reading this far! Have a nice day.
#block #css #display #google-fonts #inline #inline-block #local-fonts #none #vue-3 #vue-3-project-setup #vue-cli-4 #vuejs