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??

4
  • 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. Commented Aug 20, 2022 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. Commented Aug 20, 2022 at 15:22
  • Once you realise what the above comments say and it sinks in, you'll probably want to delete the question ;-) Commented Aug 20, 2022 at 15:26
  • Ahh thats right, spreading the object into a new one is only a shallow copy, thanks guys. Commented Aug 21, 2022 at 0:00

1 Answer 1

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;
}
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the deep copy function, that is where I went wrong, thanks mate.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.