Являются ли массивы Javascript редкими? - PullRequest
89 голосов
/ 02 октября 2009

То есть, если я использую текущее время в качестве индекса в массиве:

array[Date.getTime()] = value;

Будет ли интерпретатор создавать все элементы с 0 по настоящее время? Разные браузеры делают это по-разному?

Я помню, что раньше было ядро ​​ AIX , которое создавало псевдо-ttys по запросу, но если бы вы, скажем, "echo> / dev / pty10000000000" это создавало dev / pty0, / dev / pty1, .... а затем падают замертво. На выставках было весело, но я не хочу, чтобы это происходило с моими клиентами.

Ответы [ 5 ]

62 голосов
/ 02 октября 2009

Да, они есть. Они на самом деле являются внутренними хеш-таблицами, поэтому вы можете использовать не только большие целые числа, но также строки, числа с плавающей запятой или другие объекты. Все ключи преобразуются в строки через toString() перед добавлением в хеш. Вы можете подтвердить это с помощью некоторого тестового кода:

<script>
  var array = [];
  array[0] = "zero";
  array[new Date().getTime()] = "now";
  array[3.14] = "pi";

  for (var i in array) {
      alert("array["+i+"] = " + array[i] + ", typeof("+i+") == " + typeof(i));
  }
</script>

Отображение:

array[0] = zero, typeof(0) == string
array[1254503972355] = now, typeof(1254503972355) == string
array[3.14] = pi, typeof(3.14) == string

Обратите внимание, как я использовал синтаксис for...in, который дает только те индексы, которые на самом деле определены. Если вы используете более распространенный стиль итерации for (var i = 0; i < array.length; ++i), то, очевидно, у вас будут проблемы с нестандартными индексами массивов.

36 голосов
/ 02 октября 2009

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

Вам нужно будет попросить кого-то с большим знанием о конкретных реализациях ответить на вопрос, что именно вызывает переход от плотного к разреженному, но ваш пример должен быть совершенно безопасным. Если вы хотите получить плотный массив, вам следует вызвать конструктор с явным аргументом длины и надеяться, что вы его получите.

См. этот ответ для более подробного описания olliej.

9 голосов
/ 02 октября 2009

Вы можете избежать этой проблемы, используя синтаксис javascript, разработанный для такого рода вещей. Вы можете рассматривать его как словарь, но синтаксис "for ... in ..." позволит вам захватить их все.

var sparse = {}; // not []
sparse["whatever"] = "something";
7 голосов
/ 02 октября 2009

Объекты Javascript являются разреженными, а массивы - это просто специализированные объекты с автоматически поддерживаемым свойством длины (которое на самом деле больше, чем самый большой индекс, не количество определенных элементов) и некоторыми дополнительными методами. Вы в безопасности в любом случае; используйте массив, если вам нужны его дополнительные функции, и объект в противном случае.

1 голос
/ 29 мая 2019

Ответ, как обычно бывает с JavaScript, звучит так: «Это немного страннее ...»

Использование памяти не определено, и любая реализация может быть глупой. Теоретически, const a = []; a[1000000]=0; может сжечь мегабайты памяти, как и const a = [];. На практике даже Microsoft избегает таких реализаций.

Джастин Лав указывает, что атрибут длины является набором индексов наивысший . НО только обновляется, если индекс является целым числом.

Итак, массив редкий. НО встроенные функции, такие как redu (), Math.max () и «for ... of», будут проходить через весь диапазон возможных целочисленных индексов от 0 до длины, посещая многие из них, которые возвращают «undefined». НО «for ... in» циклы могут делать, как вы ожидаете, посещая только определенные ключи.

Вот пример использования Node.js:

"use strict";
const print = console.log;

let a = [0, 10];
// a[2] and a[3] skipped
a[4] = 40;
a[5] = undefined;  // which counts towards setting the length
a[31.4] = 'ten pi';  // doesn't count towards setting the length
a['pi'] = 3.14;
print(`a.length= :${a.length}:, a = :${a}:`);
print(`Math.max(...a) = :${Math.max(a)}: because of 'undefined values'`);
for (let v of a) print(`v of a; v=:${v}:`);
for (let i in a) print(`i in a; i=:${i}: a[i]=${a[i]}`);

дает:

a.length= :6:, a = :0,10,,,40,:
Math.max(...a) = :NaN: because of 'undefined values'
v of a; v=:0:
v of a; v=:10:
v of a; v=:undefined:
v of a; v=:undefined:
v of a; v=:40:
v of a; v=:undefined:
i in a; i=:0: a[i]=0
i in a; i=:1: a[i]=10
i in a; i=:4: a[i]=40
i in a; i=:5: a[i]=undefined
i in a; i=:31.4: a[i]=ten pi
i in a; i=:pi: a[i]=3.14

Но. Есть еще несколько угловых случаев с массивами, которые еще не упомянуты.

...