То есть, если я использую текущее время в качестве индекса в массиве:
array[Date.getTime()] = value;
будет ли интерпретатор создавать экземпляры всех элементов от 0 до настоящего момента? Разные браузеры делают это по-разному?
Я помню, что раньше была ошибка в ядре AIX , которая создавала псевдо-tty по запросу, но если вы скажете «echo> / dev / pty10000000000», он создаст / dev / pty0, / dev / pty1, .... а затем упасть замертво. На выставках было весело, но я не хочу, чтобы это случилось с моими покупателями.
javascript
sparse-matrix
Ягода
источник
источник
Ответы:
Как именно реализованы массивы JavaScript, различается от браузера к браузеру, но обычно они возвращаются к разреженной реализации - скорее всего, той же, что используется для доступа к свойствам обычных объектов, - если использование фактического массива было бы неэффективным.
Вам нужно будет попросить кого-нибудь, кто лучше разбирается в конкретных реализациях, ответить, что именно вызывает переход от плотного к разреженному, но ваш пример должен быть совершенно безопасным. Если вы хотите получить плотный массив, вы должны вызвать конструктор с явным аргументом длины и надеяться, что вы действительно его получите.
См. Этот ответ для более подробного описания от olliej.
источник
foo = new Array(10000)
. Однако, это должно работать:foo = Array.apply(null, {length: 10});
.Да, они. На самом деле это внутренние хэш-таблицы, поэтому вы можете использовать не только большие целые числа, но также строки, числа с плавающей запятой или другие объекты. Все ключи преобразуются в строки
toString()
перед добавлением в хеш. Вы можете подтвердить это с помощью тестового кода:Отображает:
Обратите внимание, как я использовал
for...in
синтаксис, который дает вам только фактически определенные индексы. Если вы используете более распространенныйfor (var i = 0; i < array.length; ++i)
стиль итерации, у вас, очевидно, возникнут проблемы с нестандартными индексами массива.источник
length
свойствомlength
невидим только вfor..in
циклах, потому что у него установленDontEnum
флаг; в ES5 атрибут свойства вызываетсяenumerable
и может быть явно установлен черезObject.defineProperty()
String
; все, что вы добавляете в нижний индекс, получаетtoString()
-ed. Объедините это с неточностью целого числа большого числа, и это означает, что если вы установитеa[9999999999999999]=1
,a[10000000000000000]
будет 1 (и многие другие удивительные поведения). Использование нецелых чисел в качестве ключей очень неразумно, а произвольные объекты не подходят.Вы можете избежать этой проблемы, используя синтаксис javascript, предназначенный для такого рода вещей. Вы можете рассматривать его как словарь, но синтаксис «for ... in ...» позволит вам получить их все.
источник
Объекты Javascript разрежены, а массивы - это просто специализированные объекты с автоматически поддерживаемым свойством длины (которое на самом деле на единицу больше, чем наибольший индекс, а не количество определенных элементов) и некоторыми дополнительными методами. В любом случае вы в безопасности; используйте массив, если вам нужны дополнительные функции, и объект в противном случае.
источник
Ответ, как это обычно бывает с JavaScript, - «это немного сложнее ....»
Использование памяти не определено, и любая реализация может быть глупой. По идее
const a = []; a[1000000]=0;
мог бы сжечь мегабайты памяти, как могconst a = [];
. На практике даже Microsoft избегает таких реализаций.Джастин Лав указывает, что атрибут длины - это самый высокий индексный набор. НО он обновляется только в том случае, если индекс является целым числом.
Итак, массив разреженный. НО встроенные функции, такие как reduce (), Math.max () и "for ... of", будут проходить через весь диапазон возможных целочисленных индексов от 0 до длины, посещая многие из них, которые возвращают undefined. НО циклы for ... in могут работать так, как вы ожидаете, посещая только определенные ключи.
Вот пример использования Node.js:
давая:
Но. Есть еще не упомянутые еще случаи с массивами.
источник
Редкость (или плотность) для NodeJS можно подтвердить эмпирически с помощью нестандартного метода process.memoryUsage () .
Иногда узел достаточно умен, чтобы сохранить разреженный массив:
Иногда node решает сделать его плотным (это поведение вполне может быть оптимизировано в будущем):
Затем снова разреженный:
Поэтому, возможно, использование плотного массива, чтобы почувствовать исходную ошибку ядра AIX, может потребоваться принудительно с подобным диапазоном :
Почему бы не заставить его упасть?
источник
Они могут быть, но не всегда, и они могут работать лучше, когда это не так.
Вот обсуждение того, как проверить разреженность индекса в экземпляре массива: https://benmccormick.org/2018/06/19/code-golf-sparse-arrays/
Этот код победителя гольфа (наименьшее количество символов):
По
!!
сути, обход массива для индексированных записей с уменьшением значения длины и возвращением усиленного логического значения ложного / правдивого числового результата (если аккумулятор полностью уменьшен до нуля, индекс полностью заполнен, а не разрежен). Вышеупомянутые предостережения Чарльза Мерриама также следует учитывать, и этот код не обращается к ним, но они применяются к хешированным строковым записям, что может произойти при назначении элементов,arr[var]= (something)
где var не является целым числом.Причина, по которой нужно заботиться о разреженности индекса, заключается в его влиянии на производительность, которое может различаться для разных скриптовых движков, здесь большое обсуждение создания / инициализации массива: В чем разница между «Array ()» и «[]» при объявлении JavaScript массив?
В недавнем ответе на этот пост есть ссылка на подробное описание того, как V8 пытается оптимизировать массивы, помечая их, чтобы избежать (повторного) тестирования на такие характеристики, как разреженность: https://v8.dev/blog/elements-kinds . Сообщение в блоге от сентября 2017 года, и в него могут быть внесены некоторые изменения, но разбивка по значениям для повседневной разработки полезна и понятна.
источник