Skip to content
Carl Victor Fontanos
Carl Victor Fontanos

Carl Victor Fontanos

Software Engineer

I build web applications and share what I learn along the way.

© 2026

Array.from({ length }) Is JavaScript's Missing range()

C
Carlo Fontanos
· 2 min read

Ask a JavaScript developer to make an array of numbers 1 to 10 and you'll see loops, fill().map() chains, and occasionally the trap that doesn't work at all. The idiom worth memorizing:

Array.from({ length: 10 }, (_, i) => i + 1);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Array.from accepts anything with a length property, and its second argument is a mapping function called for every index. An object like {length: 10} has no actual elements - but from() doesn't care; it iterates indices and lets your callback produce the values.

Why not new Array(10).map()?

new Array(10).map((_, i) => i);   // [empty × 10] - map did NOTHING

Array(10) creates a sparse array with holes, and map skips holes entirely. This is the classic gotcha. Array.from never produces holes, which is exactly why the {length} idiom exists. (fill().map() also works - Array(10).fill(0).map(...) - it just allocates twice.)

The recipes I actually use

// Skeleton loading cards while data fetches
const placeholders = Array.from({ length: 6 }, (_, i) =>
    `<div class="card skeleton" style="animation-delay:${i * 80}ms"></div>`
).join('');

// Year dropdown, current year back to 1990
const years = Array.from({ length: currentYear - 1989 }, (_, i) => currentYear - i);

// Pagination page numbers
const pages = Array.from({ length: totalPages }, (_, i) => i + 1);

// A 2D grid (game boards, spreadsheets)
const grid = Array.from({ length: rows }, () =>
    Array.from({ length: cols }, () => null)
);

That grid one avoids the other classic trap - Array(3).fill([]) gives three references to the same array, so pushing to one row pushes to all. The from() version calls the callback per row, creating independent arrays.

The other things from() converts

Array.from(document.querySelectorAll('a'), a => a.href);   // NodeList -> array of hrefs, one pass
Array.from('hello');                                        // ['h','e','l','l','o'] - unicode-aware
Array.from(new Set(tags));                                  // dedupe idiom's second half

The querySelectorAll one is a two-for-one: conversion and mapping in a single iteration, no intermediate array. (For emoji-safe string splitting beyond code points, you want Intl.Segmenter - from('👨‍👩‍👧') still splits families into parts.)

A one-line range() helper wraps it up if the idiom offends you: const range = (n, s = 0) => Array.from({ length: n }, (_, i) => i + s). Either way, stop writing for-loops to build arrays.

C
Written by Carlo Fontanos

Full-stack web developer sharing practical tutorials and building tools that ship.

Got something on your mind?

My inbox is open - no forms disappearing into the void here.

  • Just say hello Found a tutorial useful? Spotted a mistake? Tell me.
  • Hire me for a project Have something custom in mind? Let's talk scope and timelines.
  • Product support Bought something here? I'll help you get it running.

I usually reply within 1-2 business days.

Message sent!

Your details are only used to reply to you.

Keep reading