Zum Inhalt springen

Creating Arrays of Arrays (Nested Arrays) in JavaScript: Common Pitfalls and Best Practices

Working with arrays of arrays—often referred to as „nested arrays“ or „2D arrays“—is a common requirement in JavaScript when dealing with matrices, grids, or tabular data. However, the way we initialize these structures can introduce subtle bugs if we’re not careful! In this post, we’ll walk through the right and wrong ways to create arrays of arrays in JavaScript, explain why certain pitfalls occur, and show you best practices for robust code.

The Basic Case: Hardcoding Nested Arrays

Suppose we want to create a simple nested array with two empty arrays:

const arr = [[], []];

This works perfectly if you know the number of inner arrays in advance. Each sub-array is independent, and you can safely push data into one without affecting the other.

The Dynamic Case: Creating a Random-Length Array of Arrays

What if you don’t know ahead of time how many inner arrays you need? For example, suppose you want to create an array of len empty arrays, where len is determined at runtime.

A common first attempt might look like this:

const len = 5; // Suppose len is 5
const arr = new Array(len).fill([]);

At first glance, this seems reasonable: new Array(len) creates an array with len empty slots, and .fill([]) fills each slot with an empty array.

The Hidden Trap: Shared References

However, this approach can cause unexpected behavior! The problem is that .fill([]) fills every slot with the same array instance:

const arr = new Array(3).fill([]);
arr[0].push(1);
console.log(arr); 
// Output: [[1], [1], [1]]

Uh-oh! When you modify arr[0], you end up modifying every sub-array, because all elements of arr point to the exact same array in memory.

This happens because in JavaScript (and many other languages), arrays and objects are reference types. The value [] is a reference to a specific array object, and fill([]) copies that reference into every slot.

The Solution: Create a New Array for Each Slot

To avoid this, you should create a new empty array for each position. You can do this using .map() or .from():

Using Array.from()

const len = 5;
const arr = Array.from({ length: len }, () => []);

Here, the second argument to Array.from is a mapping function that returns a new empty array for each slot, so each sub-array is unique.

Using .map() (after .fill())

Alternatively, you can chain .map() after .fill():

const len = 5;
const arr = new Array(len).fill().map(() => []);
  • new Array(len).fill() creates an array of len undefineds.
  • .map(() => []) replaces each undefined with a new array.

Demonstration

const arr = Array.from({ length: 3 }, () => []);
arr[0].push(1);
console.log(arr); 
// Output: [[1], [], []]

Now, each inner array is independent!

Summary Table

Approach Are sub-arrays independent? Example Output
[[], []] Yes [[1], []] (after arr[0].push(1))
new Array(len).fill([]) No (shared reference) [[1], [1], [1]]
Array.from({length: len}, () => []) Yes [[1], [], []]
new Array(len).fill().map(() => []) Yes [[1], [], []]

Key Takeaways

  • Don’t use .fill([]) to create nested arrays—you’ll end up with shared references!
  • Use Array.from({ length: n }, () => []) or .map(() => []) to ensure each sub-array is unique.
  • Remember: objects and arrays in JavaScript are reference types. Assignment or .fill() with an object/array copies the reference, not the value.

Real-World Example: Initializing a 2D Matrix

Suppose you want a 5×5 grid of zeros:

const size = 5;
const matrix = Array.from({ length: size }, () =>
  Array.from({ length: size }, () => 0)
);
console.log(matrix);

Each row and each cell is independent—perfect for grid-based algorithms, games, or spreadsheets!

Conclusion

While it’s easy to create arrays of arrays in JavaScript, it’s just as easy to fall into the shared reference trap with .fill([]). By understanding how references work and initializing each sub-array independently, you’ll write safer, more predictable code.

Happy coding!

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert