1

This seems so simple in my head but I can't seem to get the correct output. All I'm trying to do is run through a list of data and assign an object property with another object like so

{
  Foo: {
    firstname: "sally",
    lastname: "jenkins"
  },
  Bar: {
    firstname: "john",
    lastname: "smith"
  }
}

however with this code every element in the object gets assigned the same values.

let formInfo = {}
let spriteAndId = {}
forms.forEach((form) => {
  spriteAndId["id"] = parseInt(form.pokemon.url.substr(form.pokemon.url.length - 6), 10);
  spriteAndId["url"] = spriteUrlGen(spriteAndId["id"]);
  formInfo[form.pokemon.name] = spriteAndId;
})

I apologize if that is hard to understand but all it does is assign a url ("https://example.com") and id (1234) to the empty object spriteAndId. The variable forms is an array with data already in it.

If I log spriteAndId in the loop I get the correct output with brand new values on each iteration, but it seems it just assigns only one of those iterations to every element in the parent object.

I thought maybe I didn't understand forEach well enough so I implemented it using a for loop and got the same outcome. I can't wrap my head around why it would assign the same object to all the values of formInfo.

Hopefully someone can shed some light on what I'm missing here. Thanks in advance!

4
  • 1
    Object values are references to the object. Assigning does not make a copy. Move the initialization of spriteAndId to the inside of the loop. Commented Jul 16, 2018 at 17:00
  • @Pointy Does this have any performance hindrances as I'm assigning a new value per loop iteration? There's times where there's around 400 items in the array. And thank you so much! Will test it out right now Commented Jul 16, 2018 at 17:04
  • No; think about what performance would be like if assigning object references actually did make copies. Commented Jul 16, 2018 at 17:06
  • @Pointy Once again thank you so much, that did indeed do it and you cleared up so much. Take care Commented Jul 16, 2018 at 17:15

1 Answer 1

1
    const formInfo = Object.keys(form)
     .map(obj => ({
          [form[obj].name]: {
            id: form[obj].id,
            sprite: spriteUrlGen(form[obj].id)
           }
     }))
     .reduce((prev, curr) => ({ ...prev, curr }, {}))

If I understood what you are trying to achieve is a final form object with the name of the pokemon as key and the data (sprite and Id) as value. Object.keys() returns an array of all the properties of an object. You can them map over them and transform the data, in this case we are returning an object with the pokemon name as key and id, sprite as values. Notice the [] that enclose the key of the object, that is what makes the value dynamic, otherwise if you write hardcode the key it won't work. Now all these values have been mapped/transformed to objects, the reduce functions takes them all and encloses them in a single object, starting from {} an empty object

Sign up to request clarification or add additional context in comments.

1 Comment

You're spot on. Another way of doing things is never bad! I could use this for another spot with a similar problem. Thank you!!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.