Подтвердить что ты не робот

Нуль занимает память в javascript?

У меня есть следующая ситуация:

var large = [a,b,c,d,e,f,g,h,i];
var small = [a2, b2, c2, null, null, null, null, null, null, i2];

где каждый элемент обоих массивов является объектом.

Малый массив содержит информацию, относящуюся к большему, но не для каждого элемента large требуется связанный элемент в small, и поэтому я устанавливаю его в null. Тем не менее, мне все равно нужно поддерживать индексы такими же, чтобы я мог делать такие вещи, как large[16].id + ': ' + small[16].description. Имеет ли тот факт, что у меня есть массив, который в основном имеет значение null, приводит к увеличению использования памяти?

Мой вопрос в том, будет ли лучше делать что-то вроде small = [a2,b2,c2,i2] и устанавливать индексы в свойствах типа a2.index = 0; b2.index = 1 и так далее.

Я также нашел предложение использовать undefined, а кто-то даже упомянул о внедрении связанных списков. Я не думаю, что мне нужно реализовать связанный список, поскольку я не часто добавляю или удаляю элементы.

4b9b3361

Ответ 1

Массивы на самом деле являются объектами со специальной обработкой свойств с именами, которые являются индексами массива.

Назначая "null", вы приводите каждое свойство, которое будет использовать ненулевой объем памяти и, как уже упоминалось, замедляет поиск.

Вместо этого вы можете исключить несуществующие элементы, что приведет к разреженному массиву:

var small = [a2, b2, c2,,,,,,, i2];
// small == [a2, b2, c2,undefined,undefined,undefined,undefined,undefined,undefined, i2]

Edit Обратите внимание, что undefined занимает пробел, если вы явно назначаете его элементу массива (или любой переменной). Чтобы восстановить память в этом случае, вам нужно явно указать элемент delete. Стиль инициализации, показанный в моем примере кода, никогда не присваивает ничего элементам, которые уклонялись, поэтому они вообще не существуют. Это можно подтвердить, проверяя существование этих элементов как свойств объекта массива:

// continued from above
small.hasOwnProperty('3'); // returns false

small[3] = undefined;
small.hasOwnProperty('3'); // now returns true because the property exists

delete small[3];
small.hasOwnProperty('3'); // returns false again

alert(small.length); // alerts '10', showing that the array itself is still intact.

Ответ 2

Почему бы просто не поместить мелкие предметы в большие [2]. В любом случае, вам обычно не нужно беспокоиться о потреблении памяти в javascript, но все же лучше оставить неиспользуемые позиции в малом undefined (что-то другое, чем установка их на undefined!), Так что механизм javascript может решить переключиться на разреженный массив (представлен хэш-таблицей вместо массива).

Ответ 3

Я не могу полностью ответить на ваш вопрос, потому что я не уверен, что null занимает столько места, сколько явно устанавливает его на undefined. Но я считаю, что стандартный способ сделать это - использовать конструктор Array:

var large = [1,2,3,4,5,6,7];
var small = new Array(large.length);
small.length; // 7
small[0]; // undefined

Я считаю, что это использует меньше памяти, чем явно устанавливая значения undefined, хотя эффект тот же. Я использовал это для разреженного массива с 250 000 + индексами и не испытывал проблем с памятью (используя Google Chrome).

Изменить: (после игры и проведения немного большего исследования) Многим людям не нравится конструктор new Array() по множеству причин (см., например, обсуждение). Но я думаю, что у него есть несколько преимуществ для больших, редких массивов:

  • Он правильно устанавливает свойство length. Если вам нужна длина массива в соответствии с вашим большим массивом, вы не можете сделать это иначе, не устанавливая его явно (small.length = large.length) или помещая что-то undefined в конец (small[large.length-1] = undefined).

  • Он не устанавливает ключи для пустых индексов, что заставляет меня думать, что он использует меньше памяти. Если у вас есть массив a = [null,null,null] или a = [undefined,undefined,undefined], каждый из этих массивов имеет три индекса, и если вы используете a.map или a.forEach, ваша функция будет вызываться для каждого индекса. Если вы используете a = new Array(3), а затем вызываете a.forEach, ваша функция будет вызываться только для индексов, которые вы явно задали после постконструирования.

Но, похоже, нет большой разницы в производительности между:

var a = new Array(2000); 
a[2000] = 1;

и

var = [];
a[2000] = 1;

который также дает вам массив длиной 2000 с одним определенным индексом. Поэтому, если вам не волнует, соответствует ли length of small length large, я просто использовал бы var a = [] и динамически изменял его по мере необходимости - с простой точки зрения настройки и получения значения при определенных показателях, это точно то же самое.

Ответ 4

Null будет использовать память только для размера слова "NULL" (в терминах интерпретатора), но поиск замедляется из-за того, что массив перегружен объектами, которые не будут попадать в результат поиска, а JS не имеет способа оптимизировать это. Вам лучше использовать массив объектов, и каждый объект должен хранить значение и индекс.

Использование undefined тоже сложно. Что касается интерпретации и размера script, это увеличит объем памяти, но это не входит в спецификации, чтобы сообщить, должен ли undefined потреблять память и сколько, так что это зависит от браузера, его возможностей для сбора мусора, потребляют кучу памяти и т.д. Лучше всего попробовать, наверное. Запустите относительно большой массив как NULL, так и undefined в Chrome, сделайте снимок и сравните кучу.