8

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);

3
  • Maybe the interpreter of this snippet does not fully support es6? Works fine for me using Chrome console... Commented Jun 11, 2018 at 23:06
  • Possible duplicate of Array.prototype.fill() with object passes reference and not new instance Commented Jun 11, 2018 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. Commented Jun 11, 2018 at 23:09

1 Answer 1

13

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))

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

5 Comments

/**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.
Fair enough, what stack snippets actually does is irrelevant anyway, as the OP would have issues they were not even aware of :p
"When the fill method gets passed an object, it will copy the reference and fill the array with references to that object." developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… I guess that's what I missed. Thanks for this answer, very insightful.
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
added that @Gallaxhar

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.