0

I have a use case that I thought the Map object would be perfect for but there is confusing behaviour that appears to me as a bug, but Im after any information as to why this happens and possibly a solution to the behaviour.

For instance, say I have 2 objects:

const obj1 = { name: "John" };
const obj2 = { name: "Jane", age: 35 };

And I have defined and extra object for extra properties to add to both objects later:

const extProps = { gender: "unspecified", children: [] };

Create a new Map object and add the 2 objects:

const map = new Map();
map.set(obj1.name, obj1);
map.set(obj2.name, obj2);

Due to the objects being reference types I can assign the extra props like so:

Object.assign(obj1, { ...extProps });
Object.assign(obj2, { ...extProps });

Now I can get the values from the map using the keys like:

const johnObj = map.get("John");
const janeObj = map.get("Jane");

And the object have all the extra props like expected. The following statements update the individual objects in the map:

janeObj.gender = "female";
johnObj.age = 45;

Here is where the confusing behaviour I see is happening... If I add an entry to the children array of either objects, it updates both

johnObj.children.push("jack");
obj2.children.push("jenny");

name: "John"
gender: "unspecified"
children: ["jack", "jenny"]
age: 45

name: "Jane"
age: 35
gender: "female"
children: ["jack", "jenny"]

What am I missing??

Dreamystify
  • 125
  • 13
  • 4
    `Due to the objects being reference types I can assign the extra props` arrays are also objects and are reference types. You have just added the same object to these other objects. – Konrad Aug 20 '22 at 15:08
  • 3
    Every time you think you have found a bug in a programming language or its runtime, you have actually found a bug in your own program. Every time. – jarmod Aug 20 '22 at 15:22
  • Once you realise what the above comments say and it sinks in, you'll probably want to delete the question ;-) – trincot Aug 20 '22 at 15:26
  • Ahh thats right, spreading the object into a new one is only a shallow copy, thanks guys. – Dreamystify Aug 21 '22 at 00:00

1 Answers1

1

Like Konrad said in his comment, "arrays are also objects and are reference types". The issue is that the spread operator (...) only goes on level deep, so for the array in extProps, is it not copied, it is the same one. To solve this you can use a recursive function to "deep copy" an object.

Here is an example of a deep copy function:

const deepCopy = objIn => {

    if (typeof objIn !== 'object' || objIn === null) return objIn;

    let objOut = Array.isArray(objIn) ? [] : {};

    for (const key in objIn) {
        objOut[key] = deepCopy(objIn[key]);
    }
    return objOut;
}
Darwin Island
  • 141
  • 1
  • 3