Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 [ 63 ] 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189

Согласитесь, массив $Monthes, содержащий названия месяцев, довольно объемист. Поэтому описывать его прямо в функции было бы, мягко говоря, неудобно. В то же время функция GetMonthName() представляет собой довольно преемлемое средство для приведения номера месяца к его словесному эквиваленту (что может потребоваться во многих программах). Она имеет единственный и понятный параметр: это номер месяца. Как бы мы это сделали без глобальных переменных?

Массив $GLOBALS

В принципе, есть и второй способ добраться до глобальных переменных. Это - использование встроенного в язык массива $globals. Последний представляет собой хэш, ключи которого есть имена глобальных переменных, а значения - их величины.

Этот массив доступен из любого места в программе - в том числе и из тела функции, и его не нужно никак дополнительно объявлять. Итак, приведенный выше пример можно переписать более лаконично:

Возвращает название месяца по его номеру. Нумерация начинается с 1! function GetMonthName($n) { return $GLOBALS["Monthes"][$n]; }

Кстати, тут мы опять сталкиваемся с тем, что не только переменные, но даже и массивы могут иметь совершенно любую структуру, какой бы сложной она ни была. Например, предположим, что у нас в программе есть ассоциативный массив $A, элементы которого - двумерные массивы чисел. Тогда доступ к какой-нибудь ячейке этого массива с использованием $globals мог бы выглядеть так:

$GLOBALS["A"][First"][10][20];

То есть получился четхрехмерный массив!

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

□ присвоить этот массив какой-либо переменной целиком, используя оператор =;

□ как следствие, передать его функции "по значению" - можно передавать только по ссылке.

Однако остальные операции допустимы. Мы можем при желании, например, по одному перебрать у него все элементы и, скажем, вывести их значения на экран. И, наконец, третье: добавление нового элемента в $globals равнозначно созданию новой глобальной переменной (конечно, предваренной символом $ в начале имени, ведь в самом массиве ключи - это имена переменных без символа доллара), а выполнение



операции Unset() для него равносильно уничтожению соответствующей переменной.

А теперь я скажу нечто весьма интересное все о том же массиве $globals. Как вы думаете, какой элемент (то есть, глобальная переменная) всегда в нем присутствует? Это - элемент globals, "которая" также является массивом, и в "которой" также есть элемент globals... Так что же было первей - курица или яйцо (только не надо мне говорить, что первым был петух)?

А собственно, почему бы и нет? С чего это мы все привыкли, что в большом содержится малое, а не, скажем, наоборот? Почему множество не может содержать себя же в качестве элемента? Очень даже может, и $globals - тому наглядный пример.

В PHP версии 3 такая ситуация была чистой воды шаманством. Однако с появлением в четвертой версии PHP ссылок все вернулось на круги своя. На самом-то деле элемент с ключом globals является не об1чн1м массивом, а лишь ссхлкой на $globals. Вот поэтому все и работает так, как было описано.

Вооружившись механизмом создания ссылок, мы можем теперь наглядно продемонстрировать, как работает инструкция global, а также заметить один ее интересный нюанс. Как мы знаем, global $a говорит о том, что переменная $a является глобальной, т. е., является синонимом глобальной $a. Синоним в терминах PHP - это ссылка. Выходит, что global создает ссылку? Да, никак не иначе. А вот как это воспринимается транслятором:

function Test() { global $a; $a=10;

Приведенное описание функции Test() полностью эквивалентно следующему описанию:

function Test()

{ $a=&$GLOBALS[a];

$a=10;

Из второго фрагмента видно, что оператор Unset($a) в теле функции не уничтожит глобальную переменную $a, а лишь "отвяжет" от нее ссылку $a. Точно то же самое происходит и в первом случае. Вот пример:

$a=100;

function Test() { global $a; Unset($a);

Test();

echo $a; выводит 100, т. е. настоящая $a не была удалена в Test()!



Эта особенность инструкции global появилась только в PHP версии 4, т. е. когда начали поддерживаться ссылки! Если вы запустите приведенный только что пример на PHP версии 3, то при исполнении echo увидите предупреждение: $a не определена. Помните это при переносе старых сценариев на новый PHP версии 4.

Как же нам удалить глобальную $a из функции? Существует только один способ: использовать для этой цели $GLOBALS[a]. Вот как это делается:

function Test() { unset($GLOBALS[a]); }

$a=100; Test();

echo $a; Ошибка! Переменная $a не определена!

Статические перемеииые

Видимо, чтобы не отставать от других языков, создатели PHP предусмотрели еще один вид переменных, кроме локальных и глобальных, - статические. Работают они точно так же, как и в Си. Рассмотрим следующий пример (листинг 11.12):

i Листинг 11.12. Статические переменные

function Silly() { static $a=0;

echo $a;

$a++;

for($i=0; $i<10; Silly();

После запуска будет выведена строка 0123456789, как мы и хотели. Давайте теперь уберем слово static. Мы увидим: 0000000000. Это и понятно, ведь переменная $a стала локальной, и ей при каждом вызове функции присваивается одно и то же значение - 0.

Итак, конструкция static говорит компилятору о том, что уничтожать указанную переменную для нашей функции между вызовами не надо. В то же время присваивание $a=0 сработает только один раз, а именно - при самом первом обращении к функции (так уж устроен static).

Рекурсия

Конечно, в PHP поддерживаются рекурсивные вызовы функций, т. е. вызовы функцией самой себя (разумеется, не до бесконечности, а в соответствии с определенным условием). Это бывает чрезвычайно удобно для таких задач, как, например, обход



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 [ 63 ] 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189