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.

JavaScriptbeginner
12 min read

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:

javascriptjavascript
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.

javascriptjavascript
// 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:

javascriptjavascript
// 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).

CallResultExplanation
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)RangeErrorNegative 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:

javascriptjavascript
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:

Expressionnew 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:

javascriptjavascript
// 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:

javascriptjavascript
// 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:

javascriptjavascript
// 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:

javascriptjavascript
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:

javascriptjavascript
const grid = Array.from({ length: 3 }, () => []);
grid[0].push("X");
console.log(grid); // [["X"], [], []] — independent arrays

Practical Initialization Patterns

Here are patterns you will encounter in real codebases:

javascriptjavascript
// 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:

javascriptjavascript
// 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"]
PatternSyntaxResult
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:

javascriptjavascript
// 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():

javascriptjavascript
const tags = ["javascript", "arrays", "beginner"];
const tagString = tags.join(", ");
console.log(tagString); // "javascript, arrays, beginner"

Comparison of All Creation Methods

MethodBest forCreates holes?Map built-in?
[a, b, c]Known values at write timeNoNo
new Array(n)Pre-sized arrays (use with .fill())Yes (empty slots)No
Array.of(a, b)Dynamic values where new Array is ambiguousNoNo
Array.from(iter, fn)Converting iterables, generating sequencesNoYes
[...iterable]Cloning, merging, converting iterablesNoNo
new Array(n).fill(v)Fixed-size arrays with a default valueNo (filled)No

Common Mistakes

Using the constructor when you want an element:

javascriptjavascript
// 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):

javascriptjavascript
// 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 — correct

Using for...in to iterate arrays:

javascriptjavascript
// 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

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]; use Array.of(5) or [5] when you want an element
  • Object reference danger: fill() shares one reference across all slots; use Array.from(() => ...) for independent objects
  • Spread for cloning and merging: [...arr] creates a shallow copy; [...a, ...b] merges arrays without mutating either one
RunePowered by Rune AI

Frequently Asked Questions

What is the fastest way to create an array in JavaScript?

rray literals (`[1, 2, 3]`) are the fastest because the JavaScript engine can optimize them at parse time. The `Array` constructor and `Array.from()` involve function calls with additional overhead, though the difference is negligible for arrays under 10,000 elements.

Should I use new Array() or array literals?

Use array literals in almost every case. They are more readable, less error-prone (no single-number ambiguity), and marginally faster. The only time `new Array(n)` makes sense is when you need a specific length and immediately fill it with `.fill()` or `Array.from()`.

How do I create a 2D array in JavaScript?

Use `Array.from()` with a nested factory function: `Array.from({ length: rows }, () => new Array(cols).fill(0))`. This creates independent inner arrays. Never use `new Array(rows).fill(new Array(cols).fill(0))` because every row will reference the same inner array.

What is the difference between Array.from() and the spread operator?

Both convert iterables to arrays, but `Array.from()` also works on array-like objects (anything with a `length` property and numeric keys, such as `arguments` or DOM NodeLists) and accepts a mapping function. The spread operator only works on true iterables (objects that implement `Symbol.iterator`).

How do I create an array of N random numbers?

Use `Array.from({ length: n }, () => Math.random())` to generate `n` random numbers between 0 and 1. For integers in a range, use `Array.from({ length: n }, () => Math.floor(Math.random() * (max - min + 1)) + min)`.

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.