1

So I was debugging one day when I came across this case in JavaScript.

var arrayA = [1, , 1],
    arrayB = [1, void 0, 1];

Now at first glance arrayA and arrayB look similar but when I tried this code in the Google Chrome Developer Console, things got weird:

Defining Array A and Array B

As you can see here, arrayB (the second one) has all it's members listed, including the undefined element.

But it's not the same with arrayA, ignoring the second member (arrayA[1]) even though it's undefined.

There's a problem here when it comes to how arrayA and arrayB are indexed, even though they are practically the same.

Indexing Array A

Everything is fine and dandy when iterating through arrayA using for and for...of statements but when using the for...in statement, the array's second element (arrayA[1]) is skipped over.

Indexing Array B

However, every element of arrayB was recognized when using all for loop variations.

This has also been tested on Mozilla Firefox and Microsoft Edge as well with the same results.

Is there any explanation for why this is so? Why is arrayA treated differently (no matter how slightly) from arrayB — using for...in statements?

I apologize if the images aren't ideal, they were just to show I was using the Google Chrome Developer Console.

And my thanks in advance for anyone willing to answer the question.

EDIT

Just to add, the custom depth property in the arrays do not have any effect on the arrays, even without them I still get the same result.

Lapys
  • 846
  • 1
  • 8
  • 22
  • 2
    console.log(Array(100)) – epascarello Jun 25 '18 at 21:26
  • 2
    Arrays with empty slots are different to arrays that have slots filled with `undefined`. See e.g. https://stackoverflow.com/a/44471705/3001761. Methods like `forEach` are [explicitly documented](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) as not including uninitialised elements. – jonrsharpe Jun 25 '18 at 21:28
  • It seems you are on to something, @epascarello. I just tried the code and it has the same behavior as the arrays in the question. Any idea why? – Lapys Jun 25 '18 at 21:29
  • Because `Array(size)` also creates an array containing `size` empty slots. – jonrsharpe Jun 25 '18 at 21:31
  • sounds like you can use `array.hasOwnProperty(n)` to split the hairs you need. – dandavis Jun 25 '18 at 21:32
  • Thanks for the responses, I'm just now learning that there are **Sparse Arrays** in JavaScript. I think I'll be avoiding them most of the time though as I can't easily see a use case for them right now. – Lapys Jun 25 '18 at 21:35

2 Answers2

3

Your arrayB is what arrays usually look like, they are filled with values.

However, your method ( as well as using Array(n)) can create sparse arrays, array in which some of the values are missing. Arrays, after all, are only special objects meaning that they are key values collection so your first array looks like

{"0": 1, "2": 1 }

while your second looks like

{"0": 1, "1": undefined, "2": 1}

The way to see it is to consider sparse arrays a quirk of the language and avoid it because they don't really have a use case. If you want an array, don't make it sparse, otherwise, use an object ( or an ES6 Map / Set, according to your use case)

Axnyff
  • 7,275
  • 2
  • 26
  • 31
3

empty is used to distinguish that there is actually no key at that position (for...in enumerates the keys):

var arrayA = [1, , 1], arrayB = [1, void 0, 1];
    
console.log( { ...arrayA } );   // { "0": 1, "2": 1 }
console.log( { ...arrayB } );   // { "0": 1, "1": undefined, "2": 1 }

console.log( 1 in arrayA );   // false
console.log( 1 in arrayB );   // true

console.log( JSON.stringify(arrayA) );   // "[1,null,1]"
console.log( JSON.stringify(arrayB) );   // "[1,null,1]"

As a side note, JavaScript Array is just an object where the positive integer keys are used :

var a = []
a[1] = 1
a.b = 'c'
a[-1] = -1
a[.1] = .1
    
console.log( a );   // [undefined, 1] but DevTools shows "►(2) [empty, 1, b: "c", -1: -1, 0.1: 0.1]
console.log( { ...a } );   // { "1": 1, "b": "c", "-1": -1, "0.1": 0.1 }
console.log( JSON.stringify(a) );   // "[null,1]"

(but that is not the case for TypedArrays)

Slai
  • 19,980
  • 5
  • 38
  • 44