Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue changes array in data after making a copy of it

So I have this code in vue:

export default {
 name: 'Test',
  data() {
    return {
      test1: ['1', '2', '3'],
      test2: [{
        name: 'Hello'
      }, {
        name: 'Number two'
      }, {
        name: 'What ever'
      }], 
     };
  },
 created() {    
    const first = [...this.test1];
    first.forEach((elm, index) =>  first[index] = 'New');
    console.log('first: ', first);
    console.log('test1 in data', this.test1);

    const second = [...this.test2];
    second.forEach(elm => elm.name = 'New');
    console.log('second: ', second);
    console.log('test2 in data', this.test2);
  },
}

After setting the value of each item of the array 'first' (that should be a copy without reference to the data 'test1' array) each item is equal to 'new'. The value of this.test1 doesn't change.

I did the same with test2. Copied and changed the value of each item to 'New'. But now the value of the data array 'test2' also has 'New' in every item.

I have no clue why this is like that. Any ideas?

like image 458
Micha Avatar asked Feb 21 '19 07:02

Micha


2 Answers

Spread syntax creates a shallow copy. If your array has primitive types like numbers or strings, it won't update the original array. That's the case with test1. In the second case, only a new array is created. If you push or pop from the array, original array won't be updated. But, the objects are still pointing to their same place in memory. Updating them will update original array's objects as well.

You can use the spread syntax on the individual object to create a copy of the objects:

const second = this.test2.map(o => ({...o}))

You can also use JSON.parse and JSON.stringify. But, if the objects have any function properties, they'll be removed.

const second = JSON.parse(JSON.stringify(this.test2))
like image 140
adiga Avatar answered Nov 16 '22 08:11

adiga


The reason it is like that is because you are having an array of Vue data values. So even though you are cloning the Array, you are also copying over each values 'getters' and 'setters' which have a reference to the original array. In order to remove the getters and setters you should do what d-h-e has suggested.

You could also do this.

    const second = this.test2.map(() => { name: 'New' } );
    console.log('second: ', second);
    console.log('test2 in data', this.test2);
like image 44
Miguel Coder Avatar answered Nov 16 '22 10:11

Miguel Coder