Ситуация. К разработчику одной федеральной торговой сети поступила такая задача: собрать и предварительно обработать все покупки за месяц со всех магазинов по всей стране. Разработчик выяснил стандартный среднемесячный объём данных, количество магазинов, сколько касс в магазине и количество смен.
Для обработки данных разработчик создаёт пустой массив, но хочет заранее указать, сколько элементов будет в массиве. Для этого он получает общее значение данных для обработки и объявляет новую переменную с массивом:
// получаем общее количество записей для обработки,
// исходя из средних данных, количества магазинов, касс и смен
var total = monthData * shops * boxOffice * shifts;
// организуем новый массив для данных
var data = new Array(total);
Но при запуске код выдаёт ошибку:
❌ RangeError: Array size is not a small enough positive integer
Видно, что код ругается на размер массива, но не ругается на результат умножения — но почему?
Что это значит: компьютер не смог создать массив с таким большим количеством элементов и попросил уменьшить их количество.
Когда встречается: когда мы пытаемся создать массив, где элементов больше, чем 2 32 − 1 = 4 294 967 295. Такое ограничение на размер массива появилось в 2009 году из-за внутренней команды ToUint32() — она переводит числа в 32-битный формат без использования отрицательных чисел. Максимальное число, которое попадает в этот диапазон, — 4 294 967 295.
Что делать с ошибкой RangeError: Array size is not a small enough positive integer
Решить эту ошибку можно двумя способами: указав безопасное количество элементов вручную или проверив его перед созданием массива.
В первом случае всё просто: мы создаём новый массив и сразу указываем максимальное количество элементов:
var data = new Array(4294967295);
Во втором — проверяем допустимый размер перед созданием:
// получаем общее количество записей для обработки,
// исходя из средних данных, количества магазинов, касс и смен
var total = monthData * shops * boxOffice * shifts;
// если не превысили размер
if (total <= 4294967295) {
// организуем новый массив для данных
var data = new Array(total);
} else {
//иначе выводим сообщение об ошибке
console.log('Слишком большой размер массива')
}
Но почему компьютер не ругался на промежуточный результат?
Когда мы перемножили числа и положили результат в переменную total, к нему применялись совсем другие требования, в том числе и на максимальный размер числа — 21024 − 1. Это в 32 раза больше, чем максимально возможное количество элементов массива.
Получается, что очень большую переменную мы посчитать можем, а использовать её для создания массива — нет. А если интересно, как можно работать в JavaScript с очень большими числами, — почитайте, как мы научили компьютер складывать в столбик.