2010-12-30 5 views
3

Я вставив некоторые элементы в массив со случайно созданными индексами, например, как это:JavaScript массив вставка случайного индекса и удаление

var myArray = new Array(); 
myArray[123] = "foo"; 
myArray[456] = "bar"; 
myArray[789] = "baz"; 
... 

Другими словами индексы массив не начинаются с нулем и будут " числовые пробелы "между ними. Мои вопросы:

  • Будут ли эти числовые промежутки быть каким-то образом выделены (и, следовательно, взять память), даже если у них нет назначенных значений?
  • Когда я удалю myArray [456] из верхнего примера, будут ли перемещены элементы ниже этого элемента?

EDIT: Что касается моего вопроса/заботы о перемещении элементов после вставки/удаления - Я хочу знать, что происходит с показателями памяти и нет. Более подробная информация от wikipedia article:

Связанные списки имеют ряд преимуществ по сравнению с динамических массивов. Вставка из элемента в конкретной точке списка является операцией постоянная времени, в то время как вставки в динамическом массиве при случайных местах потребует перемещения половины элементов в среднем, и все элементов в худшем дело. В то время как один может «удалить» элемент из массива в постоянное время, как-то маркируя его слот как «свободный», это вызывает фрагментацию , которая препятствует производительности итерации .

+2

не имеющий отношения к вашему вопросу, но при выполнении такого рода вещей вы можете использовать объект вместо var myArray = {} – Zevan

ответ

6

Будут ли эти числовые промежутки быть каким-то образом выделены (и, следовательно, взять некоторую память), даже если у них нет назначенных значений?

Нет. Массивы JavaScript на самом деле не являются массивами (см. Ниже), а неиспользуемые индексы не содержат памяти.

Когда я удалю myArray [456] из верхнего примера, будут ли перемещены элементы ниже этого элемента?

Если вы говорите об индексах массивов, это зависит от того, как вы его удаляете: если вы используете ключевое слово delete, нет. Если вы используете функцию splice или аналогичную, да. В терминах памяти нет, другие записи не перемещаются (независимо), и любая память, на которую ссылалась запись, которая больше не существует (из-за delete или splice или pop или аналогичных) становится доступной для исправления сборщик мусора. Связанные списки практически не имеют преимущества в JavaScript над массивами или обычными старыми объектами, и вы редко их видите. Добавление к массиву JavaScript (или объекту), скорее всего, будет операцией с почти постоянным временем (реализациям, вероятно, потребуется сделать хэширование и, возможно, некоторый обход структур B-дерева или аналогичный, но это полностью зависит от реализации), так как это удаление.

Для того, что вы описываете, как указал Зевон, вам может не понадобиться массив. Вам действительно нужен массив, если вам нужно свойство length или одна из функций массива, которая опирается на него. В противном случае вам будет лучше с обычным старым объектом:

var obj = {}; 
obj[123] = "foo"; 
obj[456] = "bar"; 
obj[789] = "baz"; 

Совершенно верно JavaScript. Значения, которые вы используете в скобках (123 и т. Д.), Принудительно привязываются к строкам (независимо от того, имеете ли вы дело с массивом или простым объектом), и поэтому ключ действительно «123» и т. Д. (Независимо от того, используя Array или Object). Вы можете даже прокручивать их, используя структуру управления for..in (details here).


Что я подразумеваю под «... на самом деле не являются массивами»? Буквально это. Объектами JavaScript являются карты key-> value, а массивы JavaScript - не что иное, как объекты, которые имеют ключи и значения, и специальную обработку для ключей, которые являются числовыми строками, и специальное свойство length. Хотя мы обычно записываем массивы «индексы» в виде чисел, как и все имена свойств, они относятся к . Строки   — a[0] преобразуется в a["0"] (хотя реализации могут быть оптимизированы, если поведение остается в соответствии с спецификацией). Это предусмотрено статьей 15.4 the specification, который начинается с этим пунктом:

массив объекты особого обращения к определенному классу имен свойств. Имя свойства Р (в виде значения String) является индексом массива тогда и только тогда, когда ToString (ToUint32 (Р)) равна P и ToUint32 (P) не равно 2^32-1. Свойство, имя свойства которого является индексом массива, также называется элементом . Каждый объект Array имеет свойство length, значение которого всегда является неотрицательным целым числом менее 2^32. Значение свойства length численно больше имени каждого свойства, имя которого является индексом массива; всякий раз, когда создается или изменяется свойство объекта Array, другие свойства корректируются по мере необходимости для поддержания этого инварианта.В частности, всякий раз, когда добавляется свойство, чье имя является индексом массива, свойство length изменяется, если необходимо, на одно больше, чем числовое значение этого индекса массива; и всякий раз, когда изменяется свойство length, каждое свойство, имя которого является индексом массива, значение которого не меньше, чем длина нового , автоматически удаляется. Это ограничение применяется только к собственным свойствам объекта Array и не зависит от свойств индекса длины или массива, которые могут быть унаследованы от его прототипов.

+0

Спасибо за ваш длинный и информативный ответ. Каков наилучший способ удалить ключ с его значением, когда я использую простой старый объект вместо массива? – yojimbo87

+0

@Tomi: 'delete' может быть в форме выше, с литералом для имени свойства:' delete obj.foo; 'Или он может использовать заключенную в скобки запись со строкой:' delete obj ["foo"]; ' –

1

Будут ли эти числовые пробелы как-то выделяется (и, следовательно, потребуется некоторое память), даже если они не имеют присвоенные значения?

Нет, см. spec on Array's property setter.

При удалении MyArray [456] из верхней например, будет пункты ниже этого пункта быть перемещены?

Нет, если бы предмет был на 460, он останется там после удаления 456. Если вы хотите, те ниже, чтобы быть должным образом смещенными вниз, используйте метод splice как так:

myArray.splice(456, 1) 
+1

. Первый вопрос, * «Это полностью зависит от реализации браузера ...» * Нет, это не так, если реализация не соответствует спецификации. –

+0

@ T.J. Кроудер: Упс, спасибо за исправление. Я просмотрел соответствующую часть спецификации и обновил свой ответ. –

1

«разрывы» не приведет к ассигнованиям, и нет, там нет «перехода» из существующих значений от их индексов ,