SKU // 65

JavaScript Array Constructor

Square brackets are the usual way to make an array. There are also a few built-in functions for creating arrays: one with a well-known trap, and two that are genuinely useful for building arrays from other things.

// new Array(): Handle With Care

new Array() behaves differently depending on how many arguments you give it:

new Array("a", "b")   // ["a", "b"]         two arguments: the elements
new Array(3, 4)       // [3, 4]             two numbers: still the elements
new Array(3)          // [empty × 3]        ONE number: 3 empty slots!
new Array(-1)         // RangeError: Invalid array length
["a", "b"] [3, 4] [empty × 3] RangeError: Invalid array length

Only a single number triggers the length rule. Any other single value becomes the one element, and no arguments at all gives an empty array:

new Array()          // []
new Array("3")       // ["3"]   a string is an element
new Array(2.5)       // RangeError: Invalid array length
The Trap
new Array(3) does not make [3]. A single number is treated as a length, giving an array of 3 empty slots. Loops like for...of see them as undefined, but methods like map skip them entirely, which leads to confusing bugs.

The simple rule: use [] for arrays you write out yourself. The literal never has this problem.

const good = [3];            // [3]
const alsoGood = [];         // []

// Array() Without new

You can leave off new. Array checks whether you forgot it and adds it for you, so these are exactly the same:

new Array("Saab", "Volvo")   // ["Saab", "Volvo"]
Array("Saab", "Volvo")       // ["Saab", "Volvo"]
Array(3)                     // 3 empty slots: same trap

// Empty Slots Are Not undefined

W3Schools describes new Array(40) as "40 undefined elements". That is not quite right: the slots are empty, which is different from holding undefined. Reading one gives undefined, but some methods skip empty slots completely:

const holes = new Array(3);
const blanks = [undefined, undefined, undefined];

console.log(holes[0], blanks[0]);
console.log(holes.map(x => "hi"));
console.log(blanks.map(x => "hi"));
undefined undefined [empty × 3] ["hi", "hi", "hi"]

(map builds a new array from a function; it is covered in Array Iterations.) Chrome's console shows empty slots as empty.

// Array.of(): The Fixed Version

Array.of always treats its arguments as elements, even a single number:

Array.of(3)         // [3]
Array.of(3, 4, 5)   // [3, 4, 5]

// Array.from(): Make an Array from Something Else

Array.from turns anything list-like or iterable into a real array:

Array.from("hello");                  // ["h", "e", "l", "l", "o"]
Array.from({ 0: "a", 1: "b", length: 2 });   // ["a", "b"]
["h", "e", "l", "l", "o"] ["a", "b"]

That last one is an array-like object: numbered keys plus a length, but none of the array methods. You have met one already: arguments inside a function (Function Arguments). Array.from turns it into a real array:

function check() {
  console.log(Array.isArray(arguments));
  console.log(Array.isArray(Array.from(arguments)));
}
check(1, 2, 3);
false true

On web pages, lists of page elements are array-like too, and Sets (coming in JS Sets) can be converted the same way.

// Array.from() with a Builder Function

A second argument runs a function for each position. Combined with { length: n }, it builds an array of any size from a rule:

Array.from({ length: 5 }, (_, i) => i);       // [0, 1, 2, 3, 4]
Array.from({ length: 5 }, (_, i) => i * 2);     // [0, 2, 4, 6, 8]
Array.from({ length: 3 }, () => 0);           // [0, 0, 0]
[0, 1, 2, 3, 4] [0, 2, 4, 6, 8] [0, 0, 0]
Reading the Code
The builder receives two things: the current value (always undefined here, so it is named _ to show it is ignored) and the index i. Whatever the builder returns becomes that element.

// fill(): Same Value Everywhere

new Array(4).fill(0)        // [0, 0, 0, 0]
[1, 2, 3, 4].fill(9, 2)   // [1, 2, 9, 9]  (fill from index 2 on)

This is one of the few good uses for new Array(n): immediately filling its empty slots.

// Building a Grid Correctly

// WRONG: every row is the SAME inner array
const bad = new Array(3).fill([0, 0, 0]);
bad[0][0] = 1;
console.log(bad[2][0]);    // 1  (changed all three rows!)

// RIGHT: the builder makes a new row for each position
const good = Array.from({ length: 3 }, () => [0, 0, 0]);
good[0][0] = 1;
console.log(good[2][0]);   // 0  (rows are independent)
1 0
Watch out
fill puts the same value in every slot. For numbers and strings that is fine. For arrays or objects, every slot points to one shared object.

// Which to Use

Values you can type out[a, b, c]
Convert a string or array-like objectArray.from(thing)
Generate n values from a ruleArray.from({ length: n }, fn)
n copies of one number or stringnew Array(n).fill(value)

// Quick Check

Which one creates an array containing just the number 7?

  1. new Array(7)
  2. [7]
  3. Array(7)
  4. new Array(7).fill()
Show answer
B. A single number passed to Array, with or without new, is a length: A and C make 7 empty slots, and D fills those 7 slots with undefined. Array.of(7) would also work.

What does this log?

const a = new Array("5");
console.log(a.length);
Show answer
1. "5" is a string, not a number, so it becomes the single element. Only a single number is treated as a length.

What is the difference between new Array(1, 2) and Array(1, 2)?

  1. Array(1, 2) is a SyntaxError
  2. The second one makes 1 empty slot
  3. None: both make [1, 2]
  4. The first one is frozen
Show answer
C. Array adds the missing new for you. Both still have the single-number trap, which is why [] is preferred.

// Try It

  1. Click Open Playground and run it. Which of the three made 5 empty slots, and which made an array holding the number 5?
  2. Split your name into letters with Array.from
  3. Generate the first 10 square numbers (0, 1, 4, 9...) with Array.from and a builder
  4. Open the grid example with its Try it Yourself button, reproduce the shared-row bug, then fix it
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:41 AM ET