Arrays
Understand how to create arrays, access and modify their elements by index, work with the length property, and use nested arrays to represent multi-dimensional data.
An array is an ordered, list-like collection of values, accessed by numeric index rather than by name. Arrays are one of the most heavily used data structures in JavaScript — used to represent everything from a list of todo items, to search results, to rows in a table, to the pixels of an image.
Creating arrays
The most common way to create an array is with array literal syntax: square brackets containing a comma-separated list of values, for example const fruits = ["apple", "banana", "cherry"]. Arrays can hold any mix of types — numbers, strings, objects, other arrays, even functions — all in the same array, since JavaScript arrays are not type-restricted.
Arrays can also be created with the Array constructor (new Array()) or Array.of() / Array.from(), but the literal [] syntax is preferred in almost all real-world code because it's shorter and avoids a well-known quirk: new Array(5) creates an array with length 5 but no actual elements, which surprises many beginners.
Indexing
Array elements are accessed using square-bracket notation with a zero-based numeric index: the first element is at index 0, the second at index 1, and so on. fruits[0] gives "apple", and fruits[2] gives "cherry" in the example above.
Accessing an index that doesn't exist (like fruits[10] on a 3-element array) does not throw an error — it simply returns undefined. This is different from many other languages and is a common source of subtle bugs if you forget to check whether an index is valid.
The length property
Every array has a length property that reports how many elements it currently has. Because indexes are zero-based, the last valid index of an array is always length - 1 — fruits.length is 3, and fruits[fruits.length - 1] gives you the last element ("cherry").
length is not just read-only information — you can assign to it directly. Setting fruits.length = 1 truncates the array down to just its first element, and setting it to a larger number than the current length pads the array with empty slots.
Mutation
Arrays in JavaScript are mutable: you can change an individual element by assigning directly to its index (fruits[1] = "blueberry"), and the array itself keeps the same identity — this is different from reassigning the whole variable to a new array.
Because arrays are objects under the hood, when you pass an array into a function or assign it to another variable, you are passing a reference to the same underlying array, not a copy — mutating it in one place affects every variable that references it. (Non-mutating alternatives, and copying techniques, are covered in the Array Methods and Destructuring/Spread lessons.)
Nested arrays
Because an array can hold any value, including other arrays, you can build nested (multi-dimensional) structures — for example a 2D grid represented as an array of arrays, where grid[row][col] accesses a specific cell.
Nested arrays are common for representing tables, matrices, game boards, and grouped data (like a list of student records, each containing an array of that student's grades).
Array literal, indexing, and length
Indexes are zero-based: the first element is always at index 0. Assigning to an out-of-range index (like fruits[5] = "x") extends the array and leaves gaps (empty slots) in between. length always reflects the current highest index + 1, and updates automatically as you add or remove elements with array methods.
const fruits = ["apple", "banana", "cherry"];
console.log(fruits[0]); // "apple"
console.log(fruits[fruits.length - 1]); // "cherry" (last element)
console.log(fruits[10]); // undefined — index out of range
fruits[1] = "blueberry"; // mutate in place
console.log(fruits); // ["apple", "blueberry", "cherry"]
console.log(fruits.length); // 3Code Examples
This creates a simple array of three strings and reads two elements by index, plus the array's length. Expected result: red green 3 colors[0] accesses the first element using zero-based indexing.
scores[scores.length] = 95 writes to the index right after the current last element, which is a manual way to append (though push(), covered in the next lesson, is the normal way). Setting.length directly then truncates the array down to just its first two elements. Expected result: [ 88, 92, 76, 95 ] [ 88, 92 ] scores.length = 2; shortens the array in place by reassigning the length property.
Common mistake: Manually writing to scores[scores.length] works but is unusual and easy to get wrong if the array has gaps; push() is clearer and safer for adding elements.
grid is an array of three arrays, representing a 3x3 matrix. grid[1][2] first accesses the array at index 1 ([4, 5, 6]), then index 2 of that inner array (6). The nested for loops walk every row and column to print the whole grid. Expected result: 6 1 2 3 4 5 6 7 8 9 grid[1][2] chains two index lookups: outer array first, then the inner array it returns.
const colors = ["red", "green", "blue"];
console.log(colors[0]);
console.log(colors[1]);
console.log(colors.length);const scores = [88, 92, 76];
scores[scores.length] = 95; // append using length as the next open index
console.log(scores);
scores.length = 2; // truncate the array
console.log(scores);const grid = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
];
console.log(grid[1][2]); // row 1, column 2
for (let row = 0; row < grid.length; row++) {
let line = "";
for (let col = 0; col < grid[row].length; col++) {
line += grid[row][col] + " ";
}
console.log(line.trim());
}Array indexing
Indexes always start at 0, and the array's length is always one greater than its highest valid index.
const fruits = ["apple", "banana", "cherry"]
index: 0 1 2
│ │ │
▼ ▼ ▼
"apple" "banana" "cherry"
fruits.length === 3
last valid index === fruits.length - 1 === 2Important Rules
Array indexes are zero-based: the first element is at index 0.
Accessing an out-of-range index returns undefined instead of throwing an error.
length always equals the number of elements (or, more precisely, the highest index used plus one), and can be read or directly reassigned.
Arrays are reference types — assigning an array to a new variable, or passing it to a function, shares the same underlying array rather than copying it.
Nested arrays let you represent multi-dimensional or grouped data by putting arrays inside arrays.
Where this shows up
Arrays are everywhere in real applications: a list of products in a shopping cart, rows returned from a database query, the results of a search, the items in a dropdown menu, or pixel/frame data in graphics and games. Nested arrays specifically show up in spreadsheets, board games (like tic-tac-toe or chess), and any grid-based UI.
const a = [1, 2, 3]; const b = a; b[0] = 99; // a is now [99, 2, 3] too!
const a = [1, 2, 3]; const b = [...a]; b[0] = 99; // a stays [1, 2, 3] const b = a; copies the reference, not the array — both variables point to the exact same array in memory, so mutating one affects the other. Using the spread operator [...a] creates a genuinely separate (shallow) copy.
[Multiple Choice] Given const arr = [10, 20, 30], what does arr[arr.length - 1] evaluate to? A. 10 B. 20 C. 30 D. undefined
C. 30 — arr.length is 3, so arr.length - 1 is 2, and arr[2] is the last element, 30. This is the standard idiom for accessing an array's last element by index.
[True / False] Accessing an index beyond the end of an array, such as arr[100] on a 3-element array, throws an error. A. True B. False
B. False — False. JavaScript simply returns undefined for an out-of-range index instead of throwing — no error is raised.
Given const matrix = [[1,2],[3,4],[5,6]], write code that logs the value at row 2, column 1, and also logs how many rows the matrix has.
const matrix = [[1, 2], [3, 4], [5, 6]]; console.log(matrix[2][1]); // 6 console.log(matrix.length); // 3
Use matrix[row][col] for the value, and matrix.length for the row count.