Reputation: 8970
I have a result set which is an array of objects. I need to clone this so I can make changes to it, without touching the original data.
var data = w2ui.grid.records,
exclude = Array('recid', 'w2ui'); // Exclude these data points from the pivot
// Modify our tempData records to remove HTML
$.each(data, function(key, value) {
$.each(value, function(_key, _value) {
if(jQuery.inArray(_key, exclude) != -1) {
delete data[key][_key];
}else{
data[key][_key] = $('<div>'+_value+'</div>').text(); // <div></div> for those which are simply strings.
}
});
});
In this example, I created a variable called data
and set it to my "Source Data".
I expected to be able to make changes to this new data variable but it appears that when making changes to it, the source data is being changed (w2ui.grid.records
).
Is there a proper way to clone this set so I can have a new instance of the data to modify?
Upvotes: 15
Views: 37626
Reputation: 1
The modern way to deep copy an array of objects in JavaScript is to use structuredClone:
const arr1 =[{'obj1':1}, {'obj2':2}];
const arr2 = structuredClone(arr1); //copy arr1
arr2.push({'obj3':3});
console.log(arr1); //[{'obj1':1}, {'obj2':2}]
console.log(arr2); //[{'obj1':1}, {'obj2':2}, {'obj3':3}]
Upvotes: 5
Reputation: 31
below code worked for me to deep Clone an array of object which does not have any function stored in them.
const deepClone = input => {
if (typeof input !== 'object') return input;
const output = Array.isArray(input) ? [] : {};
const keys = Object.keys(input);
keys.forEach(key => {
output[key] = deepClone(input[key]);
});
return output;
};
Upvotes: 1
Reputation: 11859
Since you are using jquery you can try extend
:
var arr = [{'obj1':1}, {'obj2':2}];
var clone = jQuery.extend(true, [], arr);
clone[0]['obj1']=10;
console.log(clone);
console.log(arr);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Upvotes: 3
Reputation: 417
ES6:
If you want to have cloned objects too, you have to spread array and objects:
const newArrayOfObjects = [
...originalArrayOfObject
].map(i => ({ ...i}));
Upvotes: 14
Reputation: 333
You can achieve this from ES6 spread operators
var arr1 = [1]
var arr2 = arr1
arr1 === arr2 //true
arr2.push(2)
arr2 //[1, 2]
arr1 //[1, 2]
var arr3 = [...arr1] //create a copy of existing array
arr1 === arr3 //false
arr2 === arr3 //false
arr3.push(3)
arr3 //[1, 2, 3]
arr1 //[1, 2]
arr2 //[1, 2]
Same syntax can be used for javascripts object as well
var newObj = [...existingObj]
Upvotes: -1
Reputation: 24130
There are various ways to do it-
let arr = [{
'obj1': 1
}, {
'obj2': 2
}];
// 1
const arr2 = arr.slice();
console.log(arr2);
// 2
const arr3 = [].concat(arr);
console.log(arr3);
// 3
// or use the new ES6 Spread
const arr4 = [...arr];
console.log(arr4);
// 4
const arr5 = Array.from(arr);
console.log(arr5);
Upvotes: 0
Reputation: 749
This is because an array is held as a pointer, so setting a new variable just points to the same array.
The easiest way I know of is with slice...
var data = w2ui.grid.records.slice(0);
This creates a new array with all of the original values in, because you're slicing from the first one (0).
If you need a deep clone, because your array contains objects/arrays too, try this...
https://github.com/pvorb/clone
Upvotes: 1
Reputation: 43880
EDIT
Deep clone use JSON.parse(JSON.stringify(arr));
Shallow clone Use slice(0);
var arr = [{'obj1':1}, {'obj2':2}];
var clone = arr.slice(0);
console.log(clone);
var arr = [{'obj1':1}, {'obj2':2}]
var clone = JSON.parse(JSON.stringify(arr));
console.log(clone);
Upvotes: 36
Reputation: 5302
Lodash has a method specifically for this called clonedeep
. There's a standalone package for it if you don't want to pull in the entire library:
https://www.npmjs.com/package/lodash.clonedeep
Upvotes: 1