0

I am trying to remove an object from an array.So that I used splice but before splice I made a copy of an object

this.program.lstProgramdetails.forEach((lph: any) => {
            this.rtGridUp = Object.assign({}, lph);
            this.rtGridMid = Object.assign({}, lph);
            this.rtGridDown = Object.assign({}, lph);
            lph.Details.forEach((inm: any, index: number) => {              
                if (inm.Track !== null && inm.Track.TrackDateIn !== null) {
                    this.rtGridMid.Details.splice(index, 1);
                    this.rtGridDown.Details.splice(index, 1);
                } else if (inm.Track === null) {
                    this.rtGridUp.Details.splice(index, 1);
                    this.rtGridDown.Details.splice(index, 1);
                } else {
                    this.rtGridUp.Details.splice(index, 1);
                    this.rtGridMid.Details.splice(index, 1);
                }
            });
                    });

based on the condition two of the arrays should be sliced and one should get object without splicing.

But watching in console it clears all the 3 arrays. Is there any possible way to splice that object without affecting the copy object?

Venkatvasan
  • 491
  • 3
  • 13
  • 1
    You are creating shallow copies. You either have to make a deep copy using recursion or if you only need copies of the `Details` array you can make shallow copies of it with array destructuring, e.g. `const copy = [...lph.Details]` – Tao Feb 14 '18 at 11:13
  • Another way to achieve what you want is to use a pure function like `slice` instead of creating "first level" copies of objects as nested objects remain references. – 3Dos Feb 14 '18 at 11:16
  • Could you pls elaborate. – Venkatvasan Feb 14 '18 at 11:17

1 Answers1

0

Explanation

The issue here is Object.assign({}, objectToClone) does create a copy of the object you'd like to clone but keeps references of nested objects

const objectToClone = { a: 'a', b: { b: 'b' } };
const clone = Object.assign({}, objectToClone);

clone.b.b = 'c';
console.log(objectToClone, clone);

As you can see, the object isn't deep cloned.

See the Is this a good way to clone an object in ES6? question for more details.

A pure function

A pure function is a function which calculates a new value without altering existing ones More details about pure and impure functions

So, to avoid side effects like you are experiencing here. One neat way to achieve this is to use a pure function like slice which returns a new value while splice alters it and its possible references.

A way to address the issue

this.program.lstProgramdetails.forEach((lph: any) => {
  lph.Details.forEach((inm: any, index: number) => {
    const keys = [null, null];
    if (inm.Track !== null && inm.Track.TrackDateIn !== null) {
      keys = ['rtGridMid', 'rtGridDown'];
    } else if (inm.Track === null) {
      keys = ['rtGridUp', 'rtGridDown'];
    } else {
      keys = ['rtGridUp', 'rtGridMid'];
    }

    // ES7 syntax
    this[keys[0]].Details = [
      ...lph.Details.slice(0, index),
      ...lph.Details.slice(0, index + 1)
    ];
    this[keys[1]].Details = [
      ...lph.Details.slice(0, index),
      ...lph.Details.slice(0, index + 1)
    ];

    // Or if you prefer
    this[keys[0]].Details = lph.Details.slice(0, index).concat(
      lph.Details.slice(0, index + 1)
    );
    this[keys[1]].Details = lph.Details.slice(0, index).concat(
      lph.Details.slice(0, index + 1)
    );
  });
});

This is a cool video explaining it showing ES6 syntax too

I didn't test this code snippet but simply wrote it for an explanation purpose.

I hope you'll find this answer helpful!

3Dos
  • 3,210
  • 3
  • 24
  • 37