Московский физико-технический институт
Опубликован: 23.12.2005 | Доступ: свободный | Студентов: 2869 / 253 | Оценка: 4.61 / 4.44 | Длительность: 27:18:00
ISBN: 978-5-9556-0051-2
Лекция 4:

Контейнеры

Создание массива с помощью квадратных скобок

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

i = 1
a_array = [2, i, 0, 5, null];
i = 3;
// Обращаемся по номеру, записанному в переменной
trace("a[" + i + "] = " + a_array[i]);
// Выводим весь массив целиком
trace(a_array);

На выходе мы получим:

a[3] = 5
2,1,0,5,null

Все как и следовало ожидать. Заметьте, что функция trace легко смогла вывести весь массив целиком - на самом деле эта функция справится и с любым другим объектом, у которого определен метод toString(). То есть записи trace(a_array) и trace(a_array.toString()) эквивалентны.

А что будет, если записать нечто в индекс, который находится за пределами массива? Оказывается, все произойдет наилучшим образом: массив расширится как раз до тех пор, чтобы вместить новое поле. Впрочем, индекс должен быть целым и неотрицательным. При попытке что-либо прочесть из нецелого или отрицательного индекса мы получим undefined. Попытка записи в нецелый индекс за границей массива дает смешной результат: массив расширяется, но просто так, при обычном переборе нецелый индекс не виден. К нему можно обратиться лишь напрямую. Вот примеры всего этого: запускаем следующий код

a = [12, 22];
a[5] = 77;
trace("a = " + a);
b = [33, 44, 55];
b[-1] = 88;
trace("b = " + b);
trace("b[1.7] = " + b[1.7]);
trace("b[Math.ceil(1.7)] = " + b[Math.ceil(1.7)]);
trace("b[8] = " + b[8]);
a[9.81] = 333;
trace("a = " + a);
trace("a[9.81] = " + a[9.81]);

и получаем:

a = 12,22,,,,77
b = 33,44,55
b[1.7] =
b[Math.ceil(1.7)] = 55
b[8] =
a = 12,22,,,,77,,,,
a[9.81] = 333

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

Многомерные массивы, создание массива "на лету"

А вот как делаются во Флэш МХ многомерные массивы:

i = 7;
a_array = [[i, i+1], [i+2, i+3], [1, 2], [3, 4, 5, 6], "aaaaaaa"];
// Обращаемся к конкретному элементу
trace("a_array[1][1] = " + a_array[1][1]);
// Выводим подмассив
trace("a_array[3] = " + a_array[3]);
// Выводим список всех элементов субмассивов
trace("a_array = " + a_array);
// Создание массива "на лету"
trace([100, 23, -3]);

Приведенный здесь код выводит:

a_array[1][1] = 10
a_array[3] = 3,4,5,6
a_array = 7,8,9,10,1,2,3,4,5,6,aaaaaaa
100,23,-3

Из этого примера можно заключить, что многомерный массив во Флэше не является специальным случаем массива (как и в C/C++). Более того, вовсе не каждый элемент многомерного массива в свою очередь должен являться массивом. Просто каждый элемент массива может быть объектом любого типа - примитивного или нет. В том числе - другим массивом.

Однако с этой точки зрения строчка

a_array = [[i, i+1], [i+2, i+3], [1, 2], [3, 4, 5, 6], "aaaaaaa"];

выглядит так, как будто субмассивы были созданы прямо по ходу дела - вместо записи вида

temp1_array = [i, i+1];
temp2_array = [i+2, i+3];
temp3_array = [1,2];
temp4_array = [3, 4, 5, 6];
a_array = [temp1_array, temp2_array, temp3_array, temp4_array,
   "aaaaaaa"];

То есть возникает впечатление, что создать массив можно прямо "на лету", внутри любой части какого-нибудь выражения. Это подтверждает последняя строчка вышеприведенного примера: trace([100, 23, -3]); действительно выводит содержание созданного прямо внутри функции trace массива. Более того, следующий код, на первый взгляд кажущийся безумным, также компилируется и работает:

trace(([1, 2, 3])[2])
trace([1, 2, 3][0])
trace([10][0])
trace([3,7, 2, -1].sort())

Выводит он

3
1
10
-1,2,3,7

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

Напоследок - нечто, более напоминающее загадку, чем имеющее какой-либо практический смысл. Что выводит следующая строка: trace([1, 2, 3, 4, 5][2, 0, 7, 3]);? Если ответ не сразу приходит вам в голову, то попробуйте разгадать, почему в результате выполнения этой строчки печатается 4? Разгадка же состоит в том, что Флэш лишь первые квадратные скобки воспринимает как указание создать массив. Вторые (увидев, что массив слева от них уже стоит) он воспринимает как обращение к ячейке массива. А выражение внутри них - как определяющее индекс этой ячейки. Вычислив это выражение (по правилам пользования операцией "запятая"), он получает, что оно равно самому правому числу в последовательности, то есть 3. А элемент массива, к которому мы обращаемся, имеющий индекс 3, - это и есть четверка.