Ask many developers what the length property of an array gives you in JS and you'll likely get some variation of the same answer:
The 'length' property tells you the number of elements in the array
Well, that's actually not correct. The property does tell you the length of the array (as its name implies) but that isn't the same as the number of elements. Unfortunately, many tutorial and reference websites also make this mistake.
What do we mean by 'array length'?
The length of an array is actually the number of slots available to store elements in. So, the following array has a length of 4 because it has that many slots available for storing elements:
const arr = [1, 2, 3, 4]
console.log(arr.length) // 4
At this point you may be thinking "Yes, but the number of elements in the array is always the same as the length" - and this is where you'd be wrong. Let's remove the number 4 from the array (at index 3):
const arr = [1, 2, 3, 4]
delete arr[3]
console.log(arr.length) // still 4
As you can see, deleting an element from an array doesn't change the length of the array - despite the fact that there are now only 3 elements in the array.
Sparse Arrays
Arrays containing 'holes' (like arr above) are known as 'Sparse' arrays. You may think that the 'holes' are really just slots containing undefined, and at first glance this does appear to be the case:
const arr = [1, 2, 3, 4]
delete arr[3]
console.log(arr[3]) // undefined
When we try to access the empty slot (3) - we get undefined. This is not because it contains undefined, rather that the content is simply missing - and when we try to access a non-existent property on object (remember, arrays are objects) we see undefined.
Logging a sparse array to the console will report any slots with nothing in them:
const arr = [1, 2, 3, 4]
delete arr[3]
console.log(arr) // [ 1, 2, 3, <1 empty slot> ]
The behaviour of empty slots can be further illustrated by using forEach:
const arr = [1, 2, 3, 4]
delete arr[2] // delete the number '3' this time
arr.forEach(x => console.log(x)) // 1, 2, 4
Notice that only three things were logged to the console. Contrast this with a similar non-sparse array that has undefined at slot 2 instead of it being empty. You will notice that four things are logged:
const arr = [1, 2, undefined, 4]
arr.forEach(x => console.log(x)) // 1, 2, undefined, 4
This is not only the case with forEach - most array iteration methods are 'sparse' aware.
As well as deleting elements from 'full' arrays, sparse arrays can be created in other ways:
// create a sparse, empty array with length 4
const arr1 = new Array(4)
// another way to do this
const arr2 = [,,,]
// create a sparse array with holes at slot 1 and 3
const arr3 = [1,,2,,5]
The array arr3 above has a length of 5, but only contains 3 elements.
Conclusion
If asked about array length, the best answer you can probably give is:
The length property of an array tells you the number of slots in the array
Whilst it is true that the number of elements stored in an array is very often the same as the array's length - these are very definitely two different things.
Top comments (2)
A JS Array's length is the number of elements you could fit in the allocated memory if JS arrays were real. JS does a relatively good job at pretending "arrays" really are arrays (and under the hood, modern VMs probably really optimise them as such when possible). Buying into the act and pretending Arrays in JS are a segment of memory divided into equal sizes generally leads to the least confusion about its semantics.
The fact that in reality they're just string->object maps that have to actively track their "length" to maintain this illusion is both amusing and kind of unhinged, but not usually all that important for programmers to really think about.
Maybe a follow-up post - "JS Arrays are NOT what you think they are" 😛