Take a look at the code sample below.
let array = [,,undefined,1,2,,];
console.log(array);

Interesting! What is empty and why is it different from undefined? This article dives into this issue (called Elision in JavaScript) and offers yet another delightful deep dive into the weird warts of JavaScript.
Elision: omission of a passage in a book, speech, or film.
https://www.google.com/search?q=Elision+definition
Sparse Arrays
An array is sparse if its length is greater the number of elements it contains. Thus, it is an array containing holes; holes are empty slots which contain nothing. This nothingness is represented as undefined however it is different from the JavaScript undefined value. Confusing eh, read why you should not use isNaN in JavaScript.
This is one of the weird parts of JavaScript; since there is no real empty value, JavaScript returns undefined instead. Holes in the array means there are no elements at those unassigned indexes. Remember that arrays are objects and objects do not need to have contiguous elements.
In JavaScript, undefined is the default value for variables that have been declared but not assigned any value.
Making Sparse Arrays in JavaScript
1. Using the Array Constructor
The simplest way is to use the Array Constructor with a count.
let sparseArray = new Array(10);
console.log(sparseArray);
// (10) [empty × 10]
2. Assigning a value to an index after length
let a = [];
a[6] = 0; // assign value to index after length
console.log(a);
// [empty x 5, 0]
3. Changing the length property
let b = [];
b.length = 5; // change length property
console.log(b);
// [empty x 5]
4. Deleting elements from an array
Note: deleting array elements does not alter the array length. Rather it puts holes in those locations. Again, holes are not same as undefined, they are empty slots.
let c = [1,2,3,4];
delete c[0], delete c[1], delete c[2]; // delete
console.log(c);
// [empty x 3, 4]
You can read more about the comma operator here.
5. Using the Array literal
let d = [,,,,]; // empty slots
console.log(d);
// [empty x 4], last comma doesn't count
The difference between Undefined and Empty Array slots
let weird = new Array(2);
weird[0] = undefined;
console.log(weird);
// [undefined, empty]
console.log(weird[0]); // undefined
console.log(weird[1]); // undefined
weird[0] === weird[1]; // true
weird[0] === undefined; // true
How do you know if an array slot is empty or undefined? Obviously comparing to undefined does not work. This is where the in operator is useful.
Seeing empty slots: The in Operator
The in operator is an object operator that checks if a property exists in an object or its prototype chain. Since arrays are objects, this is a foolproof way to identify holes. Empty slots have no defined index values at their locations because the property does not exist.
let sparseArray = new Array(10);
sparseArray.length
// 10
0 in sparseArray
// false
9 in sparseArray
// false
sparseArray[0] = undefined;
0 in sparseArray
// true
This shows that the 0th slot is now filled with undefined and not empty.
Why do arrays need to be sparse?
Performance. A huge sparse array e.g. new Array(9999999) contains nothing until elements are inserted.
The V8 engine optimizes for performance by distinguishing between dense and sparse arrays. See this great article on HOLEY and PACKED element kinds: https://v8.dev/blog/elements-kinds.
Tweet
Large Sparse Array
let size = 500000000;
console.time();
let timed = new Array(size);
console.timeEnd();
// ~ 0.03 ms
Large Dense Array
Warning: this snippet will crash your browser.
let size = 500000000;
console.time();
let timed = new Array(size)fill(0);
console.timeEnd();
Summary
JavaScript Arrays are closer to ArrayLists in C#/Java since sizes can grow organically. Arrays grow/shrink at will and can store any valid JavaScript value type.
- Sparse arrays contain holes
- Dense arrays contain contiguous elements (even if they are undefined).
The ECMAScript standard leaves implementation up to browser vendors to choose how to optimize.
Avoid holey arrays because JavaScript methods handle them inconsistently (i.e., some methods ignore them, others don’t). The next post in this series should provide examples of this.
Appreciate the article. Two points:
– `Object.hasOwn` is generally safer to use than the `in` operator for checking for holey elements, as arrays can technically have custom properties, including integer-keyed properties, on their prototype-chain.
– V8 treats `new Array(length).fill(value)` as holey (as of March 2022), and doesn’t capitalize on the apparent potential optimization.
LikeLike