Массивы в JavaScript это не совсем то, к чему все привыкли в других языках. Точнее даже совсем не то. Массивы (здесь и далее массивы == массивы в JavaScript) порождаются конструктором Array
, наследующим Object
. От обычных объектов массивы отличаются тем, что специальным образом оперируют с числовыми свойствами и свойством length
.
Существует распространённое ошибочное мнение, что length
равно максимальному индексу в массиве плюс 1
. Но это лишь частный случай. В общем случае length
строго больше максимального индекса в массиве. Например, мы можем самостоятельно менять length
.
var a = [1, 2, 3];
a.length = 5;
alert(a.length + '; ' + [0 in a, 1 in a, 2 in a, 3 in a, 4 in a]); // 5; true,true,true,false,false
// Видим, что length равен 5, хотя элементов в массиве всего 3.
a.length = 1;
alert(a.length + '; ' + [0 in a, 1 in a, 2 in a, 3 in a, 4 in a]); // 1; true,false,false,false,false
// length уменьшилось и все элементы, индексы которых больше или равны length, были удалены.
Если взять определение объекта в JavaScript
Объект — это неупорядоченное множество пар ключ-значение.
То, в силу того, что массивы те же объекты, можно сказать, что массивы — это неупорядоченное множество пар ключ-значение с особой обработкой числовых ключей и свойства length
.
В общем случае невозможно узнать, сколько элементов в массиве, не перебирая их. Но в подавляющем большинстве случаев создаваемые массивы не имеют пропусков, и свойство length
у них вручную не изменяется, поэтому length
равно количеству элементов в массиве.
В JavaScript нет понятия многомерного массива, однако в самих массивах может содержаться что угодно, в том числе ссылки на другие массивы.
var a0 = [10, 11, 12];
var a1 = [20, 21, 22];
var a2 = [30, 31, 32];
var a = [a0, a1, a2];
alert(a[0]); // 10,11,12
alert(a[1]); // 20,21,22
alert(a[2]); // 30,31,32
Но не забывайте, что это всё-таки не многомерный массив, а массив массивов. В чём разница: двумерный массив, как частный случай многомерного, это матрица MxN, т.е., грубо говоря, таблица, из M строк и N столбцов. В каждой строке у неё одинаковое количество элементов, равно как и в каждом столбце. В JavaScript иначе, тут в массиве верхнего уровня лежат ссылки на другие произвольные массивы. Они могут быть одинакового размера, могут быть разного, а могут быть вообще не массивами. Многомерный массив — это нечто целое, массив массивов — это множество различных массивов, ссылки на которые лежат ещё в одном массиве.
var a = [
[1, 2, 3, 4, 5], // В этом подмассиве у нас пять чисел
['a', 'b', 'c'], // В этом подмассиве три строки
{foo: 'bar'} // А тут вообще объект
];
alert(a[0][2]); // 3
alert(a[1][1]); // b
alert(a[2].foo); // bar
alert(a[2]['foo']); // bar
Тем не менее при аккуратном использовании массив массивов может хорошо выполнять роль многомерного массива.
var a = [
['0x0', '0x1', '0x2', '0x3'],
['1x0', '1x1', '1x2', '1x3'],
['2x0', '2x1', '2x2', '2x3'],
['3x0', '3x1', '3x2', '3x3']
];
alert(a[2][1]); // 2x1
alert(a[3][3]); // 3x3
Как было сказано выше, массивы в JavaScript оперируют специальным образом только с числовыми свойствами и с length
. Со всеми остальными свойствами они ведут себя аналогично обычным объектам. Поэтому не следует использовать их в качестве ассоциативных массивов.
// Следующие "ассоциативные массивы" аналогичны
var a1 = [];
a1.foo = 'bar';
var a2 = new Number();
a2.foo = 'bar';
// Но лучше всё-таки так
var a3 = {};
a3.foo = 'bar';
// Или так
var a4 = {foo: 'bar'};