5

In the following javascript snippet, why are elements in tedious and concise not equivalent when you run this snippet? I get /**ref:2**/ output for concise from the second element.

const tedious = [
  {},
  {},
  {},
  {},
  {},
  {},
  {},
  {},
  {},
];

const concise = new Array(9).fill({});

console.log(tedious);
console.log(concise);
leogoesger
  • 3,476
  • 5
  • 33
  • 71
Gallaxhar
  • 976
  • 1
  • 15
  • 28
  • Maybe the interpreter of this snippet does not fully support es6? Works fine for me using Chrome console... – maevadevs Jun 11 '18 at 23:06
  • Possible duplicate of [Array.prototype.fill() with object passes reference and not new instance](https://stackoverflow.com/questions/35578478/array-prototype-fill-with-object-passes-reference-and-not-new-instance) – Sebastian Simon Jun 11 '18 at 23:06
  • Not sure what you mean with “error” or “does not fully support es6”. Of _course_ snippets support ES6. How could they not? `/**ref:2**/` means “reference to element 2 of the array”, since the console feature of Stack Snippets can’t know whether you’ve got an infinitely nested structure, so instead the `ref` comments (and `id` comments which aren’t used in this case) are used. – Sebastian Simon Jun 11 '18 at 23:09

1 Answers1

9

Note: not sure what is happening in running a snippet, but that ref business does not happen in the real world

as per Xufox comment: /**ref:2**/ means “reference to element 2 of the array”, since the console feature of Stack Snippets can’t know whether you’ve got an infinitely nested structure, so instead the ref comments (and id comments which aren’t used in this case) are used

The real problem with

const concise = new Array(9).fill({});

IS that all 9 entries will "refer" to the same object - see the output

const concise = new Array(9).fill({}); // {} 
concise[0].a='hello world';
console.log(JSON.stringify(concise))

To better illustrate that, let's pass a non-empty object to fill with a random value

const concise = new Array(9).fill({random:Math.floor(Math.random() * 1000)});
console.log(JSON.stringify(concise))

Clearly, that object is created exactly once

Try

const concise = new Array(9).fill(0).map(() => ({}));

concise[0].a='hello world';
console.log(JSON.stringify(concise))

as the map callback is called once for each element, a new object is created each time

Or you can try

const concise = Array.from({length:9}, () => ({}));

concise[0].a='hello world';
console.log(JSON.stringify(concise))

the second argument to Array.from is a callback that is called once for each element, it's basically the same .map

And of course, thanks to @Slai, the above is even more simply

const concise = Array.from({length:9}, Object);

Compare the output of the "math random" code above with

const concise = Array.from({length:9}, () => ({random:Math.floor(Math.random() * 1000)}));
console.log(JSON.stringify(concise))
Jaromanda X
  • 53,868
  • 5
  • 73
  • 87
  • 1
    `/**ref:2**/` means “reference to element 2 of the array”, since the console feature of Stack Snippets can’t know whether you’ve got an infinitely nested structure, so instead the `ref` comments (and `id` comments which aren’t used in this case) are used. – Sebastian Simon Jun 11 '18 at 23:14
  • Fair enough, what stack snippets actually does is irrelevant anyway, as the OP would have issues they were not even aware of :p – Jaromanda X Jun 11 '18 at 23:16
  • "When the fill method gets passed an object, it will copy the reference and fill the array with references to that object." https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill I guess that's what I missed. Thanks for this answer, very insightful. – Gallaxhar Jun 11 '18 at 23:24
  • `const concise = Array.from({length:9}, () => ({random:Math.floor(Math.random() * 1000)})) console.log(concise);` can you add this in your answer? would be very illustrative – Gallaxhar Jun 11 '18 at 23:29
  • added that @Gallaxhar – Jaromanda X Jun 11 '18 at 23:32