Javascript pushing objects into array changes entire array

I'm using a specific game making framework but I think the question applies to javascript

I was trying to make a narration script so the player can see "The orc hits you." at the bottom of his screen. I wanted to show the last 4 messages at one time and possibly allow the player to look back to see 30-50 messages in a log if they want. To do this I set up and object and an array to push the objects into.

So I set up some variables like this initially...

servermessage: {"color1":"yellow", "color2":"white", "message1":"", "message2":""},
servermessagelist: new Array(),

and when I use this command (below) multiple times with different data called by an event by manipulating servermessage.color1 ... .message1 etc...

servermessagelist.push(servermessage)

it overwrites the entire array with copies of that data... any idea why or what I can do about it.

So if I push color1 "RED" and message1 "Rover".. the data is correct then if I push color1"yellow" and message1 "Bus" the data is two copies of .color1:"yellow" .message1:"Bus"

Answers:

Answer

When you push servermessage into servermessagelist you're really (more or less) pushing a reference to that object. So any changes made to servermessage are reflected everywhere you have a reference to it. It sounds like what you want to do is push a clone of the object into the list.

Declare a function as follows:

function cloneMessage(servermessage) {
    var clone ={};
    for( var key in servermessage ){
        if(servermessage.hasOwnProperty(key)) //ensure not adding inherited props
            clone[key]=servermessage[key];
    }
    return clone;
}

Then everytime you want to push a message into the list do:

servermessagelist.push( cloneMessage(servermessage) );
Answer

When you add the object to the array, it's only a reference to the object that is added. The object is not copied by adding it to the array. So, when you later change the object and add it to the array again, you just have an array with several references to the same object.

Create a new object for each addition to the array:

servermessage = {"color1":"yellow", "color2":"white", "message1":"", "message2":""};
servermessagelist.push(servermessage);
servermessage = {"color1":"green", "color2":"red", "message1":"", "message2":"nice work"};
servermessagelist.push(servermessage);
Answer

servermessagelist: new Array() empties the array every time it's executed. Only execute that code once when you originally initialize the array.

Answer

I also had same issue. I had bit complex object that I was pushing in to the array. What I did; I Convert JSON object as String using JSON.stringify() and push in to the Array.

When it is returning from the array I just convert that String to JSON object using JSON.parse().

This is working fine for me though it is bit far more round solution. Post here If you guys having alternative options

Answer

I do not know why a JSON way of doing this has not been suggested yet. You can first stringify the object and then parse it again to get a copy of the object.

let uniqueArr = [];
let referencesArr = [];
let obj = {a: 1, b:2};

uniqueArr.push(JSON.parse(JSON.stringify(obj)));
referencesArr.push(obj);

obj.a = 3;
obj.c = 5;
uniqueArr.push(JSON.parse(JSON.stringify(obj)));
referencesArr.push(obj);

//You can see the differences in the console logs
console.log(uniqueArr);
console.log(referencesArr);

Answer

This solution also work on the object containing nested keys.

Before pushing, stringify the obj by

JSON.stringify(obj)

And when you are using, parse by

JSON.parse(obj);
Answer

There are two ways to use deep copy the object before pushing it into the array. 1. create new object by object method and then push it.

servermessagelist = []; 
servermessagelist.push(Object.assign({}, servermessage));
  1. Create an new reference of object by JSON stringigy method and push it with parse method.

    servermessagelist = []; servermessagelist.push(JSON.parse(JSON.stringify(servermessage));

This method is useful for nested objects.

Answer

As mentioned multiple times above, the easiest way of doing this would be making it a string and converting it back to JSON Object.

this.<JSONObjectArray>.push(JSON.parse(JSON.stringify(<JSONObject>)));

Works like a charm.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.