jsguides

Array

Array is a global constructor for creating list-like objects with a dynamic length. Every array inherits from Array.prototype, which provides a large set of instance methods for traversal, mutation, and transformation.

Constructor

Call Array() with elements to create a list, or with a single numeric argument to create a sparse list with a given length:

new Array();           // []
new Array(1, 2, 3);    // [1, 2, 3]
new Array(3);          // [empty × 3] — sparse, length 3
new Array("foo");      // ["foo"]

Without new, the behavior is identical. Array literals [1, 2, 3] never trigger the length behavior, so they are generally preferred. When you do use the constructor, watch out for invalid length arguments — they throw immediately instead of producing a malformed list.

The constructor throws a RangeError for non-integer or out-of-bounds lengths:

new Array(-1);      // RangeError: Invalid array length
new Array(4.5);     // RangeError: Invalid array length
new Array(2 ** 32); // RangeError: Invalid array length

Static Methods

The constructor handles creation, but Array also exposes several static utilities for type checking and constructing new instances from various sources. These methods work without a receiver — you call them directly on the Array object itself.

Array.isArray(value)

Returns true if value is an Array; false otherwise. Uses a brand check against a private field, so it works reliably across realms such as iframes and Web Workers where instanceof Array would fail.

Array.isArray([]);               // true
Array.isArray(new Array(5));      // true
Array.isArray(Array.prototype);   // true — Array.prototype is itself an array
Array.isArray({});                // false
Array.isArray(new Uint8Array(32)); // false — TypedArrays are not Arrays

The brand check makes isArray the most dependable way to confirm you are dealing with a real list, especially in library code that might receive values from unknown origins. Once you have confirmed the type, the next common need is building a new array from data that is not yet in array form.

Array.from(items[, mapFn[, thisArg]])

Creates a new shallow-copied Array from an iterable or array-like object. Added in ES6.

Array.from("foo");               // ["f", "o", "o"]
Array.from(new Set([1, 2, 2, 3])); // [1, 2, 3]

const m = new Map([["a", 1], ["b", 2]]);
Array.from(m.values());          // [1, 2]

// With map function
Array.from([1, 2, 3], x => x * x); // [1, 4, 9]

The from() method accepts any iterable — strings, Sets, Maps, or generator functions — and returns a flat list. You can also pass a mapping function as the second argument to transform each element during construction, which avoids a separate .map() call.

The method is generic. Call it on any constructor to produce instances of that class:

Array.from.call(Set, [1, 2, 3]); // Set { 1, 2, 3 }

Unlike from(), which pulls data out of an existing source, of() lets you spell out each item explicitly. This is the method to reach for when you have a handful of known values and want to avoid the single-number-as-length pitfall of the constructor.

Array.of(element1[, element2[, …]])

Creates a new list from the passed arguments. Unlike the constructor, a single numeric argument is treated as an element, not a length:

Array.of(7);         // [7]
Array.of(1, 2, 3);   // [1, 2, 3]
Array.of();         // []

This makes Array.of() the predictable alternative to new Array(length). When your data arrives asynchronously — for example, from a stream of API responses — you need a method that can wait for each item to resolve before assembling the final list.

Array.fromAsync(items[, mapFn[, thisArg]])

Creates a new list from an async iterable, iterable, or array-like. Returns a Promise that resolves to the finished product. Added in ES2024.

async function* gen() {
  yield 1;
  yield 2;
  yield 3;
}
await Array.fromAsync(gen()); // [1, 2, 3]

// With map function
await Array.fromAsync([1, 2, 3], async x => x * x); // [1, 4, 9]

Key Gotchas

While the constructor and static methods are straightforward, a few behavioral quirks can catch you off guard — especially around sparseness, type checking across realms, and the single-argument trap.

Sparse arrays. new Array(3) creates a list with length: 3 but no own properties at any index. Accessing an index returns undefined, but the property does not exist. So 0 in arr is false. Methods like .map() skip empty slots.

const a = new Array(3);
a.length;       // 3
0 in a;         // false
a[0];           // undefined
a.map(x => x);  // [<3 empty items>] — skips empty slots

Constructor vs literal. The constructor and bracket syntax produce different results for a single number argument, which has caused subtle bugs in code that dynamically passes a count to new Array(). When you see a numeric argument, always check whether the code intends a sparse list of that length or a single-element list containing that number.

new Array(3);  // [empty × 3]
[3];           // [3]

RangeError on large lengths. The constructor throws instead of silently failing for lengths at or beyond 2 ** 32.

instanceof fails across realms. If you need to check whether a value is an array and it might come from another JavaScript global (an iframe, a Web Worker, a different JS engine), use Array.isArray() instead of instanceof Array.

See Also