SBB
SBB

Reputation: 8970

How to clone a Javascript Array of Objects?

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

Answers (9)

XMehdi01
XMehdi01

Reputation: 1

structuredClone

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

arfath77
arfath77

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

Suchit kumar
Suchit kumar

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

Remownz
Remownz

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

Arun Kumar
Arun Kumar

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

WitVault
WitVault

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

Rik Lewis
Rik Lewis

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

zer00ne
zer00ne

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

monners
monners

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

Related Questions