Разница между JavaScript Array
и Object
не очень велика. На самом деле кажется, что Array
в основном добавляет поле length
, поэтому вы можете использовать как Array
s, так и Object
s как числовые массивы:
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
, и все объекты получают эвристику, чтобы увидеть, будет ли использование массива иметь больше смысла.- Что-то безумно сложное, до чего я не додумался.
На самом деле это было бы проще, если бы существовал правильный тип массива (cough WebGL типизированные массивы кашель).
length
. Если бы это было так, то смещение или несмещение нарушило бы индексацию (т. е. сместило бы значение из массива, и оно по-прежнему начинается с индекса 0, а не 1). Так что по крайней мере немного больше происходит. (Конечно, это не обязательно говорит о реализации) - person Flambino   schedule 11.02.2012r[0] == ob[0] == ar["0"] == ob["0"] == ar.bar == ob.bar
будет правдой?'a' == 'a' == 'a'
является ложным, потому что оно оценивается какtrue == 'a'
, которое оценивается какfalse
. - person Mike Samuel   schedule 11.02.2012shift
реализован как общий метод, а не специфичный для массива. Он будет отлично работать с обычным объектом. Сдвиг работает, потому что он захватывает первое значение, затем перебирает все значения, присваивая значение left, и, наконец, удаляет последний элемент и устанавливает длину. - person Mike Samuel   schedule 11.02.2012var a = { 0: 0, 1: 1, length: 2 }; Array.prototype.shift.apply(a); alert(JSON.stringify(a))
. Вы должны надежно получить{"0":1,"length":1}
. - person Mike Samuel   schedule 11.02.2012slice
дляarguments
объектов. Интересно - person Flambino   schedule 11.02.2012