How to Create and Initialize JavaScript Arrays
Master every way to create arrays in JavaScript. Covers array literals, the Array constructor, Array.of(), Array.from(), fill(), and practical patterns for initializing arrays with default values, sequences, and computed data.
JavaScript gives you at least six different ways to create an array, and each one exists for a specific reason. Choosing the wrong approach can lead to unexpected empty slots, wasted memory, or confusing behavior. This guide walks through every creation method, explains when each one is the right choice, and shows practical initialization patterns you will use in real projects.
If you are new to arrays entirely, start with what arrays are and how they work before reading this article.
Array Literal Syntax
The array literal is the most common, most readable, and most performant way to create an array:
const colors = ["red", "green", "blue"];
const numbers = [1, 2, 3, 4, 5];
const empty = [];This syntax creates a packed array (no holes) with exactly the elements you provide. The JavaScript engine optimizes literal arrays more aggressively than constructor-based arrays because it knows the exact shape at parse time.
When to use: Whenever you know the initial values at the time you write the code. This covers the overwhelming majority of array creation in real applications.
// Config arrays
const allowedRoles = ["admin", "editor", "viewer"];
// UI state
const defaultFilters = ["price", "rating", "date"];
// Test data
const sampleUsers = [
{ id: 1, name: "Alice", role: "admin" },
{ id: 2, name: "Bob", role: "editor" },
{ id: 3, name: "Carol", role: "viewer" },
];Trailing Commas
Adding a trailing comma after the last element ("viewer",) is valid JavaScript and recommended. It makes diffs cleaner when you add or remove items from the list.
The Array Constructor
The Array constructor creates arrays, but its behavior changes based on what you pass to it:
// Single numeric argument: creates an empty array with that length
const slots = new Array(5);
console.log(slots.length); // 5
console.log(slots[0]); // undefined (empty slot, not the value undefined)
// Multiple arguments: creates an array with those elements
const items = new Array("a", "b", "c");
console.log(items); // ["a", "b", "c"]
// Single non-numeric argument: creates an array with that element
const single = new Array("hello");
console.log(single); // ["hello"]The Constructor Trap
new Array(3) creates an array with 3 empty slots, not an array with the value 3. This inconsistency trips up beginners constantly. If you want an array containing the number 3, use [3] or Array.of(3).
| Call | Result | Explanation |
|---|---|---|
new Array() | [] | Empty array, same as [] |
new Array(5) | [empty x5] | 5 empty slots (holey array) |
new Array("5") | ["5"] | Array with one string element |
new Array(1, 2, 3) | [1, 2, 3] | Array with three elements |
new Array(-1) | RangeError | Negative length is invalid |
When to use: Rarely. The only practical use case is creating an array of a specific length that you immediately fill with fill() or Array.from().
Array.of() for Consistent Behavior
Array.of() was added in ES6 to eliminate the constructor's ambiguity. It always creates an array from its arguments, regardless of count or type:
const a = Array.of(5); // [5] — the number 5 as an element
const b = Array.of(1, 2, 3); // [1, 2, 3]
const c = Array.of("hello"); // ["hello"]Compare this to the constructor:
| Expression | new Array(...) | Array.of(...) |
|---|---|---|
Single number (5) | [empty x5] (length 5, holey) | [5] (one element) |
Multiple values (1,2,3) | [1, 2, 3] | [1, 2, 3] |
Single string ("hi") | ["hi"] | ["hi"] |
When to use: When you receive a dynamic value and want to guarantee it becomes an element, not a length specifier. In practice, array literals handle most cases, but Array.of() is useful in generic utility functions.
Array.from() for Converting and Generating
Array.from() creates a new array from any iterable or array-like object. It also accepts an optional mapping function, making it one of the most versatile array creation tools:
// From a string (iterable)
const chars = Array.from("hello");
console.log(chars); // ["h", "e", "l", "l", "o"]
// From a Set (iterable)
const unique = new Set([1, 2, 2, 3, 3]);
const arr = Array.from(unique);
console.log(arr); // [1, 2, 3]
// From an array-like object (has length, numeric keys)
const arrayLike = { 0: "a", 1: "b", 2: "c", length: 3 };
const real = Array.from(arrayLike);
console.log(real); // ["a", "b", "c"]The Mapping Function
The second argument to Array.from() is a map callback that transforms each element during creation:
// Generate a sequence of numbers 0-9
const sequence = Array.from({ length: 10 }, (_, index) => index);
console.log(sequence); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// Generate squares
const squares = Array.from({ length: 5 }, (_, i) => (i + 1) ** 2);
console.log(squares); // [1, 4, 9, 16, 25]
// Convert NodeList to array with transformation
// const texts = Array.from(document.querySelectorAll("p"), el => el.textContent);This pattern replaces the common new Array(n).fill(0).map(...) approach with a single, cleaner call.
Filling Arrays with Default Values
fill() Method
The fill() method replaces every element in an array with a static value:
// Create and fill in one step
const zeros = new Array(5).fill(0);
console.log(zeros); // [0, 0, 0, 0, 0]
const defaults = new Array(3).fill("pending");
console.log(defaults); // ["pending", "pending", "pending"]
// Fill a range (start inclusive, end exclusive)
const partial = [1, 2, 3, 4, 5];
partial.fill(0, 2, 4);
console.log(partial); // [1, 2, 0, 0, 5]Object Reference Trap
fill() assigns the same reference to every slot. If you fill with an object or array, every slot points to the exact same object:
const grid = new Array(3).fill([]);
grid[0].push("X");
console.log(grid); // [["X"], ["X"], ["X"]] — all three are the same array!Use Array.from() with a factory function instead:
const grid = Array.from({ length: 3 }, () => []);
grid[0].push("X");
console.log(grid); // [["X"], [], []] — independent arraysPractical Initialization Patterns
Here are patterns you will encounter in real codebases:
// Checkerboard: 8x8 grid of alternating values
const board = Array.from({ length: 8 }, (_, row) =>
Array.from({ length: 8 }, (_, col) => (row + col) % 2 === 0 ? "W" : "B")
);
// Month selector: array of month objects
const months = Array.from({ length: 12 }, (_, i) => ({
value: i + 1,
label: new Date(2026, i, 1).toLocaleString("en", { month: "long" }),
}));
// Pagination: generate page number buttons
function pageNumbers(totalPages) {
return Array.from({ length: totalPages }, (_, i) => i + 1);
}The Spread Operator for Cloning and Merging
The spread operator (...) creates a new array by expanding elements from existing arrays:
// Clone an array
const original = [1, 2, 3];
const clone = [...original];
// Merge arrays
const front = ["a", "b"];
const back = ["c", "d"];
const merged = [...front, ...back]; // ["a", "b", "c", "d"]
// Add elements during spread
const withMiddle = [...front, "MIDDLE", ...back]; // ["a", "b", "MIDDLE", "c", "d"]| Pattern | Syntax | Result |
|---|---|---|
| Clone | [...arr] | Shallow copy of arr |
| Merge two | [...a, ...b] | All elements from a then b |
| Prepend | [newItem, ...arr] | New item at start |
| Append | [...arr, newItem] | New item at end |
| Merge + dedupe | [...new Set([...a, ...b])] | Combined unique values |
Creating Arrays from Strings
Converting between strings and arrays is a daily operation in JavaScript:
// Split a string into an array
const csv = "Alice,Bob,Carol,Dave";
const names = csv.split(",");
console.log(names); // ["Alice", "Bob", "Carol", "Dave"]
// Split into individual characters
const word = "hello";
const letters = [...word];
console.log(letters); // ["h", "e", "l", "l", "o"]
// Split by words
const sentence = "JavaScript arrays are powerful";
const words = sentence.split(" ");
console.log(words); // ["JavaScript", "arrays", "are", "powerful"]To convert back, use join():
const tags = ["javascript", "arrays", "beginner"];
const tagString = tags.join(", ");
console.log(tagString); // "javascript, arrays, beginner"Comparison of All Creation Methods
| Method | Best for | Creates holes? | Map built-in? |
|---|---|---|---|
[a, b, c] | Known values at write time | No | No |
new Array(n) | Pre-sized arrays (use with .fill()) | Yes (empty slots) | No |
Array.of(a, b) | Dynamic values where new Array is ambiguous | No | No |
Array.from(iter, fn) | Converting iterables, generating sequences | No | Yes |
[...iterable] | Cloning, merging, converting iterables | No | No |
new Array(n).fill(v) | Fixed-size arrays with a default value | No (filled) | No |
Common Mistakes
Using the constructor when you want an element:
// Bug: creates 10 empty slots, not [10]
const bad = new Array(10);
// Fix: use a literal or Array.of()
const good = [10];
const alsoGood = Array.of(10);Filling with objects (reference trap):
// Bug: all rows share the same inner array
const grid = new Array(3).fill(new Array(3).fill(0));
grid[0][0] = 1;
console.log(grid[1][0]); // 1 — unintended!
// Fix: use Array.from with a factory
const safeGrid = Array.from({ length: 3 }, () => new Array(3).fill(0));
safeGrid[0][0] = 1;
console.log(safeGrid[1][0]); // 0 — correctUsing for...in to iterate arrays:
// Bug: for...in iterates all enumerable properties, not just indices
Array.prototype.customMethod = function() {};
const arr = [1, 2, 3];
for (const key in arr) {
console.log(key); // "0", "1", "2", "customMethod" — unexpected!
}
// Fix: use for...of or a standard for loop
for (const value of arr) {
console.log(value); // 1, 2, 3
}Rune AI
Key Insights
- Array literals first: Use
[a, b, c]as your default; it is the most readable and fastest option - Array.from() for generation: Create sequences, convert iterables, and map during creation with a single call
- Avoid the constructor trap:
new Array(5)creates 5 empty slots, not[5]; useArray.of(5)or[5]when you want an element - Object reference danger:
fill()shares one reference across all slots; useArray.from(() => ...)for independent objects - Spread for cloning and merging:
[...arr]creates a shallow copy;[...a, ...b]merges arrays without mutating either one
Frequently Asked Questions
What is the fastest way to create an array in JavaScript?
Should I use new Array() or array literals?
How do I create a 2D array in JavaScript?
What is the difference between Array.from() and the spread operator?
How do I create an array of N random numbers?
Conclusion
JavaScript provides multiple array creation methods because different situations call for different tools. Array literals handle the vast majority of cases cleanly and efficiently. Array.from() with a mapping function is the go-to for generating sequences and converting iterables. fill() paired with the constructor works well for fixed-size defaults, as long as you avoid the object reference trap. Understanding these patterns ensures you always pick the most readable, performant approach for the job.
More in this topic
OffscreenCanvas API in JS for UI Performance
Master the OffscreenCanvas API to offload rendering from the main thread. Covers worker-based 2D and WebGL rendering, animation loops inside workers, bitmap transfer, double buffering, chart rendering pipelines, image processing, and performance measurement strategies.
Advanced Web Workers for High Performance JS
Master Web Workers for truly parallel JavaScript execution. Covers dedicated and shared workers, structured cloning, transferable objects, SharedArrayBuffer with Atomics, worker pools, task scheduling, Comlink RPC patterns, module workers, and performance profiling strategies.
JavaScript Macros and Abstract Code Generation
Master JavaScript code generation techniques for compile-time and runtime metaprogramming. Covers AST manipulation, Babel plugin authorship, tagged template literals as macros, code generation pipelines, source-to-source transformation, compile-time evaluation, and safe eval alternatives.