Массив 1…N в JavaScript: секреты скорости и производительности

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

Массив 1…N в JavaScript: от простого к производительному

Привет, коллега-разработчик! Если ты когда-нибудь сталкивался с задачей «создать массив чисел от 1 до N» — ты не один. Это настолько популярный вопрос на Stack Overflow, что он собрал тысячи просмотров и десятки вариантов ответов. Казалось бы, что может быть проще? Но дьявол, как всегда, кроется в деталях: производительности, читаемости и универсальности кода.

Сегодня мы разберём все основные способы создания массива [1, 2, 3, ..., N] на JavaScript, сравним их по скорости, элегантности и области применения. Ты узнаешь, какой метод выбрать для обычного проекта, а какой — когда каждая миллисекунда на счету. Поехали!

Почему это важно? Контекст задачи

Представь: ты пишешь алгоритм сортировки, генерируешь тестовые данные, создаёшь сетку для игры или просто хочешь быстро получить последовательность чисел. Во всех этих случаях нужен массив от 1 до N. Казалось бы — цикл for и вперёд. Но современный JavaScript предлагает столько синтаксического сахара, что легко запутаться.

Мы рассмотрим 5 основных подходов, от классики до современных однострочников, и проверим их на прочность в реальных условиях. Готовь консоль браузера и любимый редактор — будет жарко!

Метод 1: Классический цикл for

Базовый, но надёжный способ, который знает каждый новичок:

function createArrayLoop(n) {
  const arr = [];
  for (let i = 1; i <= n; i++) {
    arr.push(i);
  }
  return arr;
}

console.log(createArrayLoop(5)); // [1, 2, 3, 4, 5]

Плюсы:

  • Максимальная читаемость — понятно даже тем, кто только начал учить JS.
  • Нет скрытых вызовов или магии.
  • Работает во всех средах, включая очень старые браузеры.

Минусы:

  • Медленнее, чем некоторые альтернативы (но не критично для малых N).
  • Много кода для простой задачи.

Метод 2: Array.from() с map-функцией

Элегантный современный подход, появившийся в ES6:

const createArrayFrom = n => Array.from({ length: n }, (_, i) => i + 1);

console.log(createArrayFrom(5)); // [1, 2, 3, 4, 5]

Здесь мы создаём массив с заданной длиной и сразу заполняем его через map-функцию. Второй аргумент Array.from — это как раз функция-маппер, которая получает текущий индекс i и возвращает i + 1.

Плюсы:

  • Очень кратко и выразительно.
  • Не требует предварительного создания пустого массива.
  • Хорошая производительность.

Минусы:

  • Может быть менее очевиден для новичков.
  • Создаёт промежуточный объект { length: n }.

Метод 3: Spread-оператор + keys()

Один из самых популярных однострочников на Stack Overflow:

const createArraySpread = n => [...Array(n).keys()].map(i => i + 1);

console.log(createArraySpread(5)); // [1, 2, 3, 4, 5]

Как это работает? Array(n) создаёт разреженный массив из n пустых элементов. .keys() возвращает итератор индексов (0, 1, 2...). Spread-оператор разворачивает его в обычный массив, а затем map сдвигает значения на +1.

Плюсы:

  • Очень лаконично (один вызов).
  • Выглядит «магически» — приятно удивляет коллег на код-ревью.

Минусы:

  • Самый медленный из всех методов для больших N (из-за двойного прохода и создания промежуточных массивов).
  • Сложнее для понимания начинающими.
  • Потребляет больше памяти.

Метод 4: Array.fill() + map()

Ещё один популярный вариант:

const createArrayFill = n => Array(n).fill().map((_, i) => i + 1);

console.log(createArrayFill(5)); // [1, 2, 3, 4, 5]

Сначала создаём массив из n пустых элементов, затем заполняем его значениями (fill() без аргументов ставит undefined), и только потом map превращает индексы в числа.

Плюсы:

  • Проще для понимания, чем spread + keys.
  • Быстрее, чем spread-версия.

Минусы:

  • Всё ещё два прохода (fill + map).
  • Немного медленнее Array.from.

Метод 5: Uint8Array и typed arrays (для спецзадач)

Если тебе нужна максимальная производительность и ты работаешь с числами в диапазоне 0-255, можно использовать типизированные массивы:

const createTypedArray = n => Uint8Array.from({ length: n }, (_, i) => i + 1);

console.log(createTypedArray(5)); // Uint8Array [1, 2, 3, 4, 5]

Этот метод возвращает не обычный массив, а Uint8Array. Он занимает меньше памяти (1 байт на элемент вместо 8 для обычного числа) и быстрее обрабатывается.

Плюсы:

  • Экономия памяти (до 8 раз).
  • Очень высокая скорость для больших N.

Минусы:

  • Ограничение по значениям (0-255 для Uint8).
  • Несовместимость с обычными методами массивов без преобразования.
  • Избыточно для большинства задач.

Бенчмарк: кто быстрее?

Давайте посмотрим на реальную производительность. Я прогнал тесты в Node.js для N = 10 000 и N = 100 000 (среднее по 100 запускам). Результаты (чем меньше — тем лучше):

Блоги

Рекомендаций по книгам