0

I'm trying to add a unique ID to a bunch of array items in my project but came across an extremely weird issue that I cannot seem to reproduce in CodeSandbox. It seems to be unique to my project.

weekarr.forEach((a, q) => {
  a.forEach((b, w) => {
    console.log(`${q} + ${w}`);
    b.id = `${q} + ${w}`;
  });
});

This is the loop that I am running. In the console you see this:

0 + 0
0 + 1
0 + 2
0 + 3
0 + 4
0 + 5
0 + 6
0 + 7
0 + 8
0 + 9
0 + 10
0 + 11
1 + 0
1 + 1
1 + 2
1 + 3
1 + 4
1 + 5
1 + 6
1 + 7
1 + 8
1 + 9
1 + 10
1 + 11
2 + 0
2 + 1
2 + 2
2 + 3
2 + 4
2 + 5
2 + 6
2 + 7
2 + 8
2 + 9
2 + 10
2 + 11
3 + 0
3 + 1
3 + 2
3 + 3
3 + 4
3 + 5
3 + 6
3 + 7
3 + 8
3 + 9
3 + 10
3 + 11

That's completely perfect. But when I go ahead and check b.id in every array. This is what I see for the first array of each of every array:

3 + 0
3 + 0
3 + 0
3 + 0

This is what it should have been instead:

0 + 0
1 + 0
2 + 0
3 + 0

I cannot seem to be able to reproduce this problem in anyway. It only seems to happen with the particular array that I made. I've tried to push the array into a fresh empty array and the problem still stays. I'm not sure if it's React causing this, or some weird javascript bug. Can anyone help me?

EDIT: Picture of the array:

Array

rago182
  • 185
  • 2
  • 15
  • 2
    Are all the elements in your array somehow referring to the same `Object`? – XCS Jan 01 '20 at 23:39
  • Interesting point. I didn't know arrays referred to Objects. I thought they stored Objects. The elements in the array are copied from a blueprint Object. So yes, they are. Is this a problem? And how can I fix this? – rago182 Jan 01 '20 at 23:41
  • 2
    Everything (except primitives such as numbers) in JavaScript is stored/copied by reference unless you specifically copy the Object. It depends on how you create your array, could you post what the `weekarr` array contains? – XCS Jan 01 '20 at 23:42
  • It's an extremely long array that consists of a bunch of Objects. I'll take a screenshot and add it to OP. – rago182 Jan 01 '20 at 23:45
  • 1
    Your Array contains references to 4 other Arrays. From the screenshot it actually looks like those 4 reference actually point to the same Array, so you are just always modifying that array in the loop. You should first create copies of your 4 Arrays. – XCS Jan 01 '20 at 23:49
  • Genius! Can you point me to the right direction on how to copy arrays instead of referencing them? I used Array.push() method everytime. – rago182 Jan 01 '20 at 23:51
  • `const arr = [1,2,3,4,5]; const arr_copy = arr.slice(0);` – Jhecht Jan 01 '20 at 23:53
  • 1
    Cloning `Objects` in JavaScript is not an easy task. You can read some tutorials on this such as https://scotch.io/bar-talk/copying-objects-in-javascript or https://stackoverflow.com/questions/728360/how-do-i-correctly-clone-a-javascript-object – XCS Jan 02 '20 at 00:08
  • Thank you guys! Got it to work thanks to you! – rago182 Jan 02 '20 at 00:33

1 Answers1

0

The comments above are correct - you are updating references that point to the same object. Here's a potential solution that clones the inner array and it's objects in-place. It uses Object.create which has solid browser support (all modern browsers, IE 9+).

The only caveat here is that it creates a new object which prototypically inherits from the original. That being said, properties are all still accessible just as they would be if inheritance wasn't in play. i.e., weakarr[0][0].html still works even though you're creating a child object.

<pre>
weekarr.forEach((a, q) => {
  let newarr = [];
  a.forEach((b, w) => {
    console.log(`${q} + ${w}`);
    let c = Object.create(b);
    c.id = `${q} + ${w}`;
    newarr.push(c);
  });
  weakarr[q] = newarr;
});
</pre>
g_param
  • 156
  • 5