Во Флэш МХ имеется встроенная библиотечка объектов-контейнеров. Обычно в библиотеках контейнеров (такой, например, как стандартная библиотека С++) можно найти контейнеры, оптимизированные для всех случаев жизни - по скорости выполнения самых разных операций, по занимаемой памяти и пр. Создатели Флэша поступили проще: они, резонно полагая, что главная оптимизация состоит в использовании заранее скомпилированного компонента, предлагают нам для большинства задач один универсальный контейнер. Это класс Array. Однако, судя по названию, основной его задачей является играть роль
Сейчас мы рассмотрим все способы создания
Во Флэше версии 4 настоящих
for (var i=0; i<5; i++) set("a" + i, 5*i + 1);
// Обращаемся к конкретному элементу
trace("a2 = " + a2);
i = 4;
// Обращаемся по номеру, записанному в переменной
trace("a" + i + " = " + eval("a" + i));
Выводит этот код (который, правда, напрямую перенести во Флэш 4 нельзя - мы хотя и не использовали
a2 = 11 a4 = 21
Во Флэш МХ делать подобные вещи смысла не имеет. (Хотя генерация серий имен, бывает, применяется при создании наборов похожих клипов.) Гораздо лучше пользоваться встроенным объектом типа Array.
Создать объект типа Array можно, например, так (на выбор целых три способа):
a_array = new Array(2,3,"AAA",4,8);
b_array = new Array(10);
c_array = new Array();
// Обращаемся к конкретному элементу
trace("a_array[1] = " + a_array[1]);
i = 3;
// Обращаемся по номеру, записанному в переменной
trace("a_array[" + i + "] = " + a_array[i]);
c_array[7] = 9;
// Длину массива можно узнать, обратившись к специальному
// свойству length
trace("a_array.length = " + a_array.length);
trace("b_array.length = " + b_array.length);
trace("c_array.length = " + c_array.length);
Выводит этот код следующее:
a_array[1] = 3 a_array[3] = 4 a_array.length = 5 b_array.length = 10 c_array.length = 8
Посмотрим также, какие переменные заведены в программе (надо после запуска на исполнение нажать Ctrl+Alt+V ). Получим:
Level #0: Variable _level0.$version = "WIN 6,0,21,0" Variable _level0.a_array = [object #1, class 'Array'] [ 0:2, 1:3, 2:"AAA", 3:4, 4:8 ] Variable _level0.b_array = [object #2, class 'Array'] [] Variable _level0.c_array = [object #3, class 'Array'] [ 7:9 ] Variable _level0.i = 3
Итак, с точки зрения С++ или Java класс Array имеет три разных конструктора. Один из них - тот, в который передается больше одного аргумента - создает
Заодно, на этих примерах мы убедились, что во Флэш МХ, как и в C++ и Java,
Обратите внимание, что в названии наших _array. Это позволяет нам пользоваться Array.
Однако необязательно создавать 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
Из этого примера можно заключить, что
Однако с этой точки зрения строчка
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? Разгадка же состоит в том, что Флэш лишь первые квадратные скобки воспринимает как указание создать
Алгоритмы
Попробуем отсортировать числовой
a_array = [3, 0.5, +3, -3, 1e12, 1e-12, 12, 112]; a_array.sort(); trace(a_array);
На выходе получаем:
-3,0.5,1000000000000,112,12,1e-12,3,3
Видно, что метод sort() (в отличие от многих методов
a_array.sort(function(a,b){return a-b;});
Тогда на выходе действительно будет
-3,1e-12,0.5,3,3,12,112,1000000000000
О том, что на самом деле означает строчка a_array.sort(function(a,b){return a-b;});, вы узнаете чуть позднее. Впрочем, уже ясно, что для a_array.sort(function(a,b){return b-a;});. Также приятное известие состоит в том, что в ActionScript 2 рассматриваемая проблема решена - в метод sort можно передавать набор управляющих флагов, один из которых (Array.NUMERIC) командует трактовать содержимое
Но зато с
s_array = ["bulb", "bulb.", "c", "CC", "ground"]; s_array.sort(); trace(s_array);
и получаем в результате
CC,bulb,bulb.,c,ground
А как нам отсортировать Array.DESCENDING. Нам же придется сделать a_array.reverse();
Если в Array.sortOn ):
a_array = [{name:"aa", info:112}, {name:"bb", info: 23},
{name: "ba", info:1e-5}];
a_array.sortOn("name");
for (var i=0; i<a_array.length; i++){
trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
trace("---------");
a_array.sortOn("info");
for (var i=0; i<a_array.length; i++){
trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
На выходе получим:
{aa, 112}
{ba, 0.00001}
{bb, 23}
---------
{ba, 0.00001}
{aa, 112}
{bb, 23}
Видим, что непорядок с sortOn не имеет дополнительных параметров - в нее нельзя передать функцию name (или info при info ) не будет, он попадет в начало undefined. В свою очередь, при преобразовании undefined в строчку, получится пустая
Мы уже слегка касались возможности сортировать info. Вот как это делается:
a_array = [{name:"aa", info:112}, {name:"bb", info: 23},
{name: "ba", info:1e-5}];
// Это еще один способ определить функцию;
// подробнее он будет описан позднее
function sortFunc(o1, o2){return o1.info - o2.info;}
a_array.sort(sortFunc);
for (var i=0; i<a_array.length; i++){
trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
На выходе получаем:
{ba, 0.00001}
{bb, 23}
{aa, 112}
Вот теперь порядок правильный!
Как мы уже говорили,
Функциональность , slice и concat. Собственно говоря, специфичной для Array.
Начнем с удаления и вставки элементов. В объекте Array для этого служит метод , название которого переводится как "соединять внахлест" - например, магнитную ленту. (Есть, конечно, и другие переводы, но этот - самый подходящий.) В этот метод может передаваться произвольное количество аргументов. Первый аргумент - индекс элемента, начиная с которого надо производить удаление. Второй - количество удаляемых элементов (это может быть ноль). Последующие аргументы - это элементы, которые надо вставить на место удаленных. Возвращает метод субмассив удаленных элементов (а вовсе не "ничего", как написано в
a_array = ["zero", "one", "two", "three", "four"];
trace("Splice returns: " + a_array.splice(1, 3, 0, 1, 2));
trace("a_array: " + a_array);
trace("---------------");
trace("Splice returns: " + a_array.splice(1, 0, 0, 1, 2));
trace("a_array: " + a_array);
выводит в консоль
Splice returns: one,two,three a_array: zero,0,1,2,four --------------- Splice returns: a_array: zero,0,1,2,0,1,2,four
Отметим, что если из .
Следующий метод, который мы рассмотрим - это slice. Он принимает два аргумента: индекс начала субмассива и индекс конца. Причем, элемент, имеющий индекс конца, в возвращаемый субмассив не включается. В отличие от , метод slice не изменяет исходный
a_array = ["zero", "one", "two", "three", "four"];
trace("Slice returns: " + a_array.slice(2, 4));
trace("a_array = " + a_array);
trace("The biggest slice: " + a_array.slice(0, a_array.length));
выводит в консоль
Slice returns: two,three a_array = zero,one,two,three,four The biggest slice: zero,one,two,three,four
Обратите внимание: последний вариант применения slice - в вызове a_array.slice(0, a_array.length) - позволяет нам получить копию
Наконец, рассмотрим метод concat. Этот метод соединяет в один concat ) при этом не изменяется; в результирующем concat:
a_array = ["zero", "one", "two", "three", "four"];
b_array = a_array.concat(3, ["a", "b"], 10, [0, [1, 2], 3]);
trace("a_array = " + a_array);
trace("b_array = " + b_array);
trace("b_array[10] = " + b_array[10]);
На выходе получаем:
a_array = zero,one,two,three,four b_array = zero,one,two,three,four,3,a,b,10,0,1,2,3 b_array[10] = 1,2
Обратите внимание на последний вызов trace. Мы проверили, что concat.
С эмуляцией Array есть методы push и pop. Единственный вопрос, который может возникнуть, - если мы захотим совместить функциональность push? В начале или в конце
electro_array = ["Резистор", "Диод"];
trace(electro_array.push("Транзистор", "Тиристор", "Дроссель"));
trace(electro_array);
trace(electro_array.pop());
trace(electro_array);
На выходе получаем:
5 Резистор,Диод,Транзистор,Тиристор,Дроссель Дроссель Резистор,Диод,Транзистор,Тиристор
Итак, элементы добавляются в конец push возвращает длину
Чтобы эмулировать shift - он аналогичен методу pop, но действует с другого конца pop. В таком случае нам понадобится помещать элементы в начало unshift. Таким образом, мы можем использовать ). Мы даже можем устроить shift и unshift, хотя есть подозрения, что он будет работать чуть медленнее обычного. Вот примеры использования всех этих методов: мы сначала двигаем
electro_array = ["Резистор", "Диод"];
trace("electro_array: " + electro_array);
trace("push returns: " + electro_array.push("Транзистор",
"Тиристор", "Дроссель"));
trace("electro_array: " + electro_array);
trace("shift returns: " + electro_array.shift());
trace("shift returns: " + electro_array.shift());
trace("electro_array: " + electro_array);
trace("unshift returns: " + electro_array.unshift("Конденсатор",
"Микропроцессор"));
trace("electro_array: " + electro_array);
trace("pop returns: " + electro_array.pop());
trace("pop returns: " + electro_array.pop());
trace("electro_array: " + electro_array);
На выходе имеем:
electro_array: Резистор,Диод push returns: 5 electro_array: Резистор,Диод,Транзистор,Тиристор,Дроссель shift returns: Резистор shift returns: Диод electro_array: Транзистор,Тиристор,Дроссель unshift returns: 5 electro_array: Конденсатор,Микропроцессор,Транзистор, Тиристор,Дроссель pop returns: Дроссель pop returns: Тиристор electro_array: Конденсатор,Микропроцессор,Транзистор
Мы уже знаем, что можно обращаться к полям объекта удобным, но недокументированным способом - при помощи квадратных скобок. Нужно только иметь имя этого поля в виде
obj1 = {};
obj1["aaa"] = 1;
obj1["bbb"] = 2;
obj1[4] = 1000;
obj1[4.00001e-17] = 1000000;
obj1["!@#$%%^*()_):"] = 222;
trace(obj1["bb" + "b"]);
trace(obj1[10*(4 + 0.00001)/1e18]);
trace(obj1["!@#$%%^*()_):"]);
Запустив это, на выходе получаем
2 1000000 222
А теперь давайте скомандуем List Variables ( Ctrl+Alt+V ). Результат:
Level #0:
Variable _level0.$version = "WIN 6,0,21,0"
Variable _level0.obj1 = [object #1, class 'Object'] {
aaa:1,
bbb:2,
4:1000,
4.00001e-17:1000000,
!@#$%%^*()_)::222
}
Так что любой объект является самой настоящей push или sort, а в
Давайте для разрешения этих вопросов сделаем такой "смешанный"
a_array = [23, 45, 67, 88];
a_array["kk"] = 345;
a_array[-1] = 3333333;
a_array.push(100);
trace("a_array: " + a_array);
trace("a_array.length: " + a_array.length);
// Выводим кусок побольше, чтобы посмотреть, не прячется ли
// что-то за дальней границей массива
trace("a_array.slice(2,6): " + a_array.slice(2,6));
trace("----- Names -----");
for(var name in a_array) trace(name);
trace("----------------");
trace(a_array["kk"]);
Вот что выводит этот код:
a_array: 23,45,67,88,100 a_array.length: 5 a_array.slice(2,6): 67,88,100 ----- Names ----- 4 -1 kk 3 2 1 0 ---------------- 345
А вот что мы получаем после команды List Variables
Level #0: Variable _level0.$version = "WIN 6,0,21,0" Variable _level0.a_array = [object #1, class 'Array'] [ 0:23, 1:45, 2:67, 3:88, 4:100, kk:345, -1:3333333 ] Variable _level0.name = "0"
В результате можно сделать следующие выводы. length ) корректируется только с учетом таких ключей. Так что достать из kk в вышеприведенном коде, то обращаться к хранящейся по этому ключу информации можно и
через точку: a_array.kk ).
Работа со
Мы уже создавали
Во Флэше есть несколько способов создать примитивную
Еще один способ обзавестись примитивной
| Escape-последовательность | Символ |
|---|---|
\b |
Backspace ("забой") (ASCII 8) |
\f |
Form-feed (знак смещения бланка) (ASCII 12) |
\n |
Line-feed (перевод строки) (ASCII 10) |
\r |
|
\t |
Символ табуляции (ASCII 9) |
\" |
Двойная кавычка |
\' |
Одинарная кавычка |
\\ |
Обратный слэш |
\000 - \377 |
Символ в восьмеричном коде |
\x00 - \xFF |
Символ в шестнадцатеричном коде |
\u0000 - \uFFFF |
16-битовый символ Unicode (в шестнадцатеричном коде) |
Последний способ получить примитивную String, служащей для преобразования в строковый тип. Работает эта функция достаточно очевидным образом. Для чисел возвращает соответствующую строчку с десятичной записью числа (возможно, с плавающей точкой). Для булевых выражений выдает " true " или " false ". В случае undefined возвращает пустую toString. По этим же правилам производится преобразование в строчку и тогда, когда оно совершается неявно (например, при передаче аргумента строкового типа или в случае прибавления какого-либо выражения к
А вот конструкция new String(выражение) создает
Изредка возникает проблема: нужно написать очень длинную +. А можно - поставив обратный слэш, как в С++. Правда, имеется проблема с использованием последнего способа: слэши остаются в
Сейчас мы кратко опишем функциональность каждого из методов класса String во Флэш. Все эти методы работают как с объектными, так и с примитивными trace("my name".toUpperCase()), и это действительно выведет на печать MY NAME, хотя подобный код и нельзя назвать хорошо читаемым.
Итак, методы charAt и charCodeAt позволяют получить символ и его код по заданному индексу; метод concat присоединяет к нашей indexOf и позволяют находить slice, substr и substring позволяют разными способами выделять toUpperCase и toLowerCase переводят все буквы в заглавный или строчный регистр; наконец, метод split разбивает String.fromCharCode. Он является чем-то вроде статического метода класса String и не нуждается в объекте строкового типа для своего вызова. Чтобы вызвать этот метод, нужно так и написать: String.fromCharCode, а в качестве аргументов передать один или несколько кодов символов, из которых и будет сформирована
Конечно, этого краткого описания недостаточно для уверенной работы со split. Метод split настолько хорош и полезен, что пример его применения мы выделим отдельно и опишем в следующем подпараграфе. Все же прочие примеры представлены в следующем коде:
a_str = "Очень длинная строка";
trace(
"a_str.toLowerCase() = " +
a_str.toLowerCase()
); // Переводим строку в нижний регистр
trace(
"a_str.toUpperCase() = " +
a_str.toUpperCase()
); // Переводим строку в верхний регистр
trace("");
trace(
"a_str.charAt(3) = " +
a_str.charAt(3)
); // Буква "н"
trace(
"a_str.charCodeAt(5) = " +
a_str.charCodeAt(5)
); // Код пробела
trace("");
trace(
"a_str.concat(', да-да. ', a_str) = \n\t" +
a_str.concat(', да-да. ', a_str)
);
trace("");
trace(
"String.fromCharCode(46, 56, 74, 34, 45) = " +
String.fromCharCode(46, 56, 74, 34, 45)
);
trace("");
trace(
"a_str.indexOf('н') = " +
a_str.indexOf('н')
); // Первая буква "н"
trace(
"a_str.indexOf('нн') = " +
a_str.indexOf('нн')
); // Первое (оно же и последнее) сочетание букв "нн"
trace(
"a_str.lastIndexOf('н') = " +
a_str.lastIndexOf('н')
); // Последняя буква "н"
trace(
"a_str.lastIndexOf('нн') = " +
a_str.lastIndexOf('нн')
); // Последнее (оно же первое) сочетание букв "нн"
trace(
"a_str.indexOf('н', 6) = " +
a_str.indexOf('н', 6)
); // Первая буква "н" после 6-й позиции (или на 6-й).
trace(
"a_str.lastIndexOf('н', 6) = " +
a_str.lastIndexOf('н', 6)
); // Последняя буква "н" перед 6-й позицией (или на 6-й).
trace("-------------");
/* Несколько примеров на метод slice */
/* Он работает так же, как аналогичный метод в массиве */
trace(
"a_str.slice(8, 12) = " +
a_str.slice(8, 12)
); // Кусок строки в районе букв "нн"
trace(
"a_str.slice(8, 3) = " +
a_str.slice(8, 3)
); // Если второй аргумент меньше первого, но положителен,
// возвращается пустая строка.
trace(
"a_str.slice(8, -3) = " +
a_str.slice(8, -3)
); // Если второй аргумент отрицателен,
// отсчитываем от конца строки назад.
trace("-------------");
/* Посмотрим, чем от slice отличается substring */
trace(
"a_str.substring(8, 12) = " +
a_str.substring(8, 12)
); // Тот же результат, что и для slice
trace(
"a_str.substring(8, 3) = " +
a_str.substring(8, 3)
); // Если второй аргумент меньше первого,
// аргументы меняются местами
trace(
"a_str.substring(8, -3) = " +
a_str.substring(8, -3)
); // Если любой из аргументов отрицателен,
// он заменяется нулем. Затем, если нужно,
// аргументы меняются местами
trace("-------------");
/* Еще один метод выделения подстроки: substr */
trace(
"a_str.substr(8, 3) = " +
a_str.substr(8, 3)
); // Здесь второй аргумент задает длину подстроки.
trace(
"a_str.substr(8) = " +
a_str.substr(8)
); // Если же второй аргумент вовсе не передавать,
// то подстрока берется до конца строки
// substring и slice в этом случае работают точно так же.
Этот длинный код выводит следующий длинный текст:
a_str.toLowerCase() = очень длинная строка
a_str.toUpperCase() = ОЧЕНЬ ДЛИННАЯ СТРОКА
a_str.charAt(3) = н
a_str.charCodeAt(5) = 32
a_str.concat(', да-да. ', a_str) =
Очень длинная строка, да-да. Очень длинная строка
String.fromCharCode(46, 56, 74, 34, 45) = .8J"-
a_str.indexOf('н') = 3
a_str.indexOf('нн') = 9
a_str.lastIndexOf('н') = 10
a_str.lastIndexOf('нн') = 9
a_str.indexOf('н', 6) = 9
a_str.lastIndexOf('н', 6) = 3
-------------
a_str.slice(8, 12) = инна
a_str.slice(8, 3) =
a_str.slice(8, -3) = инная стр
-------------
a_str.substring(8, 12) = инна
a_str.substring(8, 3) = нь дл
a_str.substring(8, -3) = Очень дл
-------------
a_str.substr(8, 3) = инн
a_str.substr(8) = инная строка
Обратите внимание на разницу в работе slice, substring и substr. Примеры демонстрируют эту разницу для всех случаев, которые могут быть важны на практике. Интересно также, что существует (объявленная устаревшей) глобальная функция substring, которой в качестве первого аргумента передается substr класса String (а вовсе не как метод substring, как могло бы показаться из-за совпадения названий)!
Нерассмотренным у нас пока остался простой, но существенный вопрос: а как узнать длину length.
Согласитесь, что сделать простую замену split, для данной join, а в качестве "склеивающей"
text_str = "Мы любим буги-вуги, мы танцуем только буги";
new_str = text_str.split("уги").join("аги");
trace("text_str = " + text_str);
trace("new_str = " + new_str);
В результате действительно получаем:
text_str = Мы любим буги-вуги, мы танцуем только буги new_str = Мы любим баги-ваги, мы танцуем только баги
Во Флэш МХ имеется встроенная библиотечка объектов-контейнеров. Обычно в библиотеках контейнеров (такой, например, как стандартная библиотека С++) можно найти контейнеры, оптимизированные для всех случаев жизни - по скорости выполнения самых разных операций, по занимаемой памяти и пр. Создатели Флэша поступили проще: они, резонно полагая, что главная оптимизация состоит в использовании заранее скомпилированного компонента, предлагают нам для большинства задач один универсальный контейнер. Это класс Array. Однако, судя по названию, основной его задачей является играть роль
Сейчас мы рассмотрим все способы создания
Во Флэше версии 4 настоящих
for (var i=0; i<5; i++) set("a" + i, 5*i + 1);
// Обращаемся к конкретному элементу
trace("a2 = " + a2);
i = 4;
// Обращаемся по номеру, записанному в переменной
trace("a" + i + " = " + eval("a" + i));
Выводит этот код (который, правда, напрямую перенести во Флэш 4 нельзя - мы хотя и не использовали
a2 = 11 a4 = 21
Во Флэш МХ делать подобные вещи смысла не имеет. (Хотя генерация серий имен, бывает, применяется при создании наборов похожих клипов.) Гораздо лучше пользоваться встроенным объектом типа Array.
Создать объект типа Array можно, например, так (на выбор целых три способа):
a_array = new Array(2,3,"AAA",4,8);
b_array = new Array(10);
c_array = new Array();
// Обращаемся к конкретному элементу
trace("a_array[1] = " + a_array[1]);
i = 3;
// Обращаемся по номеру, записанному в переменной
trace("a_array[" + i + "] = " + a_array[i]);
c_array[7] = 9;
// Длину массива можно узнать, обратившись к специальному
// свойству length
trace("a_array.length = " + a_array.length);
trace("b_array.length = " + b_array.length);
trace("c_array.length = " + c_array.length);
Выводит этот код следующее:
a_array[1] = 3 a_array[3] = 4 a_array.length = 5 b_array.length = 10 c_array.length = 8
Посмотрим также, какие переменные заведены в программе (надо после запуска на исполнение нажать Ctrl+Alt+V ). Получим:
Level #0: Variable _level0.$version = "WIN 6,0,21,0" Variable _level0.a_array = [object #1, class 'Array'] [ 0:2, 1:3, 2:"AAA", 3:4, 4:8 ] Variable _level0.b_array = [object #2, class 'Array'] [] Variable _level0.c_array = [object #3, class 'Array'] [ 7:9 ] Variable _level0.i = 3
Итак, с точки зрения С++ или Java класс Array имеет три разных конструктора. Один из них - тот, в который передается больше одного аргумента - создает
Заодно, на этих примерах мы убедились, что во Флэш МХ, как и в C++ и Java,
Обратите внимание, что в названии наших _array. Это позволяет нам пользоваться Array.
Однако необязательно создавать 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
Из этого примера можно заключить, что
Однако с этой точки зрения строчка
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? Разгадка же состоит в том, что Флэш лишь первые квадратные скобки воспринимает как указание создать
Алгоритмы
Попробуем отсортировать числовой
a_array = [3, 0.5, +3, -3, 1e12, 1e-12, 12, 112]; a_array.sort(); trace(a_array);
На выходе получаем:
-3,0.5,1000000000000,112,12,1e-12,3,3
Видно, что метод sort() (в отличие от многих методов
a_array.sort(function(a,b){return a-b;});
Тогда на выходе действительно будет
-3,1e-12,0.5,3,3,12,112,1000000000000
О том, что на самом деле означает строчка a_array.sort(function(a,b){return a-b;});, вы узнаете чуть позднее. Впрочем, уже ясно, что для a_array.sort(function(a,b){return b-a;});. Также приятное известие состоит в том, что в ActionScript 2 рассматриваемая проблема решена - в метод sort можно передавать набор управляющих флагов, один из которых (Array.NUMERIC) командует трактовать содержимое
Но зато с
s_array = ["bulb", "bulb.", "c", "CC", "ground"]; s_array.sort(); trace(s_array);
и получаем в результате
CC,bulb,bulb.,c,ground
А как нам отсортировать Array.DESCENDING. Нам же придется сделать a_array.reverse();
Если в Array.sortOn ):
a_array = [{name:"aa", info:112}, {name:"bb", info: 23},
{name: "ba", info:1e-5}];
a_array.sortOn("name");
for (var i=0; i<a_array.length; i++){
trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
trace("---------");
a_array.sortOn("info");
for (var i=0; i<a_array.length; i++){
trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
На выходе получим:
{aa, 112}
{ba, 0.00001}
{bb, 23}
---------
{ba, 0.00001}
{aa, 112}
{bb, 23}
Видим, что непорядок с sortOn не имеет дополнительных параметров - в нее нельзя передать функцию name (или info при info ) не будет, он попадет в начало undefined. В свою очередь, при преобразовании undefined в строчку, получится пустая
Мы уже слегка касались возможности сортировать info. Вот как это делается:
a_array = [{name:"aa", info:112}, {name:"bb", info: 23},
{name: "ba", info:1e-5}];
// Это еще один способ определить функцию;
// подробнее он будет описан позднее
function sortFunc(o1, o2){return o1.info - o2.info;}
a_array.sort(sortFunc);
for (var i=0; i<a_array.length; i++){
trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
На выходе получаем:
{ba, 0.00001}
{bb, 23}
{aa, 112}
Вот теперь порядок правильный!
Как мы уже говорили,
Функциональность , slice и concat. Собственно говоря, специфичной для Array.
Начнем с удаления и вставки элементов. В объекте Array для этого служит метод , название которого переводится как "соединять внахлест" - например, магнитную ленту. (Есть, конечно, и другие переводы, но этот - самый подходящий.) В этот метод может передаваться произвольное количество аргументов. Первый аргумент - индекс элемента, начиная с которого надо производить удаление. Второй - количество удаляемых элементов (это может быть ноль). Последующие аргументы - это элементы, которые надо вставить на место удаленных. Возвращает метод субмассив удаленных элементов (а вовсе не "ничего", как написано в
a_array = ["zero", "one", "two", "three", "four"];
trace("Splice returns: " + a_array.splice(1, 3, 0, 1, 2));
trace("a_array: " + a_array);
trace("---------------");
trace("Splice returns: " + a_array.splice(1, 0, 0, 1, 2));
trace("a_array: " + a_array);
выводит в консоль
Splice returns: one,two,three a_array: zero,0,1,2,four --------------- Splice returns: a_array: zero,0,1,2,0,1,2,four
Отметим, что если из .
Следующий метод, который мы рассмотрим - это slice. Он принимает два аргумента: индекс начала субмассива и индекс конца. Причем, элемент, имеющий индекс конца, в возвращаемый субмассив не включается. В отличие от , метод slice не изменяет исходный
a_array = ["zero", "one", "two", "three", "four"];
trace("Slice returns: " + a_array.slice(2, 4));
trace("a_array = " + a_array);
trace("The biggest slice: " + a_array.slice(0, a_array.length));
выводит в консоль
Slice returns: two,three a_array = zero,one,two,three,four The biggest slice: zero,one,two,three,four
Обратите внимание: последний вариант применения slice - в вызове a_array.slice(0, a_array.length) - позволяет нам получить копию
Наконец, рассмотрим метод concat. Этот метод соединяет в один concat ) при этом не изменяется; в результирующем concat:
a_array = ["zero", "one", "two", "three", "four"];
b_array = a_array.concat(3, ["a", "b"], 10, [0, [1, 2], 3]);
trace("a_array = " + a_array);
trace("b_array = " + b_array);
trace("b_array[10] = " + b_array[10]);
На выходе получаем:
a_array = zero,one,two,three,four b_array = zero,one,two,three,four,3,a,b,10,0,1,2,3 b_array[10] = 1,2
Обратите внимание на последний вызов trace. Мы проверили, что concat.
С эмуляцией Array есть методы push и pop. Единственный вопрос, который может возникнуть, - если мы захотим совместить функциональность push? В начале или в конце
electro_array = ["Резистор", "Диод"];
trace(electro_array.push("Транзистор", "Тиристор", "Дроссель"));
trace(electro_array);
trace(electro_array.pop());
trace(electro_array);
На выходе получаем:
5 Резистор,Диод,Транзистор,Тиристор,Дроссель Дроссель Резистор,Диод,Транзистор,Тиристор
Итак, элементы добавляются в конец push возвращает длину
Чтобы эмулировать shift - он аналогичен методу pop, но действует с другого конца pop. В таком случае нам понадобится помещать элементы в начало unshift. Таким образом, мы можем использовать ). Мы даже можем устроить shift и unshift, хотя есть подозрения, что он будет работать чуть медленнее обычного. Вот примеры использования всех этих методов: мы сначала двигаем
electro_array = ["Резистор", "Диод"];
trace("electro_array: " + electro_array);
trace("push returns: " + electro_array.push("Транзистор",
"Тиристор", "Дроссель"));
trace("electro_array: " + electro_array);
trace("shift returns: " + electro_array.shift());
trace("shift returns: " + electro_array.shift());
trace("electro_array: " + electro_array);
trace("unshift returns: " + electro_array.unshift("Конденсатор",
"Микропроцессор"));
trace("electro_array: " + electro_array);
trace("pop returns: " + electro_array.pop());
trace("pop returns: " + electro_array.pop());
trace("electro_array: " + electro_array);
На выходе имеем:
electro_array: Резистор,Диод push returns: 5 electro_array: Резистор,Диод,Транзистор,Тиристор,Дроссель shift returns: Резистор shift returns: Диод electro_array: Транзистор,Тиристор,Дроссель unshift returns: 5 electro_array: Конденсатор,Микропроцессор,Транзистор, Тиристор,Дроссель pop returns: Дроссель pop returns: Тиристор electro_array: Конденсатор,Микропроцессор,Транзистор
Мы уже знаем, что можно обращаться к полям объекта удобным, но недокументированным способом - при помощи квадратных скобок. Нужно только иметь имя этого поля в виде
obj1 = {};
obj1["aaa"] = 1;
obj1["bbb"] = 2;
obj1[4] = 1000;
obj1[4.00001e-17] = 1000000;
obj1["!@#$%%^*()_):"] = 222;
trace(obj1["bb" + "b"]);
trace(obj1[10*(4 + 0.00001)/1e18]);
trace(obj1["!@#$%%^*()_):"]);
Запустив это, на выходе получаем
2 1000000 222
А теперь давайте скомандуем List Variables ( Ctrl+Alt+V ). Результат:
Level #0:
Variable _level0.$version = "WIN 6,0,21,0"
Variable _level0.obj1 = [object #1, class 'Object'] {
aaa:1,
bbb:2,
4:1000,
4.00001e-17:1000000,
!@#$%%^*()_)::222
}
Так что любой объект является самой настоящей push или sort, а в
Давайте для разрешения этих вопросов сделаем такой "смешанный"
a_array = [23, 45, 67, 88];
a_array["kk"] = 345;
a_array[-1] = 3333333;
a_array.push(100);
trace("a_array: " + a_array);
trace("a_array.length: " + a_array.length);
// Выводим кусок побольше, чтобы посмотреть, не прячется ли
// что-то за дальней границей массива
trace("a_array.slice(2,6): " + a_array.slice(2,6));
trace("----- Names -----");
for(var name in a_array) trace(name);
trace("----------------");
trace(a_array["kk"]);
Вот что выводит этот код:
a_array: 23,45,67,88,100 a_array.length: 5 a_array.slice(2,6): 67,88,100 ----- Names ----- 4 -1 kk 3 2 1 0 ---------------- 345
А вот что мы получаем после команды List Variables
Level #0: Variable _level0.$version = "WIN 6,0,21,0" Variable _level0.a_array = [object #1, class 'Array'] [ 0:23, 1:45, 2:67, 3:88, 4:100, kk:345, -1:3333333 ] Variable _level0.name = "0"
В результате можно сделать следующие выводы. length ) корректируется только с учетом таких ключей. Так что достать из kk в вышеприведенном коде, то обращаться к хранящейся по этому ключу информации можно и
через точку: a_array.kk ).
Работа со
Мы уже создавали
Во Флэше есть несколько способов создать примитивную
Еще один способ обзавестись примитивной
| Escape-последовательность | Символ |
|---|---|
\b |
Backspace ("забой") (ASCII 8) |
\f |
Form-feed (знак смещения бланка) (ASCII 12) |
\n |
Line-feed (перевод строки) (ASCII 10) |
\r |
|
\t |
Символ табуляции (ASCII 9) |
\" |
Двойная кавычка |
\' |
Одинарная кавычка |
\\ |
Обратный слэш |
\000 - \377 |
Символ в восьмеричном коде |
\x00 - \xFF |
Символ в шестнадцатеричном коде |
\u0000 - \uFFFF |
16-битовый символ Unicode (в шестнадцатеричном коде) |
Последний способ получить примитивную String, служащей для преобразования в строковый тип. Работает эта функция достаточно очевидным образом. Для чисел возвращает соответствующую строчку с десятичной записью числа (возможно, с плавающей точкой). Для булевых выражений выдает " true " или " false ". В случае undefined возвращает пустую toString. По этим же правилам производится преобразование в строчку и тогда, когда оно совершается неявно (например, при передаче аргумента строкового типа или в случае прибавления какого-либо выражения к
А вот конструкция new String(выражение) создает
Изредка возникает проблема: нужно написать очень длинную +. А можно - поставив обратный слэш, как в С++. Правда, имеется проблема с использованием последнего способа: слэши остаются в
Сейчас мы кратко опишем функциональность каждого из методов класса String во Флэш. Все эти методы работают как с объектными, так и с примитивными trace("my name".toUpperCase()), и это действительно выведет на печать MY NAME, хотя подобный код и нельзя назвать хорошо читаемым.
Итак, методы charAt и charCodeAt позволяют получить символ и его код по заданному индексу; метод concat присоединяет к нашей indexOf и позволяют находить slice, substr и substring позволяют разными способами выделять toUpperCase и toLowerCase переводят все буквы в заглавный или строчный регистр; наконец, метод split разбивает String.fromCharCode. Он является чем-то вроде статического метода класса String и не нуждается в объекте строкового типа для своего вызова. Чтобы вызвать этот метод, нужно так и написать: String.fromCharCode, а в качестве аргументов передать один или несколько кодов символов, из которых и будет сформирована
Конечно, этого краткого описания недостаточно для уверенной работы со split. Метод split настолько хорош и полезен, что пример его применения мы выделим отдельно и опишем в следующем подпараграфе. Все же прочие примеры представлены в следующем коде:
a_str = "Очень длинная строка";
trace(
"a_str.toLowerCase() = " +
a_str.toLowerCase()
); // Переводим строку в нижний регистр
trace(
"a_str.toUpperCase() = " +
a_str.toUpperCase()
); // Переводим строку в верхний регистр
trace("");
trace(
"a_str.charAt(3) = " +
a_str.charAt(3)
); // Буква "н"
trace(
"a_str.charCodeAt(5) = " +
a_str.charCodeAt(5)
); // Код пробела
trace("");
trace(
"a_str.concat(', да-да. ', a_str) = \n\t" +
a_str.concat(', да-да. ', a_str)
);
trace("");
trace(
"String.fromCharCode(46, 56, 74, 34, 45) = " +
String.fromCharCode(46, 56, 74, 34, 45)
);
trace("");
trace(
"a_str.indexOf('н') = " +
a_str.indexOf('н')
); // Первая буква "н"
trace(
"a_str.indexOf('нн') = " +
a_str.indexOf('нн')
); // Первое (оно же и последнее) сочетание букв "нн"
trace(
"a_str.lastIndexOf('н') = " +
a_str.lastIndexOf('н')
); // Последняя буква "н"
trace(
"a_str.lastIndexOf('нн') = " +
a_str.lastIndexOf('нн')
); // Последнее (оно же первое) сочетание букв "нн"
trace(
"a_str.indexOf('н', 6) = " +
a_str.indexOf('н', 6)
); // Первая буква "н" после 6-й позиции (или на 6-й).
trace(
"a_str.lastIndexOf('н', 6) = " +
a_str.lastIndexOf('н', 6)
); // Последняя буква "н" перед 6-й позицией (или на 6-й).
trace("-------------");
/* Несколько примеров на метод slice */
/* Он работает так же, как аналогичный метод в массиве */
trace(
"a_str.slice(8, 12) = " +
a_str.slice(8, 12)
); // Кусок строки в районе букв "нн"
trace(
"a_str.slice(8, 3) = " +
a_str.slice(8, 3)
); // Если второй аргумент меньше первого, но положителен,
// возвращается пустая строка.
trace(
"a_str.slice(8, -3) = " +
a_str.slice(8, -3)
); // Если второй аргумент отрицателен,
// отсчитываем от конца строки назад.
trace("-------------");
/* Посмотрим, чем от slice отличается substring */
trace(
"a_str.substring(8, 12) = " +
a_str.substring(8, 12)
); // Тот же результат, что и для slice
trace(
"a_str.substring(8, 3) = " +
a_str.substring(8, 3)
); // Если второй аргумент меньше первого,
// аргументы меняются местами
trace(
"a_str.substring(8, -3) = " +
a_str.substring(8, -3)
); // Если любой из аргументов отрицателен,
// он заменяется нулем. Затем, если нужно,
// аргументы меняются местами
trace("-------------");
/* Еще один метод выделения подстроки: substr */
trace(
"a_str.substr(8, 3) = " +
a_str.substr(8, 3)
); // Здесь второй аргумент задает длину подстроки.
trace(
"a_str.substr(8) = " +
a_str.substr(8)
); // Если же второй аргумент вовсе не передавать,
// то подстрока берется до конца строки
// substring и slice в этом случае работают точно так же.
Этот длинный код выводит следующий длинный текст:
a_str.toLowerCase() = очень длинная строка
a_str.toUpperCase() = ОЧЕНЬ ДЛИННАЯ СТРОКА
a_str.charAt(3) = н
a_str.charCodeAt(5) = 32
a_str.concat(', да-да. ', a_str) =
Очень длинная строка, да-да. Очень длинная строка
String.fromCharCode(46, 56, 74, 34, 45) = .8J"-
a_str.indexOf('н') = 3
a_str.indexOf('нн') = 9
a_str.lastIndexOf('н') = 10
a_str.lastIndexOf('нн') = 9
a_str.indexOf('н', 6) = 9
a_str.lastIndexOf('н', 6) = 3
-------------
a_str.slice(8, 12) = инна
a_str.slice(8, 3) =
a_str.slice(8, -3) = инная стр
-------------
a_str.substring(8, 12) = инна
a_str.substring(8, 3) = нь дл
a_str.substring(8, -3) = Очень дл
-------------
a_str.substr(8, 3) = инн
a_str.substr(8) = инная строка
Обратите внимание на разницу в работе slice, substring и substr. Примеры демонстрируют эту разницу для всех случаев, которые могут быть важны на практике. Интересно также, что существует (объявленная устаревшей) глобальная функция substring, которой в качестве первого аргумента передается substr класса String (а вовсе не как метод substring, как могло бы показаться из-за совпадения названий)!
Нерассмотренным у нас пока остался простой, но существенный вопрос: а как узнать длину length.
Согласитесь, что сделать простую замену split, для данной join, а в качестве "склеивающей"
text_str = "Мы любим буги-вуги, мы танцуем только буги";
new_str = text_str.split("уги").join("аги");
trace("text_str = " + text_str);
trace("new_str = " + new_str);
В результате действительно получаем:
text_str = Мы любим буги-вуги, мы танцуем только буги new_str = Мы любим баги-ваги, мы танцуем только баги
Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.