-1

I'm working on a Angular 5 project and I can't seem to get array copies that aren't memory pointers. Or rather I can, but sometimes. and there's no distinguishing factor in my eyes to why one would work and another no.

Here's one that doesn't :

detailsOriginal = [
    {title: 's ', value: 'sd' },
    {title: 'yy : ', value: 'sdgf'},
    {title: 'yyy: ', value: 'sdgsed'},
    {title: 'hgjtgj : ', value: 'sqdgqsd'},
    {title: 'dsfs: ', value: 'sqdg'},
    {title: 'dsfds : ', value: 'sqdfgqds'},
    {title: 'q : ', value: '1sqdfg'},
    {title: 'qsdqsdqsd : ', value: 'sdqffgdsq'},
    {title: 'qsdqsd: ', value: 'qdsf'},
    {title: 'qs qsd: ', value: 'sqdqs'},
    {title: 'qsd: ', value: '2'}
];

treatInfoArray(selection){
  console.log(this.detailsOriginal);     // correct output. unaltered 
  let dt = this.detailsOriginal.slice(); // this suposedly copies rather
                                         // than creates a pointer...
  setTimeout(()=>{
    console.log('new var', dt);          // correct output. unaltered 
  },1);
  setTimeout(()=>{
    dt.forEach(x => {
      x.value = selection[x.value];
    });
  },20);
  setTimeout(()=>{
    console.log('modified', dt);                  // correct. modified.
  },50);
  setTimeout(()=>{
    console.log('original', this.detailsOriginal);// why the hell is this also modified??
  },55);
}

Is the issue that the splice is happening in a function rather than the root of the class, that it has to be a global variable?

tatsu
  • 2,316
  • 7
  • 43
  • 87
  • 1
    `.slice()` creates a *shallow* copy of the array. It's definitely a new array, but every value in it is a copy of the object reference from the other array. – Pointy Mar 13 '18 at 12:41
  • 1
    `slice` is only a shallow copy. Changing `dt` itself won't change the original, but mutating the elements of the copy will mutate the elements of the original, since the elements of each are the same objects. You'll need to do a deep-copy. – Carcigenicate Mar 13 '18 at 12:42
  • 2
    If you want to deep copy the array you can use `var array = JSON.parse(JSON.stringify(originalArray));`. Welcome to Hacking Javascript 101 – Phiter Mar 13 '18 at 12:43
  • @Phiter well said. and you're right, that solved it. – tatsu Mar 13 '18 at 13:00

3 Answers3

2

The fastest way of doing that is the lodash cloneDeep function.

Here is a benchmark of different methods.

ibenjelloun
  • 7,425
  • 2
  • 29
  • 53
1

This is happening because of the reference in JS when you set a new object or array equal to an existing array, it will not create a new one it will just reference to the existing one so to create a new array there are a couple of methods.. one of them on ES6 is using the spread operator

let dt = [...this.detailsOriginal];
Renzo Calla
  • 7,486
  • 2
  • 22
  • 37
-1

this worked for me.

const dt = JSON.parse(JSON.stringify(this.detailsOriginal));

from here : https://stackoverflow.com/a/23481096/4770754

I'm fine with my const being irreparably altered within my function I just don't want the original array to be touched.

the issue is it's an array of objects and object copies are pointers and pointers only no matter what unless you use JsonStringify.

It's the object's fault.

tatsu
  • 2,316
  • 7
  • 43
  • 87