2

I was reading Trailing commas and .forEach() documentations on MDN meanwhile playing with arrays.

So let's imagine a scenario when you have an array with elements like Number, undefined and created ones with trailing commas and running a forEach() on that. See from the documentation:

forEach() calls a provided callback function once for each element in an array in ascending order. It is not invoked for index properties that have been deleted or are uninitialized.

Based on that it skips the elements created with trailing commas but not the undefined ones:

const array = [ 1, 2, , 4, , undefined, ];
console.log({ length: array.length }); // shows 6

array.forEach((e, i) => console.log({e, i})); // logging 4 elements

In the same time using traditional for loop it logs all the elements as expected:

const array = [ 1, 2, , 4, , undefined, ];
console.log({ length: array.length }); // shows 6 as before

for (let i = 0; i < array.length; i++) {
  console.log({e: array[i], i}); // logs 6 elements
}

Also Chrome developer tool is showing empty items for the array for ones created by trailing commas:

chrome-screenshot

My questions:

From the documentation I found .forEach() is skipping deleted or uninitialized elements when iterating. So I see that statement, that's how it has been built.

So my questions would be:

  1. What's the difference between the undefined directly added to the array and by the trailing commas?
  2. Why .forEach() is showing up one undefined which has been added but not all the other ones.
  3. How can you differentiate from items called empty and undefined in this term?

What is going on under the hood? Can someone enlighten me about this scenario?

Appreciate the clarification, thank you!


Update:

I think I understood after further reading based on the linked questions.

So I took a look how .forEach() has been implemented which has an extra check with in operator for each elements and that's the difference. See as the following:

const array = [ 1, 2, , 4, , undefined, ];
console.log({ length: array.length }); // shows 6 as before

for (let i = 0; i < array.length; i++) {
  console.log({e: array[i], i, has: i in array});
}

So for the directly added undefined element the i in array returns true for all the empty elements false which makes sense now. As a result .forEach only calls the callback once the current element is existing.

Thanks for all the comments!

7
  • 2
    Setting something to undefined is still setting it--you initialized it w/ undefined. "Under the hood" it knows which elements you've defined. Commented Apr 27, 2020 at 14:40
  • 1
    You're initializing the item with undefined, but if you leave an empty space you know an item must be there, but it wasn't initialized, it has no value/type so it's skipped on .forEach(). Commented Apr 27, 2020 at 14:41
  • 2
    Notice that a trailing comma is just ignored, as if you never had written it. A comma that creates an elision is never a trailing comma. Commented Apr 27, 2020 at 14:44
  • 1
    Arrays are sparse, the "empty" elements don't exist. Run this: Object.getOwnPropertyDescriptors(array). Commented Apr 27, 2020 at 14:45
  • @terrymorse arrays can be sparse. Not all arrays are, though. Commented Apr 27, 2020 at 14:58

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.