Являются ли массивы javascript фактически реализованы как массивы?

Разница между javascript Array и Object не очень велика. На самом деле кажется, что Array в основном добавляет поле length, поэтому вы можете использовать как Array, так и Object как числовые массивы:

var ar = new Array();
ar[0] = "foo";
ar["bar"] = "foo";

var ob = new Object();
ob[0] = "foo";
ob["bar"] = "foo";

assert(ar[0] == ob[0] == ar["0"] == ob["0"] == ar.bar == ob.bar); // Should be true.

Итак, мои вопросы касаются популярных движков javascript (V8, JavaScriptCore, SpiderMonkey и т.д.), как это обрабатывается? Очевидно, что мы не хотим, чтобы наши массивы были фактически сохранены в виде хеш-карт с ключевыми значениями! Как мы можем быть разумно уверены, что наши данные хранятся как фактический массив?

Насколько я вижу, есть несколько подходов, которые могут потребоваться машинами:

  • Array реализуется точно так же, как Object - как ассоциативный массив со строковыми ключами.
  • Array - это особый случай с массивом std::vector, поддерживающим числовые клавиши, и некоторой эвристикой плотности для предотвращения использования безумной памяти, если вы выполняете ar[100000000] = 0;
  • Array совпадает с Object, и все объекты получают эвристику, чтобы увидеть, будет ли использование массива более разумным.
  • Что-то безумно сложное, о котором я не думал.

Действительно, это было бы проще, если бы был правильный тип массива (кашель WebGL, типизированный массив кашля).

Ответы

Ответ 1

В SpiderMonkey массивы реализуются в основном как C-массивы jsvals. Они называются "плотными массивами". Однако, если вы начинаете делать с ними не-массивные вещи - например, рассматривая их как объекты - их реализация изменяется на нечто, очень похожее на объекты.

Мораль истории: когда вы хотите массив, используйте массив. Когда вы хотите объект, используйте объект.

О, jsval - это разновидность вариационного типа, которая может представлять любое возможное значение JavaScript в 64-битном типе C.

Ответ 2

В V8 и Каракане (и предположительно Chakra) все (не-хост) объекты (как те, которые являются массивами, и те, которые не являются) со свойствами, имена которых являются индексами массива (как определено в ES5), сохраняются как плотный массив (массив C, содержащий некоторую оболочку значений) или разреженный массив (который реализован как двоичное дерево поиска).

Отображение единого объекта показывает, что оно влияет на порядок перечисления: с объектом SpiderMonkey и SquirrelFish предоставляют все свойства в порядке вставки; и с массивом они вообще (в SM есть хотя бы отдельные случаи!) индексы массива сначала, а затем все остальные свойства в порядке вставки. V8, Каракан и Чакра всегда дают индексы массива сначала, а затем все остальные свойства в порядке вставки, независимо от типа объекта.