1

Why does this show the same random number twice when you run it in your console?

    var arr = [[]];
    
    arr[0][0] =  Math.random();
    console.log(arr);
    
    arr[0][0] =  Math.random();
    console.log(arr);

I derived this root issue from another post, which was not getting much attention, and I'm wondering if anyone has a clear explanation of what's going on here. I know there are things you can do to make this work as expected, but I'm interested in knowing why it doesn't work as expected right now. It's acting as if console.log() waits until everything else is through to log anything.

Pointy
  • 405,095
  • 59
  • 585
  • 614
Aaron Plocharczyk
  • 2,776
  • 2
  • 7
  • 15
  • 2
    `It's acting as if console.log() waits until everything else is through to log anything.` That is *exactly* what is happening. Very astute observation! You can prove this to yourself by forcing the array into JSON and back: `console.log(JSON.parse(JSON.stringify(arr)));` –  Dec 31 '19 at 14:39
  • 1
    You're probably testing the code in an environment with an asynchronous `console.log()` mechanism (like Chrome). As you can see above, the code works as you'd expect. – Pointy Dec 31 '19 at 14:39
  • @Pointy which environment is asynchronous? it works all the same (synced) on Chrome, IE, Opera, what else left ? – mangusta Dec 31 '19 at 14:43
  • it seems to work proper for me in my browser – NappingRabbit Dec 31 '19 at 14:45
  • Interestingly, a duplicate of this question was pointed out [in the comments to the answer linked to in this question](https://stackoverflow.com/questions/59539987/math-random-when-used-in-loop-will-not-give-new-number/59545020#comment105259643_59545020). – Heretic Monkey Dec 31 '19 at 14:45
  • @mangusta Possibly older versions of those same browsers. [Newer versions of node](https://github.com/nodejs/node/issues/3524#issuecomment-151097761) have a synchronous console, AFAIK. –  Dec 31 '19 at 14:47
  • @Pointy It's not so much because the console is asynchronous but rather because it is lazy. It indicates that a reference has been logged, but it doesn't actually resolve the referenced value until someone expands it with the arrow icons. You can observe this with the following code: `var arr = [[]]; arr[0][0] = Math.random(); console.log(arr); setTimeout(() => { arr[0][0] = Math.random(); console.log(arr); }, 3000);` – JLRishe Dec 31 '19 at 14:48
  • @mangusta Firefox, Node, Safari? – Pointy Dec 31 '19 at 14:48
  • @JLRishe sure, it's an async-like effect but there are several possible explanations. The browsers in particular log the "structured" view of the array that can be expanded and collapsed, and that's probably linked to the actual object. Of course `.join()` or `JSON.stringify()` gets around that issue. – Pointy Dec 31 '19 at 14:49
  • 1
    @JLRishe it's fascinating to me that as the debuggers have gotten vastly better over the last 10 years, the facilities get that much more confusing to new developers. There are lots of duplicates about this issue. – Pointy Dec 31 '19 at 14:51

1 Answers1

1

The console.log shows a reference to the array, the moment you expand it it retrieves the latest array value with the latest Math.random() value.

The following demo shows this:

var test = [1,2,3];
console.log(test)

test.push(4)

console.log(test)

The preview shows the old values but when expanding the values it retrieves it using the pointer and thus gets the new values.

enter image description here

MaartenDev
  • 5,631
  • 5
  • 21
  • 33