1

Starting from a 2 dimensional array M

let M = [[1,1],[1,1]];

I would expect the code

let N = Object.assign([], M);

to create a copy of M. In other words to my understanding of Object.assign I should now have two identifiers M,N pointing to different locations in memory, with both locations containing the same 2-dimensional array.

However when I mutate an entry of N, the same entry in M changes as well:

N[0][0] = 0;

console.log(N);
console.log(M);

gives

> Array [Array [0, 1], Array [1, 1]]
> Array [Array [0, 1], Array [1, 1]]

Why is that? A analog example works as expected if M is a list instead of a list of lists.

  • the inner arrays have the same object reference. the outer reference is gone. – Nina Scholz Nov 18 '20 at 17:36
  • Why do you use `Object.assign()` with an array? If you want a copy of an array use `.slice()` (or `Array.from()`, `...` spread syntax, ...) – Andreas Nov 18 '20 at 17:37
  • As you said *with both locations containing the same 2-dimensional array* that means that `N[0] === M[0]` so any modifications to the object `N[0]` references to will be reflected in `M[0]` – Titus Nov 18 '20 at 17:41
  • 1
    `Object.assign` creates a **shallow** copy of the object not a **deep** one. If you mutate `N` itself (like `N.push(7)`), `M` won't be affected, but if you mutate the inner arrays (which are not cloned), the change will be reflected in `M` too, because `N` and `M` are two different arrays that contain the same inner arrays. – ibrahim mahrir Nov 18 '20 at 17:44
  • *However when I mutate an entry of N, the same entry in M changes as well* that is not true, you're mutating an entry in `N[0][0]`, if you modify `N[0]`, you'll get a different result. – Titus Nov 18 '20 at 17:44
  • Full, community discussion here: [What is the most efficient way to deep clone an object in JavaScript?](https://stackoverflow.com/questions/122102/what-is-the-most-efficient-way-to-deep-clone-an-object-in-javascript) – pilchard Nov 18 '20 at 17:49
  • thx all, that helped a lot! – Peter Guthmann Nov 18 '20 at 18:34

1 Answers1

1

I tried Array.from() as Andreas suggested, didn't make it work.

I finished creating a deep copy in a custom method:

export function copy(array: any[]): any[] {
    const result = Object.assign([], array)
    for (let [key, val] of Object.entries(result)) {
        if (Array.isArray(val)) {
            result[key] = copy(val)
        }
    }
    return result;
}
Guillermo
  • 71
  • 4