Изучаем Майкл Моррисон

advertisement
Майкл Моррисон
Изучаем
J
a
v
a
S
c
r
i
p
t
Улучшай
качество
взаимодействия
пользователя
с веб-страницей
ШЛІя«ЖіТоЧ
Научись
оптимизировать
Освой концепцию
и синтаксис JavaScript
максимально эффективно
Управляй
НТМЬ-кодом
с помощью
ООМ
J a v a S c rip t-к o д
Избавься от страха
перед обработчиком
событий
Проверяй свои знания
с помощью сотен
упражнений и примеров
Head First JavaScript
Wouldn't it be dreamy if
th e re was a way to learn JavaScript
from a book w ithout wanting to set fir e
to it halfway through and swearing o f f
th e Web forever? I know, it's probably
ju s t a fantasy...
M ichael M orrison
O ’R E IL L Y '
Beijing • Cambridge • Farnham • Koin • Sebastopol • To/cyo
Изучаем JavaScгipt
Как было бы здорово изучить
JavaScгipt, не испытывая желания
бросить все на половине пути и никогда
больше не заходить в Интернет!
Наверное, об этом можно
только мечтать...
Майкл Моррисон
Москва ■Санкт-Петербург ■Нижний Новгород ■Воронеж
Ростов-на-Дону ■Екатеринбург • Самара ■Новосибирск
Киев • Харьков ■Минск
2012
Майкл Моррисон
Изучаем JavaScript
Перевела с английского И. Рузмайкина
Заведующий редакцией
Руководитель проекта
Ведущий редактор
Научный редактор
Литературный редактор
Художественный редактор
Корректоры
Верстка
А. Кривцов
А, Юрченко
Ю. Сергиенко
С. Бойко
Е. Пасечник
Л. Адуевская
В. Листова, И, Тимофеева
Л. Харитонов
ББК 32.988.02-018.1 УДК 004.43
Моррисон М.
М80
Изучаем JavaScript. — СПб.: Питер, 2012. — 608 с.: ил.
ISBN 978-5-459-00322-2
Вы готовы сделать щаг вперед в своей практике веб-программирования и перейти от верстки
в HTML и CSS к созданию полноценных динамических страниц? Тогда пришло время познако­
миться с самым «горячим» языком программирования — JavaScript!
С помощью этой книги вы узнаете все о языке JavaScript: от переменных до циклов. Вы пойме­
те, почему разные браузеры по-разному реагируют на код и как написать универсальный код,
поддерживаемый всеми браузерами. Вам станет ясно, почему с кодом JavaScript никогда не при­
дется беспокоиться о перегруженности страниц и ошибках передачи данных. Не пугайтесь, даже
если ранее вы не написали ни одной строчки кода, — благодаря уникальному формату подачи
материала эта книга с легкостью проведет вас по всему пути обучения: от написания простейше­
го java-CKpHHTa до создания сложных веб-проектов, которые будут работать во всех современных
браузерах.
Особенностью данного издания является уникальный способ подачи материала, вьщеляющий
серию «Head First» издательства O ’Reilly в ряду множества скучных книг, посвященных про­
граммированию.
ISBN 978-0596527747 англ.
ISBN 978-5-459-00322-2
© Authorized Russian translation of the English edition of Head First
JavaScript © O'Reilly Media, Inc. This translation Is published and
sold by permission of O'Reilly Media, Inc., the owner of all rights to
publish and sell the same.
© Перевод на русский язык ООО Издательство «Питер», 2012
© Издание на русском языке, оформление
ООО Издательство «Питер», 2012
Права на издание получены по соглашению с O’Reilly. Все права защищены. Никакая часть данной книги не может быть воспроизведе­
на в какой бы то ни было форме без письменного разрешения владельцев авторских прав.
Информация, содержащаяся в данной книге, получена из источников, рассматриваемых издательством как надежные. Тем не менее,
имея в виду возможные человеческие или технические ошибки, издательство не может гарантировать абсолютную точность и полноту
приводимых сведений и не несет ответственности за возможные ошибки, связанные с использованием книги.
ООО «Мир книг», 198206, Санкт-Петербург, Петергофское шоссе, 73, лит. А29.
Налоговая льгота — общероссийский классификатор продукции ОК 005-93, том 2;
95 3005 — литература учебная.
Подписано в печать 27.09.11. Формат 84x100/16. Уел. п. л. 63,840. Тираж 2500. Заказ 26462.
Отпечатано по технологии CtP в ОАО «Первая Образцовая типография», обособленное подразделение «Печатный двор».
197110, Санкт-Петербург, Чкаловский пр., 15.
П освящ ается ребятам из Ые15саре, которы е ещ е в про­
шлом веке мечтали, чтобы И н терн ет стал чем-то боль­
шим, чем гигантской книгой с массой гиперссылок.
Х отя, конечно, это они намечтали ужасный тег < Ы 1пк>...
продем онстрировав, что в мечтах не следует заходить
слишком далеко!
обавтщге
Автор книги Head First JavaScript
оЗаренныМ & о6а
с т и J a v a S c r ip t .
И Эйже сейчас он ост ался
.ребенком, который никак
не хочет раст и.
П ервы м ком пью тером М ай кла М о р р и со н а был
Т1-99/4А, укомплектованны й эргоном ичной клавиату­
рой, черно-белым «монитором», роль которого играл
телевизор, и набором кассет со стереосистем ой. С того
врем ени он сменил множ ество компью теров, но до сих
пор скучает по играм в Parsec на стареньком TI.
В настоящ ее время интересы М айкла сместились в сто­
рону создания и нтерактивны х веб-прилож ений и...
катания на роликовой доске. К реш ению технических
проблем он подходит с той ж е беспечной отвагой, как
к рискованному спорту. Создав несколько видеоигр,
изобретя пару игрушек, написав дюжину ком пью терны х
книг и основав множ ество ком пью терны х курсов, Майкл
наконец приш ел к идее написать книгу, посвященную
JavaScript.
Впрочем, по-настоящему подготовиться к написанию
книг серии H ead First невозможно. Нужно просто п ри ­
нять красную пилюлю и провалиться в М атрицу, которая
назы вается H ead First. Получив такой опыт, Майкл уже
никогда не будет см отреть на процесс обучения постарому. Чему он крайне рад. Сейчас он с ж еной сидит
на берегу своего пруда с золоты м и рыбками, отраж аю щ е­
го чудеса и нтерактивного И нтернета.
содержание
-т-
<^ацЖ ое содерж ание
Введение
23
1
И н теракти вн ая сеть: Реакции виртуального мира
35
2
Х ранение данных: Все на своем месте
65
3
И сследование клиента: Знакомство с браузером
115
4
G
Если на дороге развилка...
163
5
Ц иклы : Рискуя повториться
215
6
Функции: Многократное использование
267
7
Ф орм ы и п ровер ка данных: Л ) ) с т ои все р а с с ж а ж т
311
8
У правление страницами: Управление H T M L с DOM
363
9
О ж т ляем р,гншле:: Объекты как франкенданные
411
10
С пециальны е объекты; Работа со специальными объектами
465
11
Охота па. ош ибки: Когда сценарий не работает
499
12
Д инам ические данные: Удобные вебприложения
549
'Д е ] ^ ж а н и е
Введение
В а ш м о з г д у м а е т о и а уа 8 с г1 р 1 . Вы сидите за книгой и пытае­
тесь что-нибудь выучить, но ваш мозг продолжает считать, что вся
эта писанина не важна. Ваш мозг говорит; «Выгляни в окно! На свете
есть более важные вещи. Например, серфинг или голодный тигр, ког­
да ты попался на его пути». Как заставить ваш мозг думать, что ваша
жизнь действительно зависит от знания иауаЗспр!?
Д ля кого н аписана эта книга?
24
Мы знаем, о чем вы думаете
25
М етапознание: наука о мыш лении
27
Как заставить м озг повиноваться?
29
П рим и те к сведению
30
Т ехнические редакторы
32
Благодарности
33
содержание
и н т п е р а к т и Б н а я с е зп ь
Реакции виртуального мир
Устали представлять Интернет набором пассивных стра­
ниц? Кто из нас не держал в руках книг. Их читаешь, в них находишь
информацию. Но они не интерактивны. Как и интернет-страницы без
JavaScript. Без сомнения, отправить данные формы и проделать другие
трюки можно и при помощи кода HTML и CSS, но реальная интерактив­
ность требует более умного подхода и большей работы... зато и резуль­
тат впечатляет намного больше.
То, что нужно людям
36
и ничего... как будто говориш ь со стенкой
37
A JavaScript отвечает
3g
Свет, кам ера, взаимодействие!
40
Т ег <script>
45
Ваш браузер поним ает HTM L, CSS И JavaScript
46
П ом оги виртуальному другу человека
49
С делайте iRock и н терактивны м
50
Веб-страница iRock
51
Т ести рован и е
51
С обы тия
52
О повещ ение пользователей
53
iRock приветствует вас
54
Сделайте объект iRock действительно и н терактивны м
56
В заимодействие долж но бы ть Д В У С ТО РО Н Н И М
57
Как узнать имя пользователя
58
П олученны й результат
61
П роверка п ри лож ен и я iRock 1.0
62
ft is good to meet you, Paul.
10
содержание
Kl
»аш К ое с о д е р ж а н и е
Введение
23
1
И н теракти вн ая сеть: Реакции виртуального мира
35
2
Х ранение данных: Все на своем месте
65
3
И сследование клиента: Знакомство с браузером
115
4
П р и н яти е реш ений: £сли иа Эо/)оге^)(Мвгмка...
163
5
Ц иклы : Рискуя повториться
215
6
Функции: Многократное использование
267
7
Ф орм ы и п ровер ка данных: Пусть он все расскажет
311
8
У правление страницами: Управление H T M L с DOM
363
9
Ож ивляем данные: Объекты как франкенданные
411
С пециальны е объекты: Работа со специальными объектами
465
10
11
Охотг. на ош ибки: Когда сценарий не работает
499
12
Д и нам и ч ески е данные: Удобные вебприложения
549
О одержание
Введение
В а ш м о з г д у м а е т о и а уа З сг1 р 1 . Вы сидите за книгой и пытае­
тесь что-нибудь выучить, но ваш мозг продолжает считать, что вся
эта писанина не важна. Ваш мозг говорит; «Выгляни в окно! На свете
есть более важные вещи. Например, серфинг или голодный тигр, ког­
да ты попался на его пути». Как заставить ваш мозг думать, что ваша
жизнь действительно зависит от знания иауаЗспр!?
Для кого н аписана эта книга?
24
Мы знаем, о чем вы думаете
25
М етапознание: наука о м ыш лении
27
К ак заставить м озг повиноваться?
29
П рим и те к сведению
30
Т ехнические редакторы
32
Благодарности
33
содержание
)(|> ан ен и е Д аннъ1х
Все на своем месте
в реальном мире люди часто не придают значения местам
для хранения своего имущества, в иауаЗспр! такое поведение не­
возможно. Ведь там не существует роскоши в виде огромных шкафов и га­
ражей на три машины, В иауаЗспр! все имеет свое место, и ваша задача
в этом убедиться. Мы поговорим о данных — как их представить, как
хранить их и как их найти после сохранения. Вы научитесь превращать
захламленые комнаты с данными в аккуратные помещения с ящиками, каж­
дый из которых имеет пометку
С охранение данны х
66
Т ипы данны х
67
Константы и переменны е: постоян н ое и изм еняем ое
72
И сходное состоян и е перем енны х
76
П р и своен и е значений
77
У прямы е константы
78
Ч то в им ени тебе моем?
82
К орректн ы е и н екорректн ы е им ена
83
СтильВерблю да
84
Следующий этап
87
П ланируем веб-страницу
88
И нициализируйте данные... или...
93
МаМ —это Н Е число
94
Складывать м ож но не только числа
96
М етоды раг 5е 1пс() и раг8еР1оа1()
97
Откуда берутся лиш ние пончики?
98
Дункан обнаруж ивает ш пиона
102
М етод getElem entB yId()
103
П роверка данны х ф орм ы
104
И нтуитивны й ввод данны х
109
11
содержание
Ц ссЛ еД оБ ан ие к л и е н т а
Знакомство с браузером
Иногда иауаЗспр! хочет знать, что происходит в окружаю­
щем мире. Ваши сценарии могут существовать в качестве кода на веб­
страницах, но по большей части они живут в мире, создаваемом браузером
или клиентом. Умным сценариям часто необходимо знать больше о мире,
в котором они живут, в этом случае они могут общаться с браузером, чтобы
узнать про него как можно больше. Независимо от того, что требуется узнать:
размер экрана или нажата ли кнопка в браузере, они постоянно поддержива­
ют отношения с браузером.
12
К лиент, сервер и JavaS cript
Ц6
Ч то браузер мож ет сделать для вас?
118
О бъект 1Коск слиш ком счастлив
119
Т айм еры
122
Как раб о тает тайм ер
123
М етод 5е 1Т 1т е о и 1()
124
А нализ м етода 8е Ш т е о и 1()
125
Зависим ость от разм ера экрана
129
Ш и ри н а окна браузера
130
Задание ш и рины окна
131
Вы сота и ш ирина объекта 1Коск
132
1Коск долж ен соответствовать стран и ц е
133
С обы тие опге51ге
137
С обы тие опге 812е ДЛЯ камеш ка
138
Мы уже встречались?
140
Время ж изни сцен ари я
141
П родление врем ени ж изни сц ен ари я
142
Свойства куки
147
Код JavaScript ВНЕ веб-страницы
149
П ри ветстви е пользователя
150
М етод greetU ser() н а основе куки
151
С оздание куки
152
Влияние на безопасность
154
М ир без куки
156
Разговор с пользователям и... это лучше, чем н ичего
159
содержание
|> и н я1ц ие р»е1Нений
Если на дороге развилка...
Жизнь неотделима от принятия решений. Стоять или идти,
пойти
на сделку с негодяем или пойти в суд... Результата невозможно добиться без
выбора. То же самое происходит в иауаЗспр! — вам приходится выбирать
между различными вариантами сценария. Приходится то и дело при­
нимать решения. Стоит ли поверить данным, введенным пользователем,
и отправить его охотиться на львов? Или же проверить еще раз, может быть,
он всего лишь пытался заказать билет до Львова? Выбор за вами!
Welcone fo
S T IC K FIGURE
ADVEW TURE
flickeiiher
buitoN to
Start...
Счастливчик, спускайся ко мне!
164
«Уели» так, то сделай что-нибудь
166
О пер ато р if
167
Когда вариантов два
169
Вы м ож ете сделать м нож ественны й выбор
170
Клю чевое слово else
171
П ерем ен н ы е как двигатель истори и
174
Н едостаю щ ие части истори и
175
Совмещ ение усилий
176
Запись п ри помощ и if/e ls e
182
В лож енны й о п ер ато р if
183
У правление при помощ и методов
185
П севдокод
186
П роблем ы н арисованного человечка
190
!= т-с-с-с, мне нечего тебе сказать...
191
О п ер ато р ы сравнения
192
К ом м ентарии
194
К ом м ентарии начинаю тся с / /
195
О бласть видимости
197
П ровери м область видимости
198
Где ж ивут м ои данные?
199
Вы бор из пяти
„
202
П ереуслож нение конструкции
203
О п ер ато р sw itch /case
205
А нализ о п ер ато р а switch
206
Тест-драйв нового вари ан та «П риклю чений»
211
13
содержание
ДиКЛы
Рискуя повториться
Говорят, что повторение — мать учения. Заниматься новыми и ин­
д
тересными делами здорово, но наши дни, как правило, состоят из рутины.
Доведенное до автоматизма мытье рук, нервный тик, щелчок на кнопке Reply
То АП при получении любого дурацкого сообщения! Кажется, повторение не
самая лучшая вещь в этом мире. А вот в мире JavaScript без него никак. Вы
удивитесь, как часто бывают востребованы одни и те же фрагменты кода.
Здесь вам на помощь приходят циклы. Без них пришлось бы снова и снова
набирать один и тот же код.
Available
seat_avail.png
Unavailable
I)
seaLunavaiI.png
Select
seat_selectpng
14
М есто пом ечено крестом
216
и снова дежавю... цикл for
217
О хота за сокровищ ам и с циклом for
218
Составны е части цикла for
219
Специальны е места для мачо
220
П роверка доступности мест
221
Ц иклы, H TM L и свободные кресла
222
Места, как перем енны е
223
М ассивы
224
Значен и я сохраняю тся с ключами
225
О т JavaScript к H TM L
229
Визуализация кресел
230
П роверка
235
Бескон ечн ы е циклы
236
Условие выхода и з цикла
237
П реры ван и е действия
238
Л огические операторы
244
Ц икл while
248
А нализ цикла while
249
Выбор подходящ его цикла
251
К и н отеатр —место м оделирования данных
257
Двумерные массивы
258
Д ва клю ча доступа
259
Двумерная версия M andango
261
Ц елы й ки н о театр мест для мачо
264
содержание
срункД ии
М ногократное использование
Начни иауа8 сг1р1 выступать за экологию, это выступление
возглавили бы функции. Ведь именно они увеличивают эффектив­
ность кода и позволяют использовать его многократно. Они ориентированы
на решение задач и позволяют все систематизировать. Функции дают воз­
можность упростить любой сценарий, ну кроме разве что и так простых. Их
значение невозможно оценить, поэтому просто скажем, что именно функции
делают сценарии такими экологичными.
Lthrotjgh3mSow4areavaiia^e.Accept?
И сточн и к всех проблем
268
ф ункции как способ реш ения
270
И з чего состои т ф ункция
271
Уже знаком ы е вам функции
272
Улучшаем наш терм остат
275
П ередача и н ф орм ац и и функциям
276
Аргументы как данны е
277
И збавляем ся от дублирующегося кода
278
Функция, задающая места
281
Ф ункция 8е 18еа 1()
283
О братн ая связь
285
В озврат данных
286
Возвращ аемые значения
287
И н ф о р м ац и я о статусе места
291
О тображ ение статуса
292
Связь функции с изображ ением
293
Дублирующ ийся код
294
О тделите функциональность о т содерж имого
295
Ф ункции —это тож е данные
296
Вызов функции и ссылка на нее
297
С обы тия, обратн ы й вы зов и атрибуты Н ТМ Ь
301
Ссылки на ф ункции
302
Л и терал функции
303
А где ж е связывание?
304
О болочка Н ТМ Ь-страницы
307
15
содержание
и г 1]=>оБе|>ка Данных
Пусть он все р а сс ка ж ет
Для получения информации от пользователей при помо­
щи иауа8сг1р1 вам не потребуется быть джентльменом.
Но вы должны быть аккуратны. Люди часто делают ошибки, а это озна­
чает, что данные, полученные при помощи веб-форм, далеко не всегда
корректны. Проверяя вводимые данные при помощи иауаЗспр!, вы
увеличиваете надежность веб-приложений и снимаете дополнительную
нагрузку с серверов. Полоса пропускания нам пригодится для восхити­
тельных видеороликов и чудесных фотографий.
^*осИу...Ьапое*
16
Н ТМ Ь-форма ф и рм ы Ваппегос11у
313
Когда язы ка Н ТМ Ь недостаточно
314
Доступ к данны м ф орм ы
315
Ц еп очка собы тий
317
С обы тие опЫ иг
318
С ообщ ение п роверки
319
П ро вер ка полей н а наличие данных
323
П роверка без предупреждаю щ их всплываю щ их окон
324
Усложняем наш валидатор
325
Разм ер им еет значение...
327
П ро вер ка длины
328
П ро вер ка индексов
333
П ро вер ка даты
338
Регулярны е вы раж ения н е «регулярны»
340
Задание ш аблона
341
М етасимволы
343
К оличество повторен и й
344
П ро вер ка данны х п ри помощ и регулярны х вы раж ений
348
Д иапазон вхож дений
351
Вы бери это... или то
353
Н икаких случайностей
354
Вы м еня слышите?
355
Вам письмо
356
И склю чение —это правило
357
Д ополнительны е символы
358
П ро вер ка адреса электрон н ой почты
359
содержание
Ул|=*аБЛение с т р а н и ц а м и
Управление HTML с DOM
Управление содержимым веб-страницы при помощи Java­
Script напоминает приготовление еды. Конечно, это не настолько
грязное занятие... И, увы, вы не сможете съесть результат своих трудов.
Тем не менее вы получаете полный доступ к НТМи-тгрер,\лентам, из кото­
рых состоит веб-страница, и, что еще важнее, вы можете менять исходный
рецепт. Ведь JavaScript дает возможность управлять HTML-кодом веб­
страницы, что открывает для вас целый ряд интереснейших перспектив, ко­
торые реализуются посредством набора стандартных объектов DOM.
html
j|;
r {
""‘‘у ^
^ 0^ ------- 1
^
§
ф ункциональны й, но неудобный
364
Б ез всплываю щ их окон
365
Доступ к H TM L-элементам
367
Внутренний код элем ента
368
О бъектная модель документа (DOM)
373
Страница как набор узлов
374
Свойства узлов
377
Р едактирование текста
380
«П риклю чение», совместим ое со стандартами
385
П роекти рован и е лучше, варианты чищ е
387
И снова замена текста в узлах
388
Функция, заменяю щ ая текст узла
389
Д инам ические п арам етры
390
И нтеракти вн ость
391
Зн ачен и е стиля: CSS и DOM
392
Зам ена классов стилей
393
С тильны е варианты
394
П ро вер ка работы прилож ения
395
Пустая кнопка
396
Н астрой ка «а л я style»
397
кнопок
Б ез ф и кти вн ы х кнопо
399
Усложняем «П риклю чения»
400
П оход по дереву реш ений
402
П ревратим историю в НТМ Т
403
О бработка НТМЕ-кода
404
О тслеж ивание «Приклю чений*
407
17
содержание
О ж ивляем данны е
Объекты к а к ф ранкенданны е
Объекты иауа8сг1р1 вовсе не так ужасны, как заставил вас
думать доктор. Зато они интересны тем, что соединяют друг с другом
отдельные части языка иауаЗспр!, делая его более мощным. Объекты
объединяют данные с действиями в новый тип, намного более «жи­
вой», чем все, что вы использовали раньше. Вы познакомитесь с масси­
вами, которые сортируют себя сами, со строками, которые умеют ис­
кать в своем составе указанные последовательности символов, и многими
другими замечательными особенностями.
D ata
A c tio n s
var who;
function display(what, when, where) {
var what;
}
var when;
function deliver(who) {
var where;
1
O bject
function displayO
var who;
function deliver 0 {
var what;
var when;
var where;
18
{
Вечеринка в стиле JavaScript
412
Д анны е + действия = объект
413
Д анны е —это собственность объекта
414
Ссылка на члены объекта
415
Специальны е объекты
419
К онструктор
420
Структура конструктора
421
Создание объектов blog
422
Н еобходим ость сорти ровки
427
О бъект для дат
428
Вы числение времени
429
П ересм отр дат в блоге
430
О бъект внутри другого объекта
431
П реобразован и е объектов в текст
434
Доступ к ф рагм ентам даты
435
М ассивы как объекты
438
П ользовательская сортировка
439
У прощ ение сорти ровки
440
П оиск по массиву
443
М етод indexO f()
445
П оиск по блогу
446
П оиск заработал!
449
О бъект M ath
452
Генерация случайных чисел
454
П ревращ ен и е функции в метод
459
В осхитительны й новы й объект blog
460
Ч то даю т объекты блогу YouCube?
461
Ц
содержание
^оеД иаЛ ьН ы е о б ъ е к т ы
Работа со специальны ми объектами
Если бы все было так легко, мы бы, конечно, так и сделали.
иауаЗспр! не гарантирует возврат денег, но вы действительно можете делать
с ним все, что захотите. Специальные объекты — это эквивалент тройного
эспрессо с сахаром и корицей. Вот такая специальная чашка кофе! Точно так
же в специальных объектах вы можете смешивать код, добиваясь именно
того результата, который вам нужен, и пользуясь преимуществами свойств
и методов. И в конце получается объектно-ориентированный код, расширяю­
щий язык иауаЗспр!... только для вас!
Objwr Instames
С нова о методах блога Y ouCube
466
П ерегрузка методов
467
Классы и реализации
468
Реализации
469
К лю чевое слово this
470
М етоды классов
471
П рототи п ы
472
Классы, п ро то ти п ы и Y ouCube
473
С войства общ его доступа
478
Создание свойств класса
479
П одписан и доставлен
481
Н ет дублирующемуся коду!
483
М етод ф орм ати рован и я данных
484
Р асш ирение стандартны х объектов —улучшенный блог
486
М етоды классов
487
Функция сравнения
489
Вызов м етода класса
490
К арти н ка стоит ты сячи слов
491
Вставка и зображ ений
492
Д обавление галереи
494
Блог н а основе объектов
496
19
содержание
0 х о г п а н а оШ ибки
Когда сценарий не работает
Даже самые лучшие планы в иауаЗспр1 иногда не реализу­
ются. и когда это происходит, главное — не паниковать. Лучшие програм­
мисты не те, которые никогда не делали ошибок, — на самом деле это про­
сто лгуны. Лучшие — это те, кто может успешно обнаружить и устранить
ошибку. Отладчики высокой квалификации нарабатывают хорошую манеру
написания кода, минимизирующую вероятность появления неприятных оши­
бок. Лучше предотвратить, чем потом бороться. Тем не менее ошибки
то и дело встречаются, и вам нужен арсенал средств борьбы с ними...
20
У странение деф ектов
500
П роблем ы с калькулятором для
501
Различны е баузеры
502
Н еслож ная отладка
505
Н еоп ределен н ы е перем енны е
509
Р абота с циф рам и
511
Звонки на радио
512
Н ачинаем расследование
513
П роверка синтаксиса (ош ибка #1)
514
А ккуратнее со строкам и
515
К авы чки и апостроф ы
516
Евс-символы
517
Н еоп ределен н ость ф ункции (О ш ибка #2)
518
П обеж даю т все (О ш ибка #3)
520
О тладка с помощ ью всплываю щ их окон
521
Следим за значением п ерем енной
522
Н еко р р ектн ая логика
524
П рои гры ваю т все! (О ш ибка #4)
528
Атака всплываю щ их окон
529
П ользовательская консоль
531
Самая проти вная ош ибка
538
Т ри самых популярны х ти п а ош ибок
539
К ом м ентарии
542
Дважды объявленны е перем енны е
544
содержание
инаМ иЧ есК ие д а н н ы е
Удобные веб-приложения
Современный Интернет очень отзывчив, страницы умеют
реагировать на каждый каприз пользователя. Именно об этом
мечтают многие разработчики. JavaScript играет важную роль в осущест­
влении этой мечты при помощи технологии Ajax, позволяющей эффектив­
но менять «чувствительность» страниц. Благодаря Ajax страницы научились
быстро загружаться и динамически сохранять данные, отвечая на дей­
ствия пользователя в реальном времени без необходимости перезагрузки
браузера.
youcube.html
шт
Ж аж да динам ических данных
550
Блог, управляем ы й данными
551
Ajax как возм ож ность для общ ения
553
Ф орм атирование с помощ ью XML
555
XML + H TM L = XH TM L
557
XML и данны е блога Y ouCube
559
Добавим к блогу Ajax
562
И н тер ф ей с X M L H ttpR equest
564
Запрос с объектом X M L H ttpR equest
567
А нализ запросов Ajax
571
Создание запросов
575
Закончиш ь —вы зови меня
576
О бработка ответа
577
DOM как выход из полож ения
578
Y ouCube, управляем ы й данными
583
Н еработаю щ ие кнопки
585
Кнопкам нужны данны е
586
Функция, экономящ ая время
589
Зап и сь данны х в блог
590
Т реб овани я РНР
593
Д анны е для РН Р-сценария
594
О тп равка данны х на сервер
597
Делаем работу с блогом еще удобнее
602
А втозаполнение полей
603
П овторяю щ аяся задача?
604
21
J’a ë o m a m b с э т ° й к н и Г о й
Введение
на JavaScript?»
23
как работать с этой книгой
Для кого написана эта книга?
Если вы ответите «да» на все следующие вопросы.
Имеете ли вы доступ к компьютеру с браузером,
текстовым редактором и выходом в Интернет?
Хотите ли ли вы научиться создавать веб­
страницы, превращающие работу в Интернете
в по-настоящему интерактивный опыт?
Вы предпочитаете оживленную беседу сухим,
скучным академическим лекциям?
С нашей пом ощ ью вы научит есь
JavaScrip t код
M H ^ e c Z Z ^ ''^ ст^ан ы ц м делат ь
вещей
““ “ ■’« в » »
...то эта книга для вас.
Кому эта книга не подойдет?
Если вы ответите «да» н а лю бой из следующих вопросов.
Вы никогда не создавали веб-страниц?
(Быть знатоком HTML не обязательно, но вы
должны понимать, какую роль в появлении страниц
играют HTML и CSS и как опубликовать страницу
в Интернете.)
Считаете себя мастером написания сценариев
и ищете справочник по JavaScript?
Вы боитесь попробовать что-нибудь новое?
Скорее пойдете к зубному врачу, чем наденете
полосатое с клетчатым? Считаете, что техническая
книга, в которой компоненты Java изображены в виде
человечков, серьезной быть не может?
...эта книга не для вас.
В о о б щ е -т о
Z fS o z o ,
эт а книга и
у кого ест ь деньги.I
24
введение
введение
Мы знаем, о чем Вы думаете
«Разве серьезны е книги по програм м ированию нaJavaScript такие?»
«И почему здесь столько рисунков?»
‘'« о э т о
«Можно ли так чему-нибудь научиться?»
и мы знаем, что думает Ваш мозг
М озг жаждет новы х впечатлений. О н постоянно ищ ет, анализиру­
ет, ожидает чего-то необы чного. О н так устроен, и это помогает
нам выжить.
Как ж е наш мозг поступает со всеми обычными, повседневны ми
вещами? О н всеми силами пы тается отгородиться от них, ч то­
бы он и не мешали его настоящей работе —сохранению тогб,
что действительно важно. М озг не считает нужным сохранять
скучную информ ацию . О на не проходит ф ильтр, отсекаю щ ий
«очевидно несущественное».
Н о как же мозг узнает, что важно? П редставьте, что вы выехали
на прогулку и вдруг прямо перед вами появляется тигр. Ч то п ро­
исходит в ваш ей голове и в теле?
Активизирую тся нейроны . Вспыхиваю т эмоции. П роисходят
хим ические реакции.
И тогда ваш мозг поним ает...
13дця
Конечно, это важно! Не забывать!
А теп ерь представьте, что вы находитесь дома или в библиотеке,
в теплом, уютном месте, где тигры не водятся. Вы учитесь —гото­
витесь к экзамену. И ли пы таетесь освоить сложную техническую
тему, на которую вам выделили неделю... максимум десять дней.
И тут возникает проблема: ваш мозг пытается оказать вам
услугу. О н старается сделать так, чтобы на эту очевидно не­
существенную инф орм ацию не тратились драгоценны е ре­
сурсы. И х лучше потратить на что-нибудь важное. Н а тигров,
например. И ли на то, что к огню лучше не прикасаться. Или
на то, что вам не следовало соглашаться на просьбу друга по­
сидеть с его домашней анакондой.
Н ет простого способа сказать своему мозгу: «Послушай,
мозг, я тебе, конечно, благодарен, но какой бы скучной
ни была эта книга, и пусть мой датчик эмоций сейчас на
нуле, я
запом нить то, что здесь написано».
дальше >
25
как работать с этой книгой
кяига ДЛЯ « е^ . Kffiкак мь, что-то
затолкать в голову
„ования. в
Х Т н е й р о б ш л о г и . и поихолоп.и обучения, для
чем лросгой текст на отранице,
усвоения материала требуется что
Мы знаем, как заставить ваш мозг работат .
Основные принципы серии «Head First»
.о
лучше, чем обычный текст, и значи-
или на соседней странице,
разговорны й стиль изложения.
при личном разговорном
тестировании составляло до 40 %.
лекций) улучшение результатов
^е относитесь к себе слишком се-
'’ ^ Т н Г Г Л ^ о Г е Г п р «
занимательная беседа за столом или лекция.
■
пока вы не начнете напрягать извилины, в вашей голове ниА кти в но е у частие читателя. Пока вы не ,^ _ ^ з р е с о в а н в результате; он должен решать
чего не произойдет, читатель
знаниями. А для этого необходимы
;г :н е Г и Т а С : “
^р—
—
мозга и разные чувства.
привлечение ,и
на интересное, странное,
И н т е р е с н о е узнается намного быстрее.
моииям И зве стн о , что н аш а с п о с о б н о с т ь за л о м и -
“? гп г™
.. . . .
;ь г :« р е о , з „ о „ . .- .я ь » ™ » « „ = » . -
Иы ,.п о » и и а ™ то, что . а » „е б е а р а э -ч н о , М » » " » " " " • ■
что-™ ч , . с . , е » . И .,, с е к ,.м .н т » . . е с . к» п р . ч .» : P J -
„дет о таких w o * . K , как ,» « .п е » « е , л к Л о п ы т с о , « г е р .
^
........... ..
.,«ТГ,ПУЮ окоужающие счиГ я кр утГп р и решении задачи, которую окружающие счи-
кот.. . »
4 .0 разбираетесь . т е .е „ у ч .е ,
чем всезнайка Боб из технического отдела.
26
введение
М
введение
Метапознание: наука о мышлении
Если вы действительно хоти те бы стрее и глубже усваивать новы е
знания —задумайтесь над тем, как вы задумываетесь. У читесь
учиться.
Мало кто из нас изучает теорию м етапознания во время учебы. Нам
положено учиться, но нас редко этому учат.
Как бы
теперь заставить
свой мозг все это
запомнить...
Н о раз вы читаете эту книгу, то, вероятно, вы хотите изучить
п аттерны проектирования, и по возмож ности бы стрее. Вы хотите
запомнить п рочи тан н ое и применять новую инф орм ацию на п ракти­
ке. Ч тобы извлечь максимум пользы из учебного процесса, нужно
заставить ваш мозг восприним ать новы й м атериал как Н ечто Важ­
ное. К рити чное для вашего сущ ествования. Такое ж е важное,
как тигр. И наче вам предстоит бесконечная борьба с вашим
мозгом, которы й всеми силами уклоняется от запоминания
новой инф орм ации.
Как же УБЕДИТЬ мозг, что иауаЗспр! так же важна,
как и голодный тигр?
Есть способ м едлен н ы й и скучны й, а есть б ы стры й и эф ф екти в н ы й .
П ер вы й осн ован н а тупом п о вто р ен и и . Всем и звестн о , ч то даж е самую
скучную и н ф о р м ац и ю можно зап ом н и ть, если п о в то р я ть ее сн ова и снова.
П р и д о стато ч н о м кол и честве п о в то р е н и й ваш м озг п рикиды вает: «Вроде
бы несущ ественно, но раз одно и то ж е п о в то р я етс я столько раз... Л адно,
уговорил».
Бы стры й способ основан на повышении активности мозга, и особенно на
сочетании разны х ее видов. Д оказано, ч то все ф акторы , перечисленны е на
предыдущей странице, помогаю т вашему мозгу работать на вас. Н априм ер,
исследования показали, что разм ещ ение слов внутри рисунков (а не в под­
писях, в основном тексте и т. д.) заставляет мозг анализировать связи между
текстом и граф икой, а это приводит к активизации большего количества
нейронов. Больш е н ей ронов = выше вероятн ость того, что инф орм ация
будет сочтена важ ной и достойной запоминания.
Разговорны й стиль тож е важен: обычно люди проявляю т больше внимания,
когда они участвуют в разговоре, так как им приходится следить за ходом
беседы и высказы вать свое мнение. П ри чем мозг соверш енно не интересует
что вы «разговариваете» с книгой! С другой стороны , если текст сух и ф о р ­
мален, то мозг чувствует то же, что чувствуете вы на скучной лекции в роли
пассивного участника. Его клонит в сон.
Н о рисунки и разговорны й стиль —это только начало.
дальше
►
27
как работать с этой книгой
В о т что сделали МЫ:
Мы использовали рисунки, потому что мозг лучше приспособлен для восприя­
ти я граф ики, чем текста. С точки зрен и я мозга картинка томгга ты сячи слов.
А когда текст комбинируется с графикой, мы внедряем текст прямо в рисунки,
потому что мозг при этом работает эффективнее.
Мы используем избыпючность: повторяем одно и то же несколько раз, применяя
разные средства передачи информ ации, обрапцаемся к разным чувствам —и все
для повыш ения вероятности того, что материал будет закодирован в нескольких
областях вашего мозга.
Мы используем концепции и рисунки несколько неожиданным образом, потому
что мозг лучше воспринимает новую информацию . Кроме того, рисунки и идеи
обычно имеют эмоциональное содержание, потому что мозг обращ ает внимание
на биохимию эмоций. То, что заставляет нас чувствовать, лучше запоминается —
будь то шутка, удивление ш т интерес.
Мы используем разговорный стиль, потому что мозг лучше воспринимает и нф ор­
мацию, когда вы участвуете в разговоре, а не пассивно слушаете лекцию. Это
происходит и при чтении.
Так как проделанное запоминается намного лучше прочитанного, в книге вы
найдете более 80 упражнений. Надеемся, они заставят вас испы тать победное
чувство «я смог это сделать!».
Мы совместили несколько стилей обучения, потому что одни читатели лю бят по­
шаговые описания, другие стремятся сначала представить «общую картину»,
а третьим хватает фрагмента кода. Н езависимо от ваших личны х предпочтений
полезно видеть несколько вариантов представления одного материала.
Мы постарались задействовать оба полушария вашего мозга, это повыш ает веро­
ятность усвоения материала. П ока одна сторона мозга работает, др)тая имеет
возможность отдохнуть; это повыш ает эф ф ективность обучения в течение про­
должительного времени.
А еще в книгу включены истории и упражнения, отражаю щ ие другие точки зре­
ния. Мозг качественнее усваивает информацию , когда ему приходится оцени­
вать и выносить суждения.
В книге часто встречаю тся вопросы, на которы е не всегда можно дать простой от­
вет, потому что мозг быстрее учится и запоминает, когда ему приходится что-то
делать. Невозможно накачать мышцы, наблюдая за тем, как занимаются другие.
Однако мы позаботились о том, чтобы усилия читателей были прилож ены в вер­
пом направлении. Вам не придется ломать голову над невразумительными приме­
рами или разбираться в сложном, перенасыщ енном техническим жаргоном или
слишком лаконичном тексте.
В историях, прим ерах, картинках «живут» люди. Ведь вы человек. И ваш мозг
больше внимания уделяет людям, а не вещам.
28
введение
О
Условие
о
Действие
Ш ТУРМ
введение
Ч то cMO}keme сделать ВЫ, чтобы
заставить cßoü мозг повиноваться
Мы свое дело сделали. О стальное за вами. Эти советы станут отправ­
н ой точкой; прислуш айтесь к своему мозгу и определите, что вам
подходит, а что не подходит. П робуйте новое.
В р е ж ь т е а прикрепит е
ня холодильник.
©
Не торопитесь. Чем больше вы
поймете, тем меньше придется
запоминать.
Н е просто читайте. Обдумывайте. Н а­
ты каясь на вопрос, не читайте ответ
сразу. П редставьте, что вам его задал
человек. Чем больше вы заставляете
мозг думать, тем больше инф орм ации
вы пойм ете и запомните.
Выполняйте упражнения, делайте
заметки.
Д елать упраж нения за вас означает
вы полнять вашу работу. У праж нения
нужно не просто читать. Возьмите
карандаш. Вы бы стрее усвоите м атери­
ал, если будете записы вать результаты
своих размыш лений.
Читайте раздел «Часто задаваемые вопросы».
Это не просто вкладки с факультативной
и нф орм ацией —это часть основного
материала! Н е пропускайте их.
Читайте эту книгу перед сном.
Ч асть обучения (особенно перенос
инф орм ац ии в долгосрочную память) п ро­
исходит посмтото, как вы отклады ваете
книгу. Ваш мозг не сразу усваивает и н ф ор­
мацию. Если во время обработки посту­
пит новая и нф орм ация, часть того, что
вы узнали ранее, мож ет бы ть потеряна.
Пейте воду, и побольше воды.
М озг лучше всего работает при избы тке
жидкости. О безвож ивание уменьшает
способность к познанию .
Говорите вслух.
Речь активизирует другие участки мозга.
Если вы пы таетесь что-то понять или
получше запомнить, п роизн есите вслух.
А еш;е лучше —попробуйте объяснить
кому-нибудь другому. Вы будете бы стрее
усваивать материал и, возможно, откроете
для себя что-то новое.
Прислушивайтесь к своему мозгу.
С тарайтесь понять, не перегруж ен ли мозг.
Если только что прочи тан н ое сразу забы ва­
ется, явно пора на отдых. П ы таясь выучить
сразу слишком много, вы не ускорите
процесс усвоения материала, а, наоборот,
зам едлите его.
Пусть это станет реальностью!
П редставляйте себя героем историй. Д е­
лайте собственны е подписи к картинкам.
хихикать над плохой шуткой, чем
оставаться равнодушным.
Просто работайте!
Н аучиться програм м ировать можно только
одним способом: писать код. И м енно этим
вам и предстоит заняться. Н е пропускайте
упраж нения —обучение происходит в про­
цессе реш ения задач, даже таких необы чны х,
как «П риклю чения нарисованного человеч­
ка», поиск мест в ки н отеатре для настояш;их
мачо или заполнение блога YouCube. Н е
переходите к следуюш;им страницам, не
закончив упражнений. И, если вам доведет­
ся п оработать над реальны м проектом , не
забы вайте использовать приемы , описанны е
в книге.
дальше >
29
как работать с этой книгой
Примите к сведению
Это учебник, а не справочник. Мы нам еренно убрали из книги все, что могло
бы помеш ать изучению материала, над которы м вы работаете. И при первом
ч тен ии книги начинать следует с самого начала, потому что книга предполага­
ет наличие у читателя определенны х знаний и опыта.
Мы даем сведения, которые вам действительно требуются.
Если вы по другим источникам изучаете историю разви тия JavaScript, продол­
ж айте это делать, так как данная книга вам не поможет. О н а призвана научить
вас реш ать практические, каждодневные задачи по созданию интерактивны х
веб-страниц, с которы м и пользователям будет п риятно работать. Мы п ере­
ш агиваем через ф ормализм и рассматриваем только те п онятия из JavaScript,
которы е действительно потребую тся вам для работы .
Здесь не рассматриваются все нюансы языка JavaScгipt.
Разумеется, можно было бы описать все оп ераторы , собы тия, объекты и клю­
чевы е слова JavaScript, но было реш ено ограничиться более компактным
изданием, которое удобно иметь под рукой. П оэтому основной упор дается на
концепции, которы е используются программистами в 95 % случаев. Ч тобы
в результате вы получили способность самостоятельно писать сложны е сцена­
рии.
Суш;ествует больш ая библиотека уже готовых ф рагм ентов кoдaJavaScript,
и поэтому крайне важно понимать, когда следует писать собственны й вариант
функции или метода, а когда можно ограничиться стандартным. Слово «спе­
циальный» в этой книге означает, что код долж ен быть написан вами лично,
а не взят из библиотеки JavaScript.
В процессе чтения желательно пользоваться разными браузерами.
Н есм отря на то т факт, что все соврем енны е браузеры поддерж иваю т
JavaScript, имею тся небольш ие различия в процедуре обработки кода сце­
нариев. И м енно поэтому ж елательно п роверять результаты своей работы
по крайней мере в двух браузерах. И звестно, что лучше всех с обработкам и
ош ибок справляется Firefox. Н о не стесняйтесь п опросить друзей и знакомых
п ротести ровать ваши сценарии и в их браузерах также.
30
введение
введение
Упражнения обязательны.
У праж нения являю тся частью основного материала книги. О дни упражне­
ния способствую т запоминанию материала, другие помогаю т лучше понять
его, тр етьи ориен тирован ы на его п рактическое прим енение. Не пропу­
скайте упражнения.
Повторения применяются намеренно.
У книг этой серии есть одна принципиальная особенность: мы хотим, что­
бы вы действительно xojbomoусвоили материал. И чтобы вы запомнили все,
что узнали. Больш инство справочников не ставит своей целью успеш ное
запоминание, но это не справочник, а учебник, поэтому н екоторы е концеп­
ции излагаю тся в книге по нескольку раз.
Примеры кода были сделаны по возможности компактными.
Наш и читатели не лю бят п росм атривать по 200 строк кода, чтобы найти
две нужные строки. Больш инство прим еров книги приводится в минималь­
ном контексте, чтобы та часть, которую вы непосредственно изучаете,
была п онятной и простой. Н е ждите, что весь код будет стопроцентно
устойчивы м или даже просто заверш енны м —прим еры написаны в учебных
целях и не всегда являю тся полнофункциональными.
Все варианты кода из наш ей книги помещ ены в И н терн ет, чтобы дать вам
возмож ность скопировать их к себе и исследовать. Скачать их мож но по
адресу
http: //w w w . headfirstlabs. сот/books/hfjs/
Упражнения «Мозговой штурм» не имеют ответов.
Б некоторы х из них правильного ответа вообщ е нет, в других вы должны
сами реш ить, насколько правильны ваши ответы (это является частью п ро­
цесса обучения). В некоторы х упраж нениях «М озговой штурм» приводятся
подсказки, которы е помогут вам найти нужное направление.
дальше *
31
обзор команды
Технические редакторы
Ты Ви Сканнел
Ф летчер М ур
Алекс Л и —студент Хью­
стонского университета,
специализирую щ ийся на
автом атизированны х систе­
мах управления. О бож ает бег,
ком пью терны е игры и изуче­
н ие новы х язы ков програм ­
мирования,
К ат ерина
С ент -Дж он
Элейн Нельсон
Стивен Т аллент
Захарий Кессии
А лекс Ли
тм Холденер III
Ти Ви Сканнел и з города
С истерс, ш тат О регон, за­
ним ается програм м ировани­
ем с 1995 года. Разработчик
каркаса Ruby on Rails.
Элейн Н ельсон заним ается разработкой веб-сайтов около 10 лет. Как она говори т своей м атери, ученая сте­
пень в английском язы ке много где мож ет пригодиться. У знать о текущ их увлечениях Э лейн вы мож ете на ее
сайте — elainenelson.org.
Ф летчер Мур является веб-разработчиком и дизайнером в институте G eorgia Tech. Увлекается велоспортом ,
музыкой, садоводством и является ф анатом бейсбольной команды R ed Sox. П рож и вает в А тланте с ж еной
К атариной, дочерью С эйлор и сыном Сэтчелом.
Энтони Ти Х олденер III является разработчиком веб-прилож ений и автором книги Ajax: T h e Definitive G uide,
такж е выш едш ей в издательстве O ’Reilly.
Захарий К есси н заним ается веб-програм мированием около 15 лет. П рож и вает в И зраи ле с ж еной и трем я
детьми.
Катерина Сент-Джон —доцен т каф едры и н ф орм ати ки и математики в университете города Н ью -Й орк, зан и ­
мается исследованием в области вы числительной биологии и случайных структур.
Стивен Таллент ж ивет и работает в городе Н эш вилле ш тата Т еннеси, разрабаты вая спортивны е прилож ения
и воспиты вая м аленьких детей. К ром е того, он увлекается катанием н а роликовой доске и кулинарией. И даже
готовится сделать вторую карьеру в качестве повара в буфете.
32
введение
введение
Благодарности
Моему редактору;
П омните, в начальной школе нам предоставляли возмож ность п ерепи­
сы ваться с детьми из других городов, обмениваясь инф орм ац ией о своей
жизни? И м енно таким другом по переписке стала для меня Катрин Но­
лан с момента начала этого проекта. Мы общ ались по телефону, элек­
тр о н н о й почте, факсу. В процессе этого общ ения К атрин стала больше
чем коллегой по работе над изданием. О н а стала моим другом. И часто
«деловые» звонки заканчивались переходом от разговоров п ро JavaScript
к обсуждению других наших увлечений. Мы оба получили удовольствие
от работы и от ее конечного результата. Спасибо, К атрин. Я помню, что
задолжал тебе несколько мартини.
Команда издательства O’Reilly:
К ат рин Нолан, покло н­
ница десятичной с и с т е ­
мы счисления.
Сложно подобрать слова для команды H ead First. Н о я попробую.
Бретт МакЛафлин с момента моего появления в лагере ново­
бранцев H ead First заставил меня сконцентрироваться. Этот
парень одинаково серьезно относится как к необходимости
Б р ет т М акЛаф лин
анализа сценариев в процессе обучения, так и к игре на гитаре.
команды Heat
Я уверен, что даже ко сну он отходит, предварительно задав себе
поклонник
вопрос; «Зачем я это делаю?» Н о именно его вклад помог создать
такую выдающуюся книгу. Спасибо, Бретт!
Лу Барр стала ещ е одним моим другом по переписке.
Мне кажется, она спустилась к нам откуда-то с дизай­
нерского Олимпа. Б ез нее мы никогда не получили
бы столь прекрасно сверстанной книги.
Вряд ли процесс работы над книгой протекал бы
столь гладко без Сандерса Кляйфелда. И м енно он
нашел выход из многих слож ны х ситуаций.
Я не забыл и об остальны х членах команды O ’Reilly.
Лари Петриски поверила в меня настолько, что­
бы запустить данны й проект, Кетрин МакКаллох
-Лу Барр,
богиня ди^
зайна.
обеспечила поддержку сайта (www.headfirstlabs.com),
а Кейт МакНамара с удивительной точностью запол­
нила все пробелы. Спасибо, ребята!
Ну и наконец, самой теплой благодарности заслу­
жили, наверное, Кетти Сьерра и Берт Байте за их
потрясаю щ ее видение всех серий H ead First. Работа
в этой команде была для меня счастьем...
дальше »
33
/
и н ш ер ак ш и Б н ая
сеш ь
+
Реакции виртуального мира %
Устали представлять Интернет набором пассивных стра­
ниц? Кто из нас не держал в руках книг. Их читаешь, в них находишь
информацию. Но они не интерактивны. Как и интернет-страницы без
JavaScript. Без сомнения, отправить данные формы и проделать другие
трюки можно и при помощи кода HTML и CSS, но реальная интерактив­
ность требует более умного подхода и большей работы... зато и резуль­
тат впечатляет намного больше.
нужды пользователей
То, что ну)кно людям
Мы знаем, что И н терн ет —это виртуальная реальность, но
пользуются им вполне реальны е люди, с реальны м и нуждами.
Им требую тся убойные рецепты мясного рулета, возмож ность
скачать любимую песню или даже купить новы й дом. К счастью,
когда дело доходит до ваш их нужд, сеть ведет себя по-разному!
©оо„
H ouse F inder
О
Ready to find a new house?
Enter your annua} income; jSOOOO
Enter the numtier of bedrooms;
Enter your ZIP code;
Done
36
глава 1
Наконец-то я легко смогу купить
дом через Интернет. Укажу свой
годовой доход и параметры дома,
остальное будет сделано автомати­
чески.
ввод данных
пользоват елем .
интерактивная сеть
и ничего... как будто говоришь со стенкой
Сеть не всегда реагирует так, как вам хотелось бы. Б олее того,
зачастую она каж ется соверш енно равнодуш ной, отдельной от
внеш него м ира и никак не отвечаюш,ей нуждам м ногочисленны х
пользователей. Вы ож идаете реакции на введенны е вами данные...
но ничего не происходит. Н е приним айте это близко к сердцу, ста­
тический И н тер н ет по-другому просто не умеет.
П ользователь ввел данные.■■
но ничего не произошло.
\
дальше >
37
интерактивность с Javascript
А JavaScript отвечает
Я зы кJavaScript подобен выключателю, переводящ ему страницу
в интерактивны й режим. О н активирует функции, которы е п ри ­
слушиваются к нуждам пользователей, обрабаты ваю т вводимые
данны е и отвечаю т на запросы . Возможно, это некоторое преуве­
л ичение, но им енно JavaScript позволяет п реврати ть веб-страницу
в и нтеракти вное прилож ение, вдохнув в нее жизнь!
0ОО
Щ е л к й е т на кнопке для
получения результ ат а.
JavaScript оживляет веб-страницы, позволяя
им отвечать на ввод пользовательских данных.
38
глава 1
интерактивная сеть
Please enter a number.
f
OK - " ?
codT Z iZ r
e o e
H ouse Finder - Matches_
T he following h o u s e s w ere found:
Поиск ииф орМ йцыы на сервере
осущ ест вляет ся
в соответствии^^
с заданными
парам ет рам и.
110 Etm Street View
1
400 Map!© Lane
View {
847 Main Street
View
Done
Vou can affo rd a house that costs up , 0 , 3 2 0 0 0 0 .
Расчет произведен,
исходя из введен­
ных пользоват елем
данных.
^
дальше *
39
HTML, CSS и JavaScript
B s a u iM v o
C6em, камера,
^ действие!
HTM L, CSS и JavaScript —это три ки та соврем енного конструирования веб-страниц. HTM L обеспечи­
вает структуру, CSS добавляет стиль, а JavaScript обеспечивает «сцепление с дорогой». Ч тобы п рой ­
ти путь к интерактивны м веб-страницам, вы долж ны следовать от структуры (HTML) в стиле (CSS)
к действию (JavaScript). Как и в CSS, в JavaScript код часто находится непосредственно внутри веб­
страницы.
<html>
СТРУКТУРА
<head>
</head>
<body>
^‘^idii'*idi"heIdsr">Ready to find a new house?</dlv>
<div id="left">
<img src-"house.png" alt-'House
/>
</div>
<form name=
<style type="text/css">
<div clas
body {
<input
font:14px arial;
</div>
text-align:center;
<div clas
}
<input
</div>
#frame {
<div clas
width:400px;
<input
}
</div>
<input tyi
#header {
<script type="text/javascript">
<input ty]
font:l6px arial;
function v a l i d a t e N u m b e r (value) {
</form>
font-weight:bold;
// Validate the number
</div>
margin-bottom:15px
/ / i f (!isNumber (value))
</body>
alertC'Please enter a number.");
)
</html>
#left {
float: left;
width:llOpx;
д ействие!
JavaScript
}
e) {
function v a l i d a t e Z I P C o d e (value)
// Validate the ZIP code
}
div.field {
margin-bottom;lOpx
text-align:right;
}
</style>
function calcPriceO
var maxPrice =
{
document.getE l e m e n t B y I d ( " i n c o m e ) .value
d4,
alert("You can afford a house that costs up to
maxPrice +
7
function findHouses(form)
{
var bedrooms =
do c u m e n t . getElementById("bedrooms ) .value,
HTML дает
нам каркас.
var zipCode =
document.getElementByld("zip") .value;
// Display a list of matching houses from the server
form.submitO ;
|| </script>
r
CSS добавляет в и ­
зуальный ст иль.
40
глава 1
JavaScript добавляет
^ФУ^Щ иоиальность,
fпозволяя ст ранице
^вы полнят ь различные
1о'ействия.
интерактивная сеть
О
House finder
@ 0в
Rgfirfy tn flndanew bouse?
Enter your annual income: |
EnKsr fte numbo-of
E m s your ZIP wS--*-----—
Done
__ _
Все компонент ы ст раницы
Нй м ест е, но они не о т ­
ф орм ат ированы и не очень
красиво выглядят...
House Finder
Ready to find a new house?
Enter your annual Income: jioooo
О
Эта стрлнии,й
выглядит, намного
м ц м г Т ^ она пока
ничего н е д г т е £ л -
____У
Enter the number of tiedrooms:
Enter your ZIP code: [95014
c >
Calculate Wee 1 Shop for H q u ^
Done
А вот т еперь вы
мож ете получит ь
от вет !
You c m afford а h ouse th aï co sts up to 5320000.
а
к
э
Спасибо, JavaScгipt!
Я вот-вот найду холостяцкую
берлогу, о которой давно
мечтал.
JavaScripl начинает работу,
как только пользователь
просит страницу выполнить
какую-либо задачу.
дальше *
41
зачем нужен JavaScript?
А разве все то же самое нельзя
сделать средствами HTML и CSS?
Интернет прекрасно работал и до
появления JavaScript.
HTML u CSS недостаточно интерактивны
П роблема именно в недостаточной интерактивности HTM L
и CSS. В CSS существует набор приемов, позволяю щ их управ­
лять стилями в специф ических ситуациях, наприм ер при на­
ведении указателя мыши на ссылки, но ваши возмож ности все
равно крайне ограничены .
Благодаря JavaScript вы зам ечаете все происходящ ее на стра­
нице, наприм ер щ елчки пользователя на кнопках, изменение
разм еров окна обозревателя или ввод данны х в текстовое поле.
А так как JavaScript —это язы к написания сценариев, вы можете
написать код, отвечаю щ ий на действия пользователя, н апри­
мер, вы полнением вы числений, динам ической зам еной изобра­
ж ения или п роверкой данных.
ГАССЛА 1) 1>Т1 С1)
Не беспокойтесь о дета­
лях.
JavaScript позволяет
очень многое, но вы
пока в самом начале
знакомства с этим языком. Смею вас заверить,
что собы тия, функции и многие другие элементы
JavaScript со временем станут для вас понятны ми.
К роме того, есть вероятность, что вы уже знаете
намного больше, чем вам кажется.
HTML + CSS + JavaScript = РЕАЛЬНАЯ интерактивность
42
глава 1
интерактивная сеть
Возьми В руку карандаш
Вы уже знаете больше, чем вам кажется. Посмотрите на код
для страницы House Finder и напишите, что делает каждый из
выделенных фрагментов кода. Не бойтесь строить догадки.
<html>
<head>
<title>noMCK f l O M O B < / t i t l e >
<script type="text/javascript">
function validateNumber(value)
{
// Проверка ввода числа
// if (!isNumber(value))
a l e r t ("Пожалуйста, введите число.");
}
/ J ^ t i o n validateZIPCode (value)
I
{
// Проверка ввода индекса
// if (iisZIPCode(value))
a l e r t ("Пожалуйста, введите индекс в формате Х Х Х Х ^
ler'
t:'("tibi' м о ж е т е ^ озвоТить дом стоимостью до $
function findHouses (form) {
^
„„.м valuevar bedrooms = d o c u m e n t .g e t E l e m e n t B y l d ( bedroom
).
var zipCode = document.g e t E l e m e n t B y I d ( " z i p " ) .value,
// Отображение списка подходящих домов с сервера
f o r m.submit();
}
</script>
</head>
<body>
<div id="frame">
<div id="header">r0T0Bbi к поиску нового д о т
<div id="left">
<img src="house.png" alt="House" />.
< f o m name="orderform" a c t i o n = " . . ^ e t h o d = " P O S T " >
<div class="field">Укaжитe ва 1^ г о д о в о и доход:
size^l2
<S^biur="validateNumber(this.value)"7^</div>
<di7Tlass="iield" >Б55дитЪ~^^^гаю^Н5лен:
<input id="bedrooms" type="text" size-"6'^
onblur="validateNumber(this.value) " / > < / d ± v >
<div olass="field">BBeflHTe индекс:
<input id="zip" type="texj:L.ai^e;:;^
/></div>
onblur="validateZIPCode W j i ^ a l u e
цену"
<input type="button" уа1ие="ВычИСТО1
oncliclc="calcPrice()
/>
^innnt f.vpe="button" у а 1 и е = " К у п и т ^
, « H ^ Tcl?^itodHouses (this .f o r m ) 7 > /
</fOrifL5
</div>
</body>
</html>
дальше *
43
решение упражнения
Возьми Вруку карандаш
Решение
Вот какую функцию выполняют выделенные фрагменты кода.
Надеемся, ваши догадки совпали с правильными ответами.
<html>
<head>
< t i t l e > n o M C K flOMOB</title>
<script type="text/javascript">
function validateNumber(value)
// Проверка ввода числа
//if
{
(!i s N u m b e r ( v a l u e ) )
a l e r t ("Пожалуйста,
введите число.");
двести индекс в ф о р ­
}
м а т е ХХХХХ.
✓f^I^ction validateZIPCode (value) {
~
I I Проверка ввода индекса
(
11 if (IisZIPCode(value))
V
a l e r t ("Пожалуйста, введите индекс в формате ХХХХХ.
f
Вьічисляет м аксим альную
1 —--------------—-------
цену дома, умножая доход
пользоват еля на четыре.
");
function findHouses (form) {
,
var bedrooms = document.getElementByld("bedrooms ) .value,
var zipCode = d o c u m e n t .g e t E l e m e n t B y l d ("zip").value.
// Отображение списка подходящих домов с сервера
form.submit ();
</script>
</head>
I
<Ьody>
<div id="frame">
<dlv id="header">Гoтoвы к поиску нового д о м а ? < ^ 0 ^
<div id="left">
<1тд згс="Ьоизе.рпд" a l t = " H o u s e ' ' ^ ^
П роверяет, было ли
введено число в поле
income.
<£огт name="orderform" a c t j ^ p « ? < ^ method="POST">
<div class="field">Укaяa^*€ ваш годовой доход:
тr^-<^■vnгnmp"^fype="text" з 1 ^ = " 1 2 "
<Г^lur="validateNumber (this.value^5/></dlv>
<^1у class="ileld">Uвeдитe число спален:
<iпput id="bedrooms" type="text" 31ге="6"
onblur="validateNumber(this.value)"/></div>
К ,., Значение в поле вво -
да ZIP co d e.
<div class="field">Bвeдитe индекс:
<input id="zip" type="teль::-.aiz^l0j^
onblur="validateZIPCode<tth^• уа1и^ ”/></dxv>
< input tvpe="button" уа1ие="5ачистпТть цену"
OTiclick="calcPrice О ;
ияТие="Купить дом"
onclick="findHouses (this .form) ; />
гртпп у р ё - ' bULLun"
>Гщ:
</form>
</div>
</body>
</html>
44
глава 1
^После щелчка на кнопке
вычисляет м аксим альную
т ну дома.
интерактивная сеть
Тег < script >
П оместим ф рагм ент на язы ке JavaScript непосредственно в НТМЬ-код, как
было показано на предыдущей странице. П ервы м делом вы долж ны дать по­
нять браузеру, что он будет иметь дело с JavaScript... и здесь вам на помощь
п ридет тег < s c r i p t > .
Этот тег добавляется в произвольное место НТМЬ-кода, но обы чно его по­
мещают внутрь заголовка. Вот таким образом:
<html>
<head>
<title>House Finder</title>
Э т от т ег говорит
о т о м , чт о внут ри
находится некий сце- . яяккоМ
нарии
Тег script
на HTML-
function validateNumber(value) {
// Проверка ввода числа
/ / i f (!isNumber(value))
alert ("Please enter a number.'')
ст ранице
oSmmo по­
м ещ ает­
ся внут рь
т ега head.
и
иа
JavaSc^nlpt.
<script type="teKt/javascript">
ф рагм ент между от кры ваю щ им
и закры ваю щ им т егам и scrip t н а ­
писан на языке JavaScript... браузер
поним ает , чт о эт о уже не HTML,
а язык написания си,енариев.
}
</script>
бюацзерц,
дальше опятс/ п
<body>
ет ся оШиный HTML-код.
<!— Остальная часть HTML-кода — >
</body>
</html>
Чаап°
---- <аДаБаеМые
-
Б:
То есть все, что я помещу между
тегами < s c r i p t > , будет относиться
к JavaScript?
О
; Не обязательно... тег <script>
говорит браузеру, что начинается
сценарий, но он может быть и на другом
языке. Язык сценария определяется
вчасти type="text/javascript'
3
------------
Б о ц р * о с :ь 1
/ I То есть я могу использовать
и другие языки сценариев?
Q;
Конечно. Microsoft предоставляет
вам VBScript (версия языка Visual
Basic) и разновидность Ajax, которая
называется ASP.NET AJAX. О последней
мы поговорим в главе 12. Существуют
и другие языки сценариев. Но в этой книге
мы всегда будем использовать
javascript.
text/
Должны ли элементы < s c r i p t >
располагаться внутри тегов < h e a d > ?
расп
0.
Поместить теги < s c r i p t > можно
куда угодно... но их расположение вне
заголовка считается дурным тоном. Это
все равно что вставить в середину веб­
страницы стили CSS... фрагменты на
JavaScript лучше выделять в отдельную
группу, и для этого прекрасно подходит
часть страницы, ограниченная тегами
<head>.
дальше *
45
команды браузеру
Ваш браузер понимает HTML, CSS
U JavaScript
Как вы знаете, браузеры умеют отображ ать HTM L-код. Н а
язы ке CSS мы объясняем браузерам, как именно показы вать
различны е части HTML. С оответственно, язы к JavaScript —
это всего лиш ь ещ е один способ вашего общ ения с браузе­
ром... Н о на этот раз вы уже не указываете способ отобра­
ж ения, а подаете команды.
St" открываете,
браузер и вводи т е URL...
Г"
S e 6 - c e p 6ep
определяет ,
кйкую стрлнмцу
в а м показать.
Ш
®
в о е
браузер отобража&т
H T M L - к о З в со о т ­
вет ст вии с правилам и
С55...
^
■
H0U5« FMer...
...
Веб-страница
Ready to find a new house?
Enter your annual Income; jsoooo
Enter the number of bedrooms: |3
Enter your ZIPcode: |5ioi4
Ctone
__
Запц-
you can afford a house that costs up to $320000.
G
ЯЖИ
46
глава 1
Сервер о т д а е ^
¥ а у з е р у страны-*
чу, полную т е HTML, правил
интерактивная сеть
_
часщо
ЧаДаБаеМые
Б о їїр о с ь і
Б
•
Каким образом браузеры
запускают код иауа8сг1р1?
Насколько безопасно работать
с JavaScript?
0 » В браузеры встроено специальное
программное обеспечение, называемое
интерпретатором иауаЗспр!. Именно
он запускает написанный на этом
языке код. Именно поэтому иауаЗспр!
называют инт ерпрет ируемы м языком
программирования, в отличие от
т ранслируемого. Транслируемые языки,
например С++ или С#, необходимо
сначала преобразовать в исполняемый
файл при помощи компилятора.
Программам на иауаЗспр1 этого не
требуются, так как они интерпретируются
непосредственно браузером.
О
атрибута
! По большей части безопасно.
иауаЗспр! исходно разработан таким
образом, чтобы затруднить выполнение
вредоносного кода. К примеру,
средствами JavaScript невозможно
осуществлять чтение и запись файлов
на жестком диске пользователя. Это
ограничивает возможность применения
большинства вирусов. Разумеется, можно
написать вредоносный код и на иауаЗспр!.
В прошлом, из-за конструктивных
недостатков браузеров хакеры нашли ряд
дыр в безопасности иауаЗсг1р1, так что
назвать этот язык совершенно надежным,
увы, не получится.
Как заставить веб-страницу
запустить код иауаЗсг1р1?
Тег < s c r i p t > в программе
House Finder относится к HTIVIL или
0 * В большинстве случаев такой код
запускается после какого-то действия,
например загрузки страницы или щелчка
к JavaScript?
пользователя на кнопке. Включение
кода иауаЗсг1р1 после каких-то действий
производится при помощи механизма,
называемого «событием».
гіражнше
• у г ір
ажн
сценариев, вы указываете, на каком языке
будет написан ваш сценарий, при помощи
0 ; Сам по себе тег <script>
принадлежит HTML и предназначен для
встройки сценариев в код веб-страниц.
Внутри тега <script> вы видите код
JavaScript. Так как сам тег разработан для
поддержки нескольких языков написания
type.
Кажется, я встречал
интерактивные страницы, к примеру,
с формами, проверяющими
корректность введенных данных,
созданные без JavaScript. Такое
возможно?
Конечно. Сделать страницу
интерактивной можно и без JavaScript,
но в большинстве случаев такая
реализация будет неэффективной
и тяжеловесной. К примеру, проверка
корректности введенных данных может
быть осуществлена на сервере при
отправке формы. При этом вы ждете
ответа сервера в виде новой страницы.
С таким же успехом для проверки
можно воспользоваться карандашом
и бумагой! JavaScript позволяет обойтись
без загрузки новых страниц и ненужной
передачи данных на сервер и обратно.
А многие функции, реализуемые при
помощи JavaScript, альтернативно могут
быть реализованы только при помощи
сторонних встроенных программ для
браузеров.
Определите, является ли фрагмент кода стандартным выражением JavaScript
или же это выражение введено программистами, которые написали страницу
House Finder (вариант Custom):
alert
JavaScript / Custom
onblur
JavaScript I Custom
calcPrice
JavaScript I Custom
onclick
JavaScript I Custom
zipCode
JavaScript I Custom
findHouses
JavaScript I Custom
var
JavaScript I Custom
value
JavaScript I Custom
дальше
►
47
решение упражнения
п'ражнение
Итак, какие же куски кода являются стандартными выражениями язы­
ка иаУзЗспр!, а какие были введены программистами:
решение
Всплывающ ее окно, указывающее
на некоррект ное число.
<head>
<title>noHCK flOMOB</title>
<script type="text/javascript">
function validateNumber(value)
// Проверка ввода числа
/ / i f (!isNumber(value))
alert("Пожалуйста, введите число.
}
с— --- alert
П ользовательский кусок кода,
вычисляющий ст оим ост ь
’);
дом с^
^
function validateZIPCode(value) {
// Проверка ввода индекса
// if (IisZIPCode(value))
,
alert ("Пожалуйста, введите индекс в формате ХХХХХ.
)
_
^ c a lc P ric e
JavaScript
/(сйзБгтГ)
Задает внешнее м ест о
хранения данных.
'p 'r a x p f i f e " i 'd o L L n t . g e t E l e m e n t B y I d ( " l n c o m ^ 4 . v a l u e * 4;
' f f 'alert("Вы
'"
CjavaSc^/ Custom
C JavaScri^ Custom
можете позволить дом стоимостью до S
1
П ользовательский код поиска подходящих домов.
/
function findHouses (form) {
valuevar bedrooms = document. getElementById( bedrooms^)-val
var
“ document.getElementByld( zip ).
// Отображение списка подходящих домов
findHouses
JavaScript ( j^u s to n T )
Z ip C o d e
JavaScript (^CustoirT)
сервера
form.submitO ;
</script>
</head>
<body>
<div id="frame">
<div id="header">r0T0Bbi к поиску нового дoмa.</dlV
<dlv id="left">
<img src="house.png" alt="House
М есто хранения введенного
пользоват елем индекса.
/> _____________
опЫ иг
<div claз«^field">Укaжитe ваш годовой
<inpi^^d="income" type="text" size="12"
onblu?="validateNumber(this. value)"/></div>
<div class="field">BBeflHTe число спален:
<input id="bedrooms" type="text" size-"6"
onblur="validateNumber (this . v ^ e ) "/></div>
<div class="field">Bвeдитe индек(^^;^^
id="zip" type-"text"
s i z e = -n^
<lnput ia="ZipLYpeonblur="validateZIPCode (this.value) /></div>
<input type="button" value="Bычиcлить цену"
o n c l i c k = " c a l c P r i c e ( ) />
<input type="button" value="KynnTb дом"
oncliclc="findHouses (this .form) ;" />
(^Ja va S crlp Q Custom
^У к а зы ва ет , чт о пользоват ель
переш ел к следую щ ем у полю
ввода.
- v a ii^
( j a v a S c r l ^ Custom
Текущ ее значение поля
ввода индекса.
■o n c ii^ c k
(JavaS cript)/ Custom
Указывает,, чт о была
наж йм й кнопка „ К уп и т ь
48
глава 1
?
I
I
интерактивная сеть
Помоги виртуальному другу человека
С веж енаняты й успеш ный программист на HTM L и CSS вызван
к начальству для дем онстрации последнего и зобретения, которое
назы вается iRock. Виртуальный домаш ний лю бимец наделал шума
на всех конф еренц и ях игрушек, но пользователи недовольны его
поведением.
О ни щ елкаю т на изображ ении и ждут чего-то необычного... Значит,
вы долж ны сделать iRock интерактивным и прославиться... или
кануть в небы тие вместе с ним.
в в
—
Перед вами {Rock. Он
сост оит из кода HTML
LS!?'
не взаи­
м одейст вует с п о льзо ­
ват елями.
Virtual t>et «оск
О
.
При щелчке пользоват еля
на элем ент е iRock ничего
не происходит.
Разгневанные
‘п ользоват ели
дет а-версии
обрывают
т елеф он тех.
‘поддержки.
Ш ТУРМ
Что должен делать iRock, взаимо­
действуя с пользователями?
Ты чувствуешь, как
я щелкаю мышью?
дальше >
49
стратегия взаимодействия
Сделайте ^Rock интерактивным
Вы не просто сделаете объект 1Яоск интерактивны м , но
попутно познакомитесь с JavaScript. Вы бы стро научите
вашего домаш него лю бимца здороваться.
П еречислим список ваших задач.
О
©
О
Создайте для 1Роск НТМи-страницу.
Заставьте объект !Роск приветствовать
пользователей при загрузке страницы.
Напишите код, запрашивающий имя
пользователя для личного приветствия
и заставляющий объект улыбаться.
Добавьте обработчик события, запуска­
ющий написанный на шаге З^од в ответ
на щелчок на объекте.
0
50
Вы уже знает е,
как эт о сделать.
Заслужите одобрение и благодарность
начальства.
у..пава 1
Вы соединяете действия
пользоват еля, наприм ер
щ елчок на изображении
домашнего любимца...
интерактивная сеть
Веб-страница iRock
Более простую НТМ Ь-страницу, чем 1Коск, найти невозможно.
Введите указанный ниж е код в ваш лю бимы й редактор и сохра­
ните его под именем iRock.htm l. Нужные и зображ ения скачай­
те с наш его сайта http://www.headfirstlabs.com.
<html>
<head>
<title>iRock - Виртуальный любимец Rock</title>
</head>
<body>
<div style="margin-top:lOOpx; text-align:center">
<img id="rockImg" src="rock.png" alt="iRock" />
</div>
</body>
</html>
He
"7
за б ц д от е ск а ч а т ь
irock.html
Часзцо
Тестирование
П еред тем как двигаться дальше, сохраните и про­
тестируйте страницу 1Коск в браузере. Убедитесь,
что результат выглядит именно так, как показано
на рисунке, так как все уже ф актически готово,
чтобы сделать его и нтерактивны м при помощи
JavaScript.
____ з а д а в а е м ы е
_____
B o IIP o C b l
Б:
Внутри тега < d i v > находится CSS?
Да. Вы угадали.
3 * Я думал, что не стоит помещать CSS
непосредственно на HTML-страницу. Зачем это
сделано?
•
Да, обычно лучше поместить CSS в тег <style>
в заголовке страницы или на отдельную таблицу стилей.
Но ваш начальник не очень хорошо в этом разбирается,
а такая запись упрощает пример. Но если вы хотите
написать собственную таблицу стилей для файла iRock,
обязательно сделайте это.
дальше ►
51
знакомство с событиями
События
Ч тобы заставить объект п риветствовать пользователя после загрузки
страницы , нужно реш ить две задачи: определить м омент окончания
загрузки и придумать способ отображ ения приветствия.
Реш ение первой задачи связано с реакцией на собы тие (загрузку
страницы ), а во втором случае вам потребуется встроенная функция
«alert». Событиями {Events) в JavaScript назы ваю тся уведомления о про­
исходящем, наприм ер о загрузке страницы (onload) или о щ елчке на
кнопке (onclick). В качестве ответа на подобные действия можно
написать ваш собственны й код JavaScript.
.Rock-TheVinuaS
Событие onload срабат ы ва­
е т после окончания загрузки
ст раницы iRock в браузере.
o n l o ‘a d !
Код для события onload
задан в а т рибут е
onload т ега <body>.
События являются уве­
домлениями, в ответ на
которые защгскаетея код
JavaScript.
М етод alertQ вызывает окно
диалога с привет ст вием .
НеНо, Iam your petrock.
€E K 3
52
глава 1
интерактивная сеть
Оповещение пользователей
JavaScript позволяет вы звать отдельное окно с инф орм ац ией для
пользователей. Д ля этого вам потребуется написать код, вы зы ­
ваю щий метод alert {) и передаю щ ий ему отображ аемы й текст.
Методами назы ваю тся ф рагм енты кода м ногократного использо­
вания, предназначенны е для реш ения общ их задач.
alert О
^ Е с л и сразу после ключевого
слова Ja va5cript вы видите
скобки,, скорее всего, эт о
название /метода.
ЦоДроёно Про
Мето°Ды
Указывает, чт о нужно щ елкнут ь на кнопке « К у п и т ь дом>
a lert — эт о вст роен­
ный м ет од, от обра­
жающий всплывающее
окно.
с х
Э т от т е кс т появит ся
во всплывающелл окне.
Не забудьте заклю чит ь
его 6 кавычки.
Л.
Текст
И нф орм ация, передаваемая
. м ет одам J a v a S c n p t ■— в н а ^ илем случае эт о отображ ае­
мый т екст , — заклю чает ся
в скобки.
А
J
>нце п р ед лблче.ныя принят о
ст авит ь т очку, т о
каждую ст року кода
■^луаЗспрЬ заверш ает
точка с запят ой.
С оединив все вместе, вы получите строку кода JavaScript.
О на вы зы вает метод, отображ аю щ ий во всплывающем окне
указанное вами приветствие:
alert('Hello, I am your pet rock.');
Спокойно!
Методами называются
фрагменты кода много­
кратного использования.
л
Отображ аемый т екст
заклю чает ся в кавычки.
С обы тия
в этой книге
будут фигурировать часто,
и постепенно вы выучите
синтаксис и поймете, как им
пользоваться.
дальше >
53
поприветствуем пользоват елей
iRock приветствует вас
Ч тобы поприветствовать пользователей после загрузки страницы iRock,
вам потребую тся обработчик собы тия onload и метод alert ( ). Д обавьте
следующую строчку на JavaScript в код irock.html:
<html>
<head>
,ead>
<title>iRock - The Virtual Pet Rock</title>
</head>
Хотя событие
onload even t _
работ ает Зля
всей ст р а н и ­
цы, вы задаете
его в качестве
ат рибут а
т ега <body>,
т ак как имен но эт а часть
ст раницы вид­
на в браузере.
<body onload="alert('Hello, I am your pet rock.
<div style="margin-top;lOOpx; text-align:center">
<img id="rockImg" src="rock.png" alt="iRock"
</div>
</body>
</html>
П омнит е, чт о код на Ja va S crm t
вст роен непосредственно в Ш
уш ю т
’ _
irock.html
Проверка интерактивности
Т еп ерь страница iRock стала более и нтерактивной благодаря окну
с приветствием, появляющемуся в ответ на собы тие onload. Загрузи­
те в браузер страницу irock.html и посмотрите, что произойдет.
iRocit - ТЬеViRual WRotli
_ Сразу же после за гр у з­
ки ст раницы появит ся
дополнит ельное окно
с <лриветствием.
Hello, i am your pet rock.
54
глава 1
интерактивная сеть
Ч асто
'^адаБаеМые
B o ilp o c jji
Существуют ли методы кроме
Откуда берутся события?
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
alert о ?
а1<
О
! События, конечно, инициируются
пользователем, но реализуются
браузером. К примеру, при нажатии кнопки
браузер должен распаковать информацию
(какая именно кнопка была нажата)
и передать ее методу, который отвечает
События отвечают на
I Да, их множество. Метод alert () —
это только верхушка айсберга. По мере
вашего знакомства с JavaScript вы даже
научитесь создавать свои собственные
методы.
Событие onload про­
исходит в момент окон­
чания загрузки страницы.
Почему код события o n l o a d
содержит кавычки и апострофы?
соде
Вы отвечаете на со­
бытие onload, задав
атрибут onload в теге
0:.
<body>.
за данное событие.
А что будет, если не связать
особ
с
событием никакого кода?
0:.
Если рядом с падающим деревом
никого нет, производит ли оно шум? Вот
также и с событиями. Если на событие нет
ответа, браузер просто продолжает свою
работу.
Б
Код JavaScript это то, что
заключено между тегами <script>?
; Обычно да. Но этот код можно
поместить и непосредственно
в обработчик события, как вы видели
на примере события onload. Именно
так обычно и делают, когда требуется
запустить всего одну строчку кода
JavaScript как для объекта iRock.
происходящее на страни­
це кодом JavaScript.
! В HTML и JavaScript перед тем, как
начать новое предложение, требуется
закрыть предыдущее... если вы не
используете другого разделителя.
Поэтому, когда код JavaScript появляется
внутри атрибута HTML (текст внутри
другого текста), решить эту проблему
можно совместным употреблением
кавычек и апострофов. При этом не важно,
что именно вы используете для атрибута
или текста JavaScript, главное — быть
последовательным. Приведем пример
из обычного языка: «При щелчке iRock
говорит „Hello there“». Именно по такому
принципу должны располагаться кавычки
Методы связывают код
JavaScript в модули
многократного использо­
вания.
Некоторым методам
нужно передавать ин­
формацию.
Метод alert О ото­
бражает окно с тексто­
вым сообщением.
и апострофы.
КТО и
У кажите, что делает каждый ф рагм ент кoдaJavaScript.
o n lo a d
0
a le rt
П оказы вает текст во всплывающем окне.
Заверш ает строчку кoдaJavaScript.
У казы вает на окончание загрузки стра­
ницы.
Включает информ ацию , передаваемую
методу.
дальше >
55
добавим личного участия
КТ9
Вот, что делает каждый из указанных слева ф рагм ентов кода JavaScript.
П оказы вает текст во всплывающем окне.
Заверш ает строчку кода JavaScript.
У казы вает на окончание загрузки стра­
ницы.
Включает информ ацию , передаваемую
методу.
Сделаем объект ^Rock действительно
интерактивным
Вы уже сделали п ервы е шаги в сторону увеличения и нтерак­
тивности объекта 1Коск, но до момента, когда виртуального
домаш него лю бимца можно будет представить пользователям,
ещ е далеко... П ом ните наш список?
Сделано!
©
- з а ™
О
Напишите код, запрашивающий имя
пользователя для личного приветствия
и заставляющий объект улыбаться.
Добавьте обработчик события, запуска­
ющий написанный на шаге 3 код в ответ
на щелчок на объекте.
Заслужите одобрение и благодарность
начальства.
56
глава 1
-- - И эту задачу мы
интерактивная сеть
ВзаимодейстВие доА}кно бы ть двусторонним
в настоящ ий момент камеш ек говорит «Привет», но не позволяет
поучаствовать в диалоге. А хочется, чтобы он отвечал пользователям.
С небольш ой помощью JavaScript 1Коск можно п реврати ть в очарова­
тельного зверька, меняю щ его вы раж ение лица и приветствую щ его по­
сетителя страницы по имени...
После .щелчка объект
должен спрашиват(у
имя пользователя.
What is your name?
Paul
(câncd
имеет
привет ст воват ь
пользователя по
имени.
Теперь iRock
(Rock должен дем он­
ст рироват ь 3M0U,UUj
улыбаясь Полтавателям.
il Is good to meet you, Pau*.
Пользователи
довольны.
JavaScript п озволяет пользователям взаимодействовать с объектом
1Коск, превращ ая наж атия клавиш и щ елчки мыши (дополнительны е
собы тия) в удовольствие от общ ения хозяи н а с домаш ним любимцем.
Так благодаря JavaScript рож дается дружба!
п ^ о з ь м и В руку карандаш
Напишите, как, по вашему мнению, должно называться собы­
тие JavaScript, отвечающее на щелчок мыши.
дальше *
57
решение
^ В о з ь м и в руку карандаш
Решение
Вот как должно называться событие JavaScript, отвечающее на
щелчок мыши.
onclick
Событие onclick возникает , когда
п олт оват ель щ елкает на элемен
т е ст раницы - при эт о м каждому
элем ент у можно сопост авит ь сбои
собственный уникальный код отое
т а на эт о событие.
Как узнать имя пользователя
Вот готовы й к работе метод JavaScrip. И м енно такие куски кода вы
будете находить под данным значком. Со временем вы изучите все
его детали и сможете писать свой собственны й код.
]"о щ о Б ь 1й К од
JaV a^cT ^t
В данном случае перед нами пользовательский метод touchR ock; (),
которы й сначала предлагает пользователю указать свое имя, а затем
вы зы вает отдельное окно с п ерсониф ицированны м приветствием.
О дноврем енно стандартное изображ ение объекта 1Коск зам еняется
улыбающимся.
М ет од p ro m p t() вызывает
Все методы исмаЗспрЬ
всплывающ ее окно, в к о т о и м ею т свои имена. Э т от
рое пользоват елю предлага мет од называется touchRock. ет ся ввест и некую инфор ^
мацию.
С
function touchRockO {
var userName = prompt("Как вас зовут?", "Введите ваше имя.");
—
Теперь, когда мы знаем
if (userName) {
^
можно попривет ст воват ь
alert("Рад вас видеть, " + userName + ". ) f
пользователя...
document.getElementByld("rocklmg") .src = " r o ck_happy.png";
}
' t i __ м зам енит ь обьш ое
изображение камеш ка
улы баю щ им ся.
Ш ТУРМ
в какое место кода страницы irock.html
нужно поместить этот метод?
58
глава 1
интерактивная сеть
Магниты с кодом JavaScript
Код 1Воск лишился некоторых фрагментов. Можете ли вы
его восстановить?
Подсказка: проверит ь п р а ­
вильност ь своих от вет ов
можно м ет одом их ввода
в код ст раницы 1госкМт1.
/
<html>
<head>
<title>iRock - The Virtual Pet Rock</title>
<
type="text/javascript">
function touchRockO {
var userName = promptC'KaK вас зовут?", "Введите ваше имя.");
if (userName) {
alert ("Рад вас видеть, " + userName + ".");
document.getElementByld("rocklmg").src = "rock_happy.png";
}
}
</script>
</head>
<body ....... =" .........( ................................ ) ;">
<div style="margin-top:lOOpx; text-align:center">
<img id="rockImg" src="rock.png" alt="iRock" style="cursor:pointer"
............... = " .............................; " />
</div>
</body>
</html>
touchRock 0
alert
script
onclick
'Hello. I am your pet rock. '
дальше *
59
решение задачи с магнитами
Решение задачи с магнитами
Вот как выглядит целый код.
Методы иауаЗспрЬ р а с ­
полагаю т ся внут ри т ега
<scnpt>, накодяш,егося в з а ­
головке ст раница.
А т р и б у т ty p e т ега <script>
задает язык, на кот ором
будет написан сценарий. В на ш ем случае эт о JavaScript.
J _________________
<html>
<head>
<title^Rock - The V i s u a l Pet Rock</title>
script I type="text/javascript">
■TEmumTjn touchRockO {
var userName = prompt("Как вас зовут?", "Введите ваше имя.");
if (userName) {
alert("Рад вас видеть, " + userName + ".");
document.getElementByld("rocklmg").src = "rock happy.png";
}
}
</script>
</hpsd>
^
А т р и б у т события onload
^
<hody> привязы вает
к ст ранице всплывающ ее окно
^ привет ст вием .
'
З а грузит е изображение
улыбающегося камеилка.
<body onload к=" alert |(
< d i7 * f¥ f!ie * « fc a rg fie re p fl
<img id="ropkIma" src="rock.pna" alt="iRock" style="cursor:pointer"
onclick^"
" />
</body>
</html>
А т р и б у т onclick изображе
ния объект а вызывает м ет од
touchRockO при ще'лчке на
объекте.
60
глава 1
Наведенный на камеш ек
курсор должен приним ат ь
ф орм у руки.
интерактивная сеть
Полученный результат
Н ебольш ой код JavaScript вы звал м нож ество изм енений,
сделав наш объект 1Коск нам ного более интересн ы м . Д авай те
посм отрим , как теп ерь вы глядит наш а страни ц а.
Щ елчок на изображении
iRock вы зы ваем заданный
пользоват елем метод.
id="rockImg" src="rock.png" alt-"iRock"
______ onclick="touchRook();
S t y l e = " cursor-.pointer
/>
mm
function touchRockO {
var userName = promptC'KaK в а с з о в у т ? " ,
"Введите ваше имя.");
if (userName) {
alert("Рад вас видеть, " + userName + ".");
document.getElementById("rockImg").src = "rock happy.png";
}
^т т ^щ т ш т ш т т т ш я т
К ам еш ек
(i
начинает
улыбаться..
М ет од спраш ивает , как
зобут пользоват еля,
а зат ем п р и ве т ст вуе т
его по имени.
What is your name?
It is good to meet you, Paul
Paul
( C a n c ^ ) f~ O K
дальше
►
61
IRock заработал!
Проверка прило)кения iRock 1.0
Убедитесь, в том что ваша версия страницы i r o c k . h t m l со­
впадает с показанной на странице 62 и что вы загрузили с сайта
H ead First Labs {http://www.headfirstlabs.com/books/hfjs/) оба необ­
ходимых вам изображ ения. Теперь открой те вашу веб-страницу,
и пусть камеш ек вертится:
:
Сделано!
О
-€оздайте-для4Явек44ТШ г«=1=раницуг-
©
•■3 a c T a B t ï R ^ -
е
О
(Rock - The Virtual Pet Rode
вО 0
0
é b Æ
ia
4
R < №
lt
4
i f w
e
^
------------
пользователей при зарруэке-етрс№тцы.
~14атт1ш тгетю 0дгзапрж ш т^^
-пользователя для личного приветствия
и заставляющий i
3-
ющий написанный на
в ответ
выполнена.
■ Здесь мы вое 'пользовались
М ет одом
io u c h R o c k ().
реш ения
эт ой задат нам
т ия onclick.
Заслужите одобрение и благодарность
начальства.
62
глава 1
Начальник доволен...
Может быть, он вы ­
делит нам большой
м онит ор?
JavaScript по
зволяет веб­
страницам
действовать,
а не просто
отображать
содержимое.
интерактивная сеть
В к л а д к а
Согните страницу
по вертикали, чтобы
совместить два мозга
и решить задачу.
^
Что добавляет JavaScript?
■-------- \ и xojJoiiio, а ДБа лучше!
^ ----
ЭТО х о л о д н ы й
камешек...
.а это теплый.
Теперь объект
(■Rock м м е е т коечт о общее с ЭИЛМ"
MU н е ви р т у а ль­
ными животными.
Что именно?
Поиск ответов
в Интернете, скорее всего, не
принесет вам особой пользы.
Лучше вместо этого провести время
с пользователями.
■анение Данных
Все на своем месте ^
в реальном мире люди часто не придают значения местам
для хранения своего имущества, в иауаЗспр! такое поведение не­
возможно. Ведь там не существует роскоши в виде огромных шкафов и га­
ражей на три машины. В иауаЗспр1 все имеет свое место, и ваша задача
в этом убедиться. Мы поговорим о данных — как их представить, как хра­
нить их и как их найти после сохранения. Вы научитесь превращать за­
хламленые комнаты с данными в аккуратные помещения с ящиками, каждый
из которых имеет пометку
сценарии сохранения данных
Сохранение данных
П рактически каждый сценарий им еет дело с данны ми в той
или иной ипостаси. О бы чно это подразумевает сохранение
данны х в памяти. З а выбор места для хран ен и я отвечает и н тер ­
п ретатор JavaScript. Вам же нужно объяснить ему, что это за
данные и как вы собираетесь их использовать.
House f m«l«r _
в в в.
О
И н ф о р м а ц и я , связанная
с п о и с к о м д о м о в , долж на
б ы т ь сохранена в сце н а ри и ,
^производящем вычисления.
R eady to find a new h o u se ?
Enter your annual income: jioooo
Enter the num ber o f bedroom s; |3
Enter your Z ip code: p i o i 4
CaicuUte Price 1 Shop te r H ouses..
Н а основе сохраненны х данны х сценарии вы полняю т
вы числения и помнят инф орм ацию о пользователе. Без
возмож ности сохранения данны х вы никогда не наш ли бы
новы й дом и не познакомились бы с объектом 1Коск.
Ш ТУРМ
Подумайте о той информации, с которой при­
ходится иметь дело ежедневно. На что она
похожа? Как различается? Каким образом вы
бы ее систематизировали?
66
глава 2
хранение данных
Типы данных
Д анны е из реального м ира мы категоризируем и систематизируем, даже не
задумываясь над этим: имена, числа, звуки и т. п. JavaScript такж е разделяет
данны е на типы. И м енно это является ключом п ри передаче инф орм ации
из вашего мозга в JavaScript.
JavaScript
Мозг человека
$19.95
^
number
Включить свет.
boolean
Отвези меня на
стадион.
text
В JavaScript три основных типа
данных: text, number и boolean.
Number
Ц и ф р ы используются для хран е­
н и я числовы х данных, наприм ер
массы или количества предметов.
В T a v a S c rip t они могут бы ть как
ц ^ ы м и (2 кг), так и десятичны м и
(2.5 кг).
Текстовы е данны е используют­
ся для хран ен и я набора симво­
лов, наприм ер названия вашего
лю бимого завтрака. М ожно не
ограничиваться словами и пред­
лож ениями. Текст в ;ау а 8 с п р 1
всегда заклю чается в кавы чки ("
')
или в ап остроф ы ('').
Boolean
Л огические данны е
имею т два значения true и false. П оэтому с их
помош;ью представляю т­
ся п роцессы и объекты,
имею щ ие два состояния,
наприм ер; тостер мож ет
быть вклю чен или выклю ­
чен. П одробно об этом
типе данны х мы погово­
ри м в главе 4 .
Тип данны х определяет способ его обработки кодом JavaScript.
Н априм ер, всплываю щ ие окна отображ аю т только текст.
П оэтому числа перед отображ ением следует преобразовать
в текстовы й формат.
дальше >•
67
упражнение
Возьми в руку карандаш
Найдите информацию, которая может быть представлена
данными JavaScript, и укажите, к какому типу она должна
относиться.
З с 1 п с а п 5 D G n lllts
1‘ж л , :
О
68
глава 2
хранение данных
дальше >
69
решение упражнения
Возьми В руку карандаш
\
Решение
Вот к каким типам относились бы данные с картинки
в сценарии JavaScript.
Text
Object (о них
мы поговорим
в главе 9).
/
i
4
О опа
B o o lean
1202
Ы итЬ Ш
-
г»
is-.
.й.
70
’
fi ^ ^
глава 2
хранение данных
дальше ^
71
постоянное и изменяемое
Константы и переменные
С охраняя данны е в JavaScript, нужно помнить не только
про их тип, но и про назначение. Будут ли данны е меняться
в процессе вы полнения сценария? О т ответа на этот вопрос
зависит, константами вы будете пользоваться или ж е п ере­
менными.
Константа
Площадь ст раны с о ­
ст авляет ъ .5 миллиона
квадрат ных м и л ь — это
конст ант а, если, конечно,
не сдвинут ся т ект о ни ч е­
ские плит ы .
В сут ках 2-4 часа.
Это конст ант а,
известная всем
людям.
и я и веб-ст раницы
w w w .duncansdonuts.com
эт о конст ант а, по кр а й ­
ней м ере до т ех тор, пока
бизнес не пр и дет в упадок.
Ш ТУРМ
Какие еще типы информации работают как с переменными, так
и с константами?
72
глава 2
Переменные ме­
няют свое значе­
ние, в то время
как константы
фиксированы.
Переменная
Население в 3 0 0
м иллионов человек —
' перем енная, т ак как
население СШ А во з­
раст ает .
Восход солнца в 6 :4 3 —
э т о переменная, т ак
как врем я восхода солн­
ца м еняет ся каждый
день.
32-4 посещения — п е ­
рем енная, т ак как
пользоват ели п р о ­
должают заходит ь на
ст раницу и м енят ь
показания счетчика.
хранение данных
Возьми в руку карандаш
Обведите все данные, связанные с кондитерской Дункана,
и укажите, к переменным или к константам они относятся.
Э а п с а п з D o n (J ts
'ж л .
1202
дальше у
73
решение упражнения
11^ з ь м и
В
руку карандаш
Решение
Вам нужно было определить, какие данные относятся к пере­
менным, а какие к константам.
-КонстантаПеремен ная
опсапз
Константа
Переменная
^Переменная
74
глава 2
хранение данных
Беседа у камина
Переменные и константы обсуждают аспекты хранения
данных.
Переменная:
я предлагаю наиболее гибкий способ со­
хран ен и я данных. Вы мож ете менять мое
значение по своему ж еланию —именно это
я назы ваю свободой.
Разумеется, но твое упорное неж елание ме­
няться ставит в тупик в ситуациях с изм еня­
ющ имися данными. Н априм ер, при запуске
ракеты нужно произвести отсчет от 10 до 1.
И что ты будешь делать?
Смешно см отреть, как ты радуешься, гово­
ря, что изм енения это плохо. Ты просто не
понимаеш ь, что н а самом деле это хорош о,
особенно когда нужно сохранить инф орм а­
цию, введенную пользователем, вы полнить
вы числения и п рочее в этом роде.
Константа:
А я называю это нереш ительностью ! Я гово­
рю, что значения нужно вы бирать раз и на­
всегда. И именно моя последовательность
делает меня столь ценной... П рограм мисты
ценят мою предсказуемость.
И вот поэтому ты считаеш ь себя един­
ственным вариантом хран ен и я данны х для
важ ны х прилож ений? Угадай, почему ракета
оказалась на стартовой площадке. Лиш ь
потому, что парам етры запуска являю тся
константами. Ты когда-нибудь видела п ере­
менны й срок окончания проекта?
Ч ем больше вещ и меняю тся, тем более неиз­
менны ми они остаются. Почему изм енения
нужно ставить на первое место? П рисвой
изначально нужное значение и не трогай его
больше. Это ж е так удобно, когда парам етр
не мож ет бы ть случайно изменен.
я думаю, тут можно только соглашаться.
И ли не соглашаться.
И м енно так. И я с тобой полностью несо­
гласна.
дальше р
75
создание переменной
исходное состояние переменных
П ерем енной назы вается место хранения и нф орм ац ии в памяти,
имею щ ее уникальное имя. Это как метка на коробке для хранения
вещей. Д ля создания п ерем енной прим еняется клю чевое слово v a r ,
после которого следует ее имя. Ключевыми назы ваю тся слова, заре­
зервированны е в JavaScript для вы полнения различны х операций.
К лю чевое слово var
указы вает на создание
новой переменной.
Имя
Б конце каждой ст роки
кода Ja va S crip t ст авит ся
точка с запят ой.
переменной
Д ля переменной можно вы ­
драт ь любое им я, главное,
чтобы оно было уникальны м
для вашего сценария.
С озданная при помощ и клю чевого слова v a r перем енная из­
начально пуста —она не им еет никакого значения. П оэтому не
им еет смысла пользоваться перем енной до операции п ри ­
своения. Вы.же не вклю чаете М РЗ-проигрыватель, не вставив
в него диск.
Д а , эт о новая
<леременная.
^о н е ц
v a r p a g e H its ;
^•^роки.
Ящмк п у с т — сюда
можно полож ить
информацию.
Ее им я радеИНв — к о ­
личест во посеш,ений
страницы.
Вновь созданная перем енная резервирует пространство для
хран ен и я и нф орм ации и готова к присвоению ей значений.
В ы бранное для нее имя играет немаловажную роль. О но долж­
но быть уникальным и значимым. К примеру, имя p a g e H i ts
сразу дает понять, что за и нф орм ац ия содерж ится внутри. Если
бы перем енной для подсчета количества посещ ений страни­
цы было присвоено имя X или д егк ± п , вы бы уже не смогли с
п ервого взгляда определить, для чего она предназначена.
76
глава 2
■ч
хранение данных
Присвоение значений
Н е следует создавать переменную , не имеющую значения. Бо­
лее того, имеет смысл присваивать зн ачение перем енной уже
в момент создания. Эта процедура назы вается инициализаци­
ей. Д ля ее вы полнения достаточно добавить небольш ой кусо­
чек кода в уже знакомую вам строчку:
Имя
Заверш ает
с т р о ч к у кода.
ш
Значение
перем енной
З н а к р а в е н с т в а соединяет
и м я п е р е м е н н о й с ее н а ч а л ь ­
н ы м значением .
И м енно эт о
значение б у ­
де т х р а н и т ь с я
в пе р е м е н н о й .
В отли чи е от своего пустого дубликата, и ни циализирован­
ная п ерем енная немедленно готова к использованию ... П о­
скольку она уже им еет значение. Вы как будто купили МРЗпроигры ватель со вставленным внутрь диском —и сразу
мож ете слушать музыку.
П р и сво й т е
значение
»переменной.
Конец.
Теперь переменная
с о д е р ж и т численны е
данные.
va r
p o p u la t io n
=
300; ^
/К
С оздайт е п е р е м е н н у ю .
П р и сво й т е
ей и м я.
У каж ит е
ее значение.
П ом ните о типах данных? П оказанная выше строчка кода
автом атически н азначает перем енной ти п данных. В данном
случае JavaScript создает переменную p o p u l a t i o n число­
вого типа, потому что вы присваиваете ей значение 300.
П осле присвоени я другого зн ачен ия ти п перем енной может
измениться. В больш инстве cлyчaeвJavaScript делает это
автоматически, хотя бываю т случаи, когда переход от одно­
го ти п а к другому следует вы полнять вручную. Н о о них мы
поговорим позже.
дальше *
77
упрямые константы
Не все браузеры
поддерживают
Ьдыпе
I ключевое слово
0СШ0|=0ЖНьі!
const.
Константы
в процессе инициализации перем енной присваивается
начальное значение, но ничто не меш ает его п о з ж е поме­
нять. А вот для хран ен и я данных, которы е никогда не будут
меняться, вам потребуется константа. К онстанты создаются
аналогично инициализированны м перем енны м, но вместо
клю чевого слова v a r используется клю чевое слово c o n s t .
И «начальное» зн ачение становится постоянным!
Э т о клю чевое слово
Присвоение
создает конст ант у.
значения к о н ­
ст ант е.
Ключевое слово c o n s t —
новинка для JavaScript, и не
все браузеры его понимают.
Поэтому тщательно про­
веряйте те браузеры, для
которых пишется код, содер­
жащий константы.
/
const 1 4- \
і
Имя константы
Значение
Значение к о н с т а н т ы
никогда не и зм е н и т ся .
Имя константы.
П роцесс создания константы отличается только используемым
клю чевым словом. О стальной синтаксис остается таким же, как
при инициализации перем енной. Ч тобы выделить константы ,
им часто присваиваю т имена, написанны е больш ими буквами.
Э т о значение
Эти данные не и з м е ­
н я т с я никогда!
const
конст ант а будет
и м е т ь вечно.
TAXRATE
=
.9 2 5 ;
/
Т О Л Ь К О П Р О П И С Н Ы Е буквы
о и м е н и к о н с т а н т ы о б ле гча ю т ее
от личие от переменных, в именах
к о т о р ы х возможны буквы р а зн ы х
регист ров.
К онстанты позволяю т хранить информ ацию , кодируемую прямо
в сценарии, скажем, ставку налога с продаж. Вместо числа 0 .9 2 5
им еет смысл вставить в код константу со значим ы м именем, на­
п рим ер ТАХКАТЕ. П ри таком подходе, если впоследствии вам
потребуется пом енять зн ачение константы , достаточно будет
сделать это один раз —в месте ее инициализации. Это намного
прош,е, чем искать и зам енять числа по всему сценарию .
78
глава 2
О перация
закончена.
хранение данных
А я думала, что константы не
могут менять своих значений.
Константы не могут менять своих значений
без текстового редактора.
К онстанты не меняю т значений в процессе
вы полнения сценария, но ничто не мешает
пом енять их в том месте, где им присваивалось
значение. Так что константа неизм енна с точки
зрен и я сценария, в то время как вы мож ете ее
поменять, вернувш ись в точку ее создания. Так,
ваша константа для налоговой ставки не может
меняться в процессе работы сценария, но ничто
не меш ает поменять ее значение в коде инициа­
лизации.
ненке
Как вы думаете, переменной или константой должно быть каждое из указанных ниже
значений? При желании вы можете написать код для создания и инициализации каждо­
го из них.
Температура воздуха в данный момент. Начальное значение неизвестно.
Коэффициент преобразования возраста собаки в возраст человека (1 год че­
ловека = 7 годам собаки).
Обратный отсчет перед запуском ракеты (от 10 до 0).
Цена вкусного пирожка (50 центов).
дальше >
79
решение упражнения
^
ш нпг
Вам требовалось решить, чем будет каждое из указанных ниже значений: перемен­
ной или константой, а затем написать код для их создания и инициализировать их
при необходимости.
решение
Температура воздуха в данный момент. Начальное значение неизвестно.
Коэффициент преобразования возраста собаки в возраст человека
(1 год человека = 7 годам собаки).
Обратный отсчет перед запуском ракеты (от 10 до 0).
Цена вкусного пирожка (50 центов).
var tem p;
Т ем перат ура все врем я меняет ся,
а ее исходное значение неизвест но,
поэт ом у для нее мы резервируем
п ус т ую переменную .
const HUMANTODOQ = 7;
1
•
К оэффс^циент преобразования
м еняет ся, поэт ом у для него
превосходно подойдет ко н ст ант а.
var countdow n - Ю ;
Обратный от счет
меняет ся от ХО до X,
' поэт ом у нам нужна
переменная с начальным
значением i-O.
var donutPrice = О.SO; или const PONUTPRICE = О.SO;
цену на пирожки
нужно предст авит ь п е р е ­
менной с указанны м в задаче
начальным значением
80
глава 2
Если же цена фиксированная,
.лучш е всего выбрать для ее
предст авления конст ант у.
хранение данных
чааэдо
ЧадаБаеМые
B o iij= » o c :b i
ляет тип данных, если я их не
ИЛожно ли оставить переменную
неинициализированной,если я заранее
имеет смысл создать для них константы.
Это облегчит вам работу в будущем, если
указываю?
не знаю ее значения?
вдруг потребуется поменять значение
этих параметров.
Q ; в отличие от других языков про­
граммирования, JavaScript не позволяет
в явном виде задавать тип констант
; Конечно. Инициализация призвана
предотвратить проблемы, которые могут
возникнуть при попытке доступа к пере­
менной, не имеющей значения. Но бы­
вают и случаи, когда в момент создания
переменной ее значение еще неизвестно.
Каким образом JavaScript опреде­
и переменных. Тип выражается неявно
в момент присвоения значения. Это дает
переменным JavaScript ббльшую гибкость.
К примеру, присвоив число 17 пере­
менной X , вы приведете ее к числовому
типу. Но если затем присвоить ей же текст
“seventeen”, тип изменится на строковый.
Если JavaScript автоматически
заботится о типах данных, зачем мне
вообще о них задумываться?
I Во многих ситуациях нельзя целиком
положиться на автоматическую обработку
данных средствами JavaScript. К примеру,
у вас есть число, сохраненное в виде
текста, которое нужно использовать в вы­
числениях. Для этого его предварительно
нужно преобразовать из строкового типа
в числовой. Обратная ситуация возникает
при необходимости отобразить число
во всплывающем окне. JavaScript умеет
автоматически преобразовывать числа
в текст и обратно, но не всегда делает это
так, как вам нужно.
Тогда следить за тем, чтобы обращение
не происходило к пустым переменным,
уже вам. Кстати, переменным можно
присваивать и «пустые» значения, на­
Что происходит с данными сцена­
рия при перезагрузке страницы?
! Все данные принимают свои началь­
ные значения, как будто сценарий перед
этим и не запускался. Другими словами,
после перезагрузки страницы сценарий
запускается сначала.
пример" " для текста, О для числа, или
false логического типа. Это уменьшает
риск обращения к неинициализированным
данным.
Как определить, когда мне нужна
переменная, а когда константа?
0 ; Часто пользователи начинают
работать исключительно с переменными,
а позже обнаруживают, что некоторые
из них можно превратить в константы.
Скорее всего, это будут повторяющиеся
строки текста или число, которое встреча­
ется в нескольких местах кода, к примеру,
повторяющееся приветствие или коэффи­
циент преобразования. Вместо того чтобы
писать этот текст или число снова и снова.
Тип данных
определяется
после того, как
переменной
или константе
было присвоено
значение.
КЛЮЧЕВЫЕ
МОМЕНТЫ
Данные в сценариях обычно принадлежат к одному
из трех типов: text, number или boolean.
Ключевое слова v a r создает переменные, в то
время как c o n s t создает константы.
Переменной называется кусок данных, который
меняется в процессе работы сценария.
Тип данных JavaScript определяется в момент при­
своения значения. У переменных тип данных может
Константа — это неизменяемый кусок информации.
меняться.
дальше
►
81
меня зовут
Ч то В имени тебе моем?
П ерем енны е, константы и другие синтаксические конструкции JavaScript
определяю тся по своим уникальным именам или, как их ещ е называют,
идентиф икаторам . И н ден тиф и каторы JavaScript напоминаю т им ена лю­
дей из реального мира, хотя и с некоторы м и ограничениям и (люди могут
носить одинаковы е имена, а вот перем енны е JavaScript —нет). К роме того,
им еет смысл придерж иваться следующих правил именования;
Идентификатор должен быть длиной хотя бы в один
символ.
Первым символом идентификатора должна быть
буква, знак подчеркивания ( J или знак доллара ($).
В символах после первого допускаются буквы, циф­
ры, знаки (_) и {$).
Пробелы и специальные символы, отличные от
и $, в идентификаторах недопустимы.
Когда вы создаете и дентиф икатор JavaScript для перем енной или
константы , давайте им «говорящие» имена. То есть вам недостаточно
просто вы полнить п еречисленны е выше требования. И мена должны
быть такими, чтобы по их виду было понятно, для чего предназначена
та или иная перем енная или константа.
Разумеется, бываю т и случаи, когда можно обойтись просты м х —дале­
ко не каждый ф рагм ент и нф орм ации в сценарии можно легко описать.
Ш ериф Правосудов,
за с л у ж е н н ы й юрист .
Идентификаторам следует
присваивать значимые имена.
82
глава 2
Я не потерплю на­
рушений закона, когда
речь идет об иденти­
фикаторах.
О
хранение данных
Корректные u некорректные имена
f ir s t N a m e
t o p i ОО
Н е ко р р е к т н о :
и м я не м о ж е т
начинат ься
с циф ры .
Коррект но: им я
с о с т о и т т о л ь ко
из букв.
ка chow
Коррект но:
буквы с н и ж н и м
п о д ч е р ки в а н и е м
сост авляю т
допуст им ую
комбинацию .
topSecret
J
Коррект но: циф ­
р ы р а с п о л о ж е н ы на
п о зи ц и я х , о т л и ч н ы х
о т первой.
Некорректно: и м я не
м о ж е т начинаться
со сп е ц и а л ьн о го с и м ­
вола, от личного от
« » или «$»■
$total
?g u i l t y
К о р р е кт н о : начинат ь им я
с н иж него по дче р ки ва н и я м о ж но — н е ко т о р ы е п о льзо ва т е ли
даж е спец иал ьно п р и м е н я ю т
т а к о е и м е но ва ни е , чт обы п о д ­
ч е р к н у т ь особое значение п е р е ­
м енной.
1^
К о рр е к т н о : х о т я т а к и е
имена и вы глядят н е ­
с ко л ько с т р а н н о , но зн а к
доллара на первой п о з и ­
ции вполне д о п у с т и м .
Вот примеры бейсболок для агентов, рекламирующих кондитерскую Дункана. К сожа­
лению, при их разработке не учитывались стандарты именования идентификаторов
в иауа8сг1р1. Зачеркните неподходящие с точки зрения иауаЗсг1р1 варианты.
donut '
fflazel
дальше *
83
решение упражнения
,Н 2Н И б
ешение
Вам нужно было вычеркнуть бейсболки с именами, некорректными с точки зрения
иауаЗсг1р1.
?1агег
в именах идент иф икат оров
недопуст имо использоват ь
восклицат ельный знак.
И пробелы в них
также запрещены..
Символ # вызовет
ярост ь и шерифа
Правосудова.
СтильВерблюда
Законов, обязующих использовать определенны е стандарты именования
в JavaScript, не существует, но есть неофициальные правила, которы х
придерж ивается больш инство. Одно из таких правил —использовать
СтильВерблюда в составны х именах и дентиф икаторов. Такое название
появилось из-за того, что заглавны е буквы внутри слова напоминаю т
горбы верблюда. В именах перем енны х первое слово обы чно пиш ется
буквами ниж него регистра, а все п рочие —смешанным регистром .
n ш l_ c a ]c e _ d o n u ts
Первая буква
каждого слова
прописная.
Знак подчеркивания между
от дельны ми словами вполне
д опуст им , но сущ ест вует
лучш ий способ.
НижнийСтильВерблюда
используется для именования
многословных переменных.
84
глава 2
N ш n C a k e D o n u ts
Именно т ак выглядит
ст и ль верблюда, но и он
не совсем подходит для
переменных.
Вот т акой ст иль п р е ­
восходно подходит для
именования переменных.
Прописной
является
первая буква
каждого слова,
кроме саМ_ого
хранение данных
Магниты JavaScript
От магнитов с описаниями отвалились имена переменных и кон­
стант. Поместите на каждый магнит нужное имя, особо проследив за
их корректностью. В качестве дополнительного задания в каждом
случае укажите тип данных.
данных с Ш д -
Количество муки
(Поиг) для п р и - ^
гоилоол€-ныя одной
порции (hatch)
пирожков.
ця Чйш ек
,
( n u m b e r of cups).
І^мя ра5отни ~
ка месяца (the
е-тріодее o f the
т опЩ .
(^e,cord holder\
Cocm om ae (status)
аварийной сигна
лизаи,ии (йійгил).
мЛ
Н йлого^й номер
number) для
Фиксации налога
^ продаж.
(eclaits).
emDlovee*of*the*Month
дальше >
85
решение задачи с магнитами
Решение задачи с магнитами
Вам нужно было поместить на каждый магнит имя
подходящей переменной или константы. В качестве
дополнительного задания предлагалось указать тип
данных.
К-Оличейилбс)
дат ьт с и о д ня ч й ш е к к о ф е
( n w w b e f or CMpS)-
Количество муки
(flour) Зля п р и - ^
готовлеиий одной
порции (batch)
пирожков.
^ м я работ ни­
ка месяца (рке
пшпСирз
enployeeOfMonth
Text
Number
(ИХ number) для
с
налога
Состояние (status)
аварийной сигнаАизации (alarm).
alarmstatus
V
Boolean
T ext
cups-o-cjoffee
Eir^loyee of the Month
alarm s
Оставш иеся ,—
имена являю т ся
некоррект ны ми
с точки зрения
JavaScript■
86
глава 2
f
Tax#
f ~
flour quantity
|
e c la ir W in n e r I
Tfc
хранение данных
Следующий этап
Вы уже читали о заведении Дункана, но пока ничего не
знаете о планах его хозяина. Дункан хочет перевести свой
бизнес на новы й уровень... П родавать пончики ч ерез И н ­
тернет! Только представьте, пользователь вводит в форму
количество товара и время доставки и точно в указанное
время получает горячи е пончики. Вам нужно убедиться, что
пользователь ввел все требуемые данны е, и вы числить на­
лог и итоговую сумму заказа.
Ouncan's Just-irvTime Donuts
Mdonuts^c
^
Minutes « pidiup.
То«р6^
Привет, я Дункан. Система
заказа моих пончиков через
Интернет — это нечто!
хО
На основе введенмых пользоват елем
данных иауйЗсп'рг
вычисляет налог
и ит оговую с т о и ­
м о ст ь заказа.
О
D onut Blaster 3 0 0 0 .
Горячие
и вовремя!
«oPFtr
V>x>№ifTB
дальше >
87
форум для заказа пончиков
Планируем Веб-страницу
О бработка заказов вклю чает в себя как проверку введенны х в ф о р ­
му данных, так и вы числение на их основе суммы заказа. Промежу­
точная и полная суммы долж ны отображ аться сразу же после ввода
инф орм ации пользователем. К нопка Сделать заказ просто отправ­
ляет сведения. Ее работа не им еет отнош ения к JavaScript, поэтому
здесь она рассматриваться не будет.
.О л
Э т а инф ормация т ребует ся
для выполнения заказа и п о э­
т о м у ее следует проверит ь
средст вами JavaScript.
D u n c a n ^ J u s t-ln ^ tn e O o n m s
в о о
D u n c a n 's J u 8 t - J n - T i m e D o n u t e
All donuts 50 cents each, cake or ^azed.
" N a m e T jp a u l^
#
of cake do n u ts: ^
# o f g la zed do n uts; pL2
j^ u te s
& jb to lS iir |$ 6 .0 0
Tax: j$0 .5 S
Total: fse .is
Done
Э т у инф ормацию
JavaScript вычисляет,
чт о называется, на
88
глава 2
Д ля ф инальной о т ­
правки введенных
в ф орм у данных на
сервер JavaScript не
т ребует ся.
хранение данных
Промежуточная сумма вычисляется умножением требуемого
количества пончиков на стоимость одного пончика:
( кол-во пончиков + кол-о глазированных ) х цена пончика
Налог вычисляется умножением промежуточной суммы на ставку:
сумма X налоговая ставка
Общая стоимость заказа вычисляется сложением промежуточной
суммы и налога:
сумма + налог
Кажется, у Дункана достаточно данных, чтобы отслеж ивать их
при помощ и ф ормы . Ему нужно быть не только в курсе введен­
ной пользователем инф орм ации, но и вы числить при помощ и
кодаЗауа8сг1р1 ряд параметров.
При помощи
JavaScгipt каждый заказ
будет доставлен во­
время!
О
Ш ТУРМ
Какие переменные и константы пона­
добятся для этих вычислений? Какие
имена вы бы им присвоили?
дальше ¥
89
не считается
Начнем с Вычислений
Дункан попы тался самостоятельно написать код JavaScript, вы полняю щ ий
подсчеты, но столкнулся с проблемой. П осле ввода пользователем количе­
ства требуемых пончиков в полях с результатами вы числений стало появ­
ляться не имею щее никакого смысла зн ачение $NaN. Б олее того, заказ не
заполнялся. И клиенты были соверш енно не в восторге от технологическо­
го «усоверш енствования» Дункана.
о
10ОО
Duncan's
D u n c a n 's
Just-In-Time Donuts
AHdonuts 50 cents each, cake or ^ z e d l
Name: jPauT
$ЫаЫ — эт о код
для чего-т о п л о ­
хого?
# of caKe donuts: jO
# of glazed donuts:
Minutes'til pickup: j45
Subtotal; p N a iT ^
Ой, как н е ­
хорошо!
П риш ло время взглянуть на код нашего сценария
и понять, что же происходит. П ерейдите на следуюшую страницу (или загрузите п рим ер кода с сайта
http://www.headfirstlabs.com/books/hfjs/) и попы тай­
тесь п опять, где именно скры вается источник
проблем.
W
/
Нет пончиков = ест ь проблема.
90
глава 2
хранение данных
Э т о т код о бно в л яет за к а з, м гновенн о \
вычисляя п р о м е ж у ­
т очную и полную
сум мы .
Т а к к а к введенные
по л ь зо ва т е л е м дан
ные в п о р яд ке , для
п о и ска п р о б л е м ы о б ­
р а т и м в н и м а н и е на
конст ант ы .
Э т о т код о т ­
п р а в л я е т зака з
на сервер и п о д ­
т в е р ж д а е т его
принят ие.
<html>
<head>
<title>noH4MKM Дункана к указанному BpeMeHM</title>
<link rel="stylesheet" type="text/css" href="donuts.css" />
<script type="text/javascript">
function updateOrder() (
const TAXRATE;
const DONUTPRICE;
var
var
var
var
var
numCakeDonuts = document.getElementByld("cakedonuts").value■
numGlazedDonuts = document.getElementByld("glazeddonuts").value;
subTotal - {numCakeDonuts + numGlazedDonuts) * DONUTPRICEtax = subTotal * TAXRATE;
total = subTotal + tax;
document.getElementByld("subtotal") .value =
.
sum'otai t<
+ subTotal.toFixed(2)
document.getElementByld("tax").value =
+ tax.toFixed(2)■
^ document.getElementByld("total").value =
+ total.toFixed(2);
function placeOrderO {
// Передать заказ на сервер...
form, submit () ;
)
</script>
</head>
<body>
<div id="frame">
<form name="orderfo^' action="donuts .php" method="POST">
З а ка з обновляет ся
п р и и зм енени и к о ­
л и че ст в а пончиков.
З а ка з п р и н и м а ­
ет ся после ш,елчка
на к н о п к е С делат ь
заказ.
<div class="field"> ^
Число пончиков: <inpu4,type="text" id="cakedonuts" name="cakedonuts"
value=’" onchange="updateOrder0 ;" />
</div>
<div class="field">
Глазированных: <input type="text" id="glazeddonuts"
name="glazeddonuts" value=" onchange="updateOrder();" />
<div class="field">
<input type="button" value="Cдeлaть за к а з"
onclick="placeOrder(this.form);" />
</div>
<7form5
-— ----- -----------------
</div>
</body>
</html>
Возьми в руку карандаш
Запишите, что, по вашему мнению, не так с кодом данного
сценария.
дальше *
91
решение упражнения
Возьми в руку карондаш
Решение
Итак, вот в чем была проблема с кодом сценария для заказа
пончиков через Интернет.
М . и н и ц и а л и з и р о в а н ы ,
и вычисления, в которые они входят, ст али невозможны.
Я знаю, что константы сохраняют свое
значение, но не понимаю, зачем их ини­
циализировать?
Никогда не оставляйте константы без значения.
Если не и ни циализировать константу в момент ее
создания, он а не будет иметь значения —и, что хуже
всего, ей будет невозмож но его присвоить. Такие
константы являю тся ош ибками кода, хотя браузеры
об этом не сообщают.
Всегда инициализируйте
созданные константы.
92
глава 2
хранение данных
инициализируйте данные... или...
Н еин и ци али зи рованы е данны е считаю тся неопределенны ми.
Другими словами, они не имею т никакого значения. Это не
значит, что они соверш енно бесполезны . О ни просто не со­
держ ат инф орм ации... пока. П роблемы начинаю тся, когда вы
собираетесь использовать подобны е перем енны е или констан­
ты , наприм ер, для вычислений.
const
DONUTPRICE;7
“
“
в JavaScript операт ор
умнож ения
a не X.
"
^Инициализировано
v a r n u m C ak eD o n u ts = 0;
v a r nu m G laze d D o n u ts = 12;
3-Я
( n u m C a k ^ C f o n u t s + n u m G l a ^ d D o n u t s ) * D0NIJ7?RICE;
О
var
subT otal =
subtotal = (0 + 12)
0
Это большая
проблема.
К онстанта D O N U T P R IC E неинициализирована. В JavaScript
такие данны е обозначаю т специальны м состоянием;
u n d e f in e d . Это все равно что оставить на автоответчике
сообщ ение «сообщений нет», если вам нечего сказать —вы
оставляете сообщ ение, обозначаю щ ее его отсутствие. Так
же и с состоянием u n d e f i n e d —оно обозначает отсутствие
данных.
Данные
не определены,
если им не
было присвоено
значение.
Т ут нет
данных.
D O N U TP R IC E
дальше *
93
NaN — не то, что вы подумали
NaN — это НЕ число
П одобно значению u n d e f i n e d , которое представляет особое состояние данных, существу­
ет ещ е одно значение пepeм eнны xJavaScrip: NaN. Эта аббревиатура расш иф ровы вается как
N ot а N u m b er —не число. И м енно такое значение п рисваивается перем енной s u b T o t a l
из-за того, что нам не хватает инф орм ац ии для расчетов. Другими словами, вы восприни­
мали отстутствующее зн ачение как число... а получили NaN.
Число
Не ч и с л о !
"Л
subtotal = (О + 12) * ? = NaN
Так как эт и данные неопределены ,
произвест и вычисление невозможно.
Так, для реш ения возникш ей проблем ы инициализируйте
константу DONUTPRICE в момент ее создания:
NaN — это значение,
не являющееся числом.
const DONUTPRICE = 0.50;
_
Часто
;^ а Д а Б а е М ы е
B o iIp o C b i
Что означает «идентификаторы
должны быть уникальны в пределах
сценария»?
0 1 Идентификатор выступает как
уникальное имя для фрагмента
информации в сценарии. В реальном
мире люди часто имеют одинаковые
имена... но при этом они вполне
в состоянии разобраться «кто есть кто».
иауаЗспр! не умеет решать подобные
неопределенности, поэтому различные
фрагменты информации различают,
присваивая им разны е имена. И вы
должны следить за уникальностью всех
идентификаторов в ваших сценариях.
Идентификаторы должны быть
уникальными вообще или только
в пределах сценария?
94
глава 2
I
Уникальность идентификатора важна присвоим имя Donut, методу — имя
именно в пределах сценария, а иногда
g e t D o n u t ( ) , а переменной — имя
и в пределах части сценария. Но следует
numDonuts. Для констант подобный
помнить, что для больших приложений
подход не применяется. Имена констант
иногда требуются очень большие
пишутся полностью заглавными буквами.
сценарии,распределенные по файлам.
В этом случае имеет смысл делать
Существует ли значение NaN для
идентификаторы полностью уникальными.
текстовых и логических данных?
Но для этого достаточно давать им
значимые имена в контексте выполняемой
; Теоретически да, так как параметры
задачи.
этих типов не являются числами.
В реальности же это не так. Значение
Я так и не понял, зачем нужен
NaN указывает, что число — это не то,
стиль верблюда?
что вы думаете. Другими словами, NaN —
это не описание данных JavaScript,
Q ; Стиль верблюда с заглавной
а индикатор ошибки для численных
буквой первого слова используется
типов. Это значение обычно появляется
для именования объектов JavaScript,
в результате вычислений, в которые
о которых мы поговорим в главе 9. Для
в качестве параметра по какой-то причине
переменных и методов используется
попали нечисловые данные.
стиль верблюда, в котором первое
слово пишется с прописной буквы.
Соответственно, объекту мы
хранение данных
А те м временем у Дункана...
у Дункана дела идут все хуже и хуже. Вместо пустых
коробок теп ерь везде пончики —в каждый заказ добав­
ляю тся лиш ние. Дункан утонул в жалобах на избы ток
пончиков и другой выпечки...
......
Duncan's Just-In-Time Donuts
Altdonuis 50 cents each, cake or glazed!
Name: jcrS
I ■
I
‘GO 'FFEfE
J
Bom чт о было получено
вм ест о й заказанных
пончиков.
-....
„
t €50F*;iaE ^
-0'0im£9e ^
*>©;MSUT5
SSSSSSSSSS?
iiSwmwS^^
Ш ТУРМ
Что может быть не так с обработкой данных о количестве пончиков?
дальше >
95
различные типы сложения
СкладыВать мо)кно не только числа
в JavaScript многое значит контекст. О собенно важен тип данных,
с которы м и осущ ествляется манипуляция в каждом конкретном
куске кода. Ведь даже такая простая операция, как слож ение, дает
разны е результаты для данны х разны х типов.
1 + 2 = 3
"с1о" + "nuts" = "donuts"
I
У
Сло)кение чисел
^р а си во е название
-ОЛЯ «склеивания
слов друг с другом>.
^
Соединение строк
Это прекрасно вам знако­
мая из начальной школы
ариф м етическая операция.
П р и этой операции на­
чало второго слова
«приклеивается»к концу
первого.
И так, вооруживш ись знанием о том, что строки складываются
не так, как числа, ответьте, что произойдет при слож ении двух
чисел в текстовом формате?
?
Сложение, соединение,
чт о именно?
Язык5ауа8сг1р1 не разби рает смысл текста —с его точки
зрен и я, это всего лиш ь набор символов. П оэтому тот факт,
что строка содерж ит численны е символы, не им еет никако­
го значения, будет вы полнено соединение строк. Если вы
предполагали математическую операцию слож ения, дан­
ны й результат окаж ется неожиданным.
Так как эт о ст роки, а не
числа, они « склады ваю т ­
ся» п у т е м соединения
ст рок.
96
глава 2
Вы получит е ст року,
кот орая никак не напо­
м инает резуль>тат м а ­
т ем ат ической операции.
Б йА ьте
о с т о |э о ж н ь 1 !
Всегда следите,
что именно вы
складываете.
Соединение
строк вместо сложения
чисел — не самая редкая
ошибка в JavaScript. Если
требуется сложить два чис­
ла, убедитесь, что они нахо­
дятся в нужном формате.
хранение данных
Методы раг$е1п1(] и раг$еР1оа1()
П ериодически возникаю т ситуации, когда требуется сложить
числа, сохраненны е в текстовом форм ате. В этом случае вам сле­
дует сначала преобразовать строку в число. Для подобных преоб­
разований вJavaScript предусмотрены два метода:
p a r s e F lo a t
П ереданная данному методу
строка преобразуется в целое
А этот метод преобразует строку
в число с десятичной (плавающей)
точкой.
число.
О ба метода берут в качестве п арам етра строку
и преобразую т ее в число:
рдг5е1пед п р е о б р а зу е т " 1 " в г .
Я
рагз^1п1:("1") + p a r ^ n t ( " 2 " ) = 3
/ "
\
Следует помнить, что методы p a r s e I n t () и p a r s e F l o a t ()
могут и не сработать. Все зависит от парам етров, которы е
вы им передадите. О ни превосходно преобразую т строки
в ц и ф ры , но важно дать им в качестве п арам етра строку, со­
держащую только численны е символы.
p a r s e F lo a t( " $ 3 1 .5 0 " )
= ЫаК
/
Э т о т код не б уд е т
работ ат о, т а к как
т т о д не п о н и м а е т
си м во л а
На э т о т р а з м ы п о . лучи м резул ьт ат
м ат ем ат ического
слож ения.
Если вы до
сих пор не
поняли
принцип работы методов, не
волнуйтесь.
Эта тем а будет подробно разби­
раться чуть позж е — пока доста­
точно знать, что методу можно
передать данны е и он возвратит
вам некий результат.
С ю рприз! В результ ат е
п о л у ч и т е все т о т ж е
дальше >
97
когда вещи не складываются
Откуда берутся лишние пончики?
В згляните внимательно на форму заказа пончиков. П опы таемся
понять, почему возрастает количество заказанного...
#00
CD
Duncar»*s Just-ln-Time Donuts
Duncan's Just-ln-Tlfn© Donuts
All donuts 50 cents each, cake or glazed!
Name: Greg
# of cake donuts: 6
# of glazed donuts:
Minutes 'til piclcup: W
JS 3 1 .5 0 ^
О п л а т а берет ся за
ко л и ч е ст во
пончиков, ч е м было
злказано... но
ах: Ш ж
Total: $34.41
н а с к о л ^ о их больше?
Иасе Order
Done
Разделив промежуточную сумму на стоимость одно­
го пончика, мы узнаем, сколько же пончиков было
заказано.
пром еж ут очная
с у м м а заказа.
$31.50 / $0.50 = 63 пончик
Ц енй одного п о н ч и ка .
К аж ется, мы столкнулись с проблем ой объединения строк.
Ведь данны е, введенны е в форму, всегда сохраняю тся в стро­
ковом ф ормате. Даже введенны е вами ц иф ры с точки зрения
JavaScript являю тся текстом. П оэтому мы избавимся от ош иб­
ки, просто преобразовав строки в числовой ф ормат.
98
глава 2
^ о т с ко л ь ко п о н ч и ко в
было за ка за н о на с а м о м
оеле... ст ранно...
Вы п о м н и т е , ч т о "3 -" + "Я
К а ж е т с я ,, здесь м ы с т о л к н у л и с ь
с а н а л о ги ч н ы м случа е м .
хранение данных
Возьми в руку карандаш
Показанные ниже строчки кода забирают введенную в поля инфор­
мацию о количестве заказанных пончиков. Воспользуйтесь ими для
заполнения недостающих строк метода u p d a t e O r d e r () таким
образом, чтобы информация о размере заказа была преобразована
в числовой формат.
docum ent. g e tE le m e n tB y ld (" c a k e d o n u ts " ) . v a lu e
Эта ст рочка кода берет данные
о количест ве обычных пончиков,
введенные пользоват елем в ф о р ­
м у заказа.
А эт а ст рочка получает из
ф орм ы данные о количест ве
заказанных глазированных
пончиков.
•
d o c u m e n t. g e tE le m e n tB y ld (" g l a z e d d o n u t s " ) . v a lu e
function updateO rder0 {
c o n s t TAXRATE = 0 . 0 9 2 5 ;
c o n s t DONUTPRICE = 0 . 5 0 ;
v a r n u mC ak eDon ut s =
v a r numGlazedDonuts =
if
(isNaN(numCakeDonuts))
n u mC ak eDo nu ts = 0;
i f (isNaN(numGlazedDonuts))
n u m G l a z e d D o n u t s = 0;
v a r s u b T o t a l = ( nu mCakeDonuts + n u m G l a z e d D o n u t s ) * DONUTPRICE;
v a r t a x = s u b T o t a l * TAXRATE;
v ar t o t a l = subTotal + tax ;
d o c u m e n t . g e t E l e m e n t B y l d ( " s u b t o t a l " ) . v a l u e = "$" + s u b T o t a l . t o F i x e d (2);
document. g etE lem entB yld (" ta x " ) . v a l u e =
+ t a x . t o F i x e d (2) ;
d o cum ent.getE lem entB yld("total").value =
+ t o t a l . t o F i x e d (2);
дальше у
99
решение упражнения
Возьми Вруку карандаш.
'ешение
Итак, вот каким образом нужно было вставить данные в строч­
ки кода, чтобы завершить метод u p d a t e O r d e r {).
docum ent. g e tE le m e n tB y ld (" c a k e d o n u ts" ) . v a lu e
Так как в обоих случаях
мы им еем дело е целыми
числам и, используем для
преобразования м ет од
раг5е1пЬ().
docum ent. g e tE le m e n tB y ld (" g la z e d d o n u ts " ) . v a lu e
function updateO rder0 {
c o n s t TAXRATE = 0 . 0 9 2 5 ;
c o n s t DONUTPRICE = 0 . 5 0 ;
v a r n umC akeDo nu ts =
A
V
w
parselnt(docum ent.getElem entByld("cakedonuts").va(ue):,
\
v a r numGlazedDonuts =
parselifxt(docum ent.getElem ent8yld("glazeddonuts'').value);
if
(isNaN(numCakeDonuts))
n u mC ak eDo nu ts = 0;
i f (isNaN(numGlazedDonuts))
n u m G l a z e d D o n u t s = 0;
v a r s u b T o t a l = ( numCakeDonuts + n u m G l a z e d D o n u t s ) * DONUTPRICE;
v a r t a x = s u b T o t a l * TAXRATE;
var t o t a l = subTotal + tax;
docum ent.g etE lem en tB y ld C 'su b to tal").v alu e =
+ s u b T o t a l . t o F i x e d (2);
docum ent.getE lem entB yld("tax").value =
+ t a x . t o F i x e d (2);
d o c u m e n t . g e t E l e m e n t B y I d ( " t o t a l " ) . v a l u e = "$"
t o t a l . t o F i x e d (2);
М етод ЬоР1хЫ () округляет __
су м м у в долларах, ост авляя
после запят ой всего два знака.
100
глава 2
хранение данных
КЛЮЧЕВЫЕ
МОМЕНТЫ
Имена констант имеет смысл писать ПРОПИСНЫ­
МИ БУКВАМИ, а имена переменных — с использо­
ванием стиляВерблюда.
Всегда инициализируйте константы в момент
NaN означает не число и используется для указа­
ния на отсутствие численных данных там, где они
должны быть.
создания, а переменные по мере возможности.
Соединение строк отличается от математического
сложения, хотя и выполняется одним оператором (+).
Неинициализированная переменная имеет статус
Встроенные методы p a r s e i n t ()
undefined, пока ей не будет присвоено значение.
и p a r s e F l o a t {) преобразуют строки в числа.
Вы решили проблему...
Дункан восхищ ен исправлениями, которы е вы внесли в код
JavaScript. Т еп ерь с получаемыми им заказами все в порядке
и бизнес пошел в гору.
6
_____________
« j.a>№ Мида»
Duncan's JusMn-Time Donuts
-
rls »irmoPu»« Грего.
atpt 70 «< a*'»
Nam:jc^
« of oake donuts: j6~~
^ of gtazarS donuts:
Minutes 1«p)cfcup:|Ja
S u W o la tjiliJ
Tax: [so'ff
Total: IsT gT
Oone
Система заказов через
)
Интернет работает пре- "S
___ )
восходно!
Разумеется, не стоит полагать, что несколько бы стры х исправ­
л ен и й реш ат проблему навсегда. Самые надоедливы е проблемы
обы чно возникаю т из-за сторонних ф акторов...
дальше *
101
г
неприятности нарастают
Дункан обнару}киваеіп шпиона
у Дункана новая проблема: проны рливы й конкурент Ф ренки.
Ф ренки торгует хот-догами на той же самой улице. Ч тобы на­
вредить Дункану, он отп равляет ч ерез И н терн ет фальш ивые
безы м янны е заказы. В итоге Дункану приходится работать
впустую.
0 0 «
Duncan’s Just-ln-Tim e Donuts
Duncan'S Just-In-Time Donuts
All donute 50 certs each, cake or glazod!
Name:
# of cake dofiyts: p i
# of glazed donute; jio
Minutes 4it pickup: p5
Дункан впустую трати т драгоценное время, энергию и пончики,
вы полняя фальш ивы е заказы. Нужно сделать так, чтобы ф орм а
отправлялась только после ввода всех данных.
102
глава 2
хранение данных
Метод getElementByldO
Для проверки корректности вводимых в форму данны х требуется способ
получения этих данны х со страницы . Ключом, дающим JavaScript доступ
к элементам страницы , является атрибут i d в теге HTML:
<input
type= "text"
id= "cakedonuts"
nam e= "cakedonuts"
/> < -
Вводимый в ф орм у элем ент
предст авляет количество
обычных пончиков (саке
donuts).
г
А т р и б у т 1(1 использует ся
для дост упа к полям ф ормы
о коде иауаЗсп'рЬ.
# of cake donuts: 118
JavaScript п озволяет восстанавливать элементы веб-страницы
по их номеру ID п ри помощ и метода g e t E l e m e n t B y l d (). Э тот
метод не забирает данны е напрямую, а представляет поле
HTM L в виде объекта JavaScript. Д ля доступа к данны м доста­
точно воспользоваться свойством v a l u e этого поля.
ф ормально getE iem entB ylP Q
не функция, а м ет од объ ­
ект а документа.
О
document.getElementByldO
Не волнуйтесь по поводу
объектов, методов
и свойств!
|
■einjiu.i , pu.umimJiiJm-Liw*«» iJiJiiiu»
Взяв в качестве парам етра Ш элемента
страницы , метод возвращ ает вам сам
элемент, которы й затем можно исполь­
зовать для доступа к данным.
М етоЭ getE lem entB yldO
принадлеж ит об-ьекту
документа.
в JavaScript поддерж ива­
ется усоверш енствованны й тип данных, назы вае­
мый объектом, позволяю щ ий делать потрясаю щ ие
вещи. Д а и сам язы к JavaScript по сути является
набором объектов. Н о об этом мы поговорим
позднее. П ока же вам достаточно помнить, что
метод подобен м атематической функции, а свой­
ство —это своего рода перем енная.
docum ent. g e tE le m e n tB y ld (" c a k e d o n u ts " )
Ю — эт о
ключ дост упа
к элем ент ам .
docum ent. g e tE le m e n tB y ld (" c a k e d o n u ts" ) .v a lu e
Свойство value дает
дост уп к данным.
# of cake donuts: p i
Вооружившись этим кодом, п роверим форму Дункана на кор­
ректность вводимых в нее данных.
дальше *
103
всё ли вы заполнили ?
Проверка данных формы
Вам нужно убедиться, что в форму для заказа пончиков вводит­
ся имя клиента. Время обязательно следует указывать в минутах,
так как в противном случае теряется основной смысл предо­
ставляемого Дунканом сервиса.
Заказ понт ков.
В данном случае мы долж ны проверить, не равен ли парам етр
value (соответствующих полей) пустой строке ("").
docum ent. g e tE le m e n tB y ld ("name") . v a lu e
Если значением поля nam e является пустая строка, процедуру за­
каза следует приостановить и попросить клиента ввести его имя.
Аналогично следует поступить с полем ввода времени. К роме того,
следует проверить, к числовому ли типу относятся введенны е
в это поле данные. Д ля этого вам потребуется метод IsNaN () . О н
возвращ ает значение ( t r u e ) , если переданны й ему парам етр не
является числом, и зн ачение ( f a l s e ) в противном случае.
Пустая строка указывает
на отсутствие в форме
данных.
Н еверны й
'о о р м а т
оанных.
Minutes 'Ш pickup: jfifteen
г
Если значени "ем являет ся
пуст ая ст рока,
значит , у нас
проблемы.
:
\
isN aN (docum ent. g e tE le m e n tB y ld (" p ic k u p m in u te s " ) . valu e)
isNaNQ п р о ­
веряет т и п
вводимых
данных.
104
глава 2
Если возвраи^ается значет е tru e, значит , данные
введены в неверном ф о р ­
м а т е , и заказ не мож ет
быть обработан.
-^true
хранение данных
Магниты JavaScript
Метод р1ас еОг (1е г () выполняет проверку корректности введенных
в ПОЛЯ данных. Воспользуйтесь магнитами, чтобы получить код, проверяю­
щий ввод имени клиента и времени в минутах, а также то, что во второе
поле введено именно число. Вам потребуются все магниты, а некоторые из
них будут использоваться больше одного раза.
О перат ор ”(Т" проверяет со олюдение условия и в зависи м ост ц от р езу льт а т а о с у ­
щ ест вляет некое действие.
fu4ction placeOrder0
V
if (..........
alert(
Это означает , чт о к дей­
ст виям приводит одно из
двух условий — если т ак
ИЛИ т ак, т о следует н е ­
кое действие.
Это проверка
равенства.
{
y o '„ 'm ;; t 'p r o r i W e ', o «
an o r d e r . " ) ;
J
II
else if .......................................
................. U'V'''oirmnsV’Drovide''the'number of minutes until pick-up"
alert("I'm sorry but you must proviae
" before submitting an order.");
else
//
О т п р а в к а заказа на сервер
form.submit О ;
Ц}
docioment
Ш '
getElementByld
isNaljJl
value 1
дальше *
105
решение задачи с магнитами
Решение задачи с магнитами
Вот как выглядит код метода p la c e O r d e r ( ) , проверяющего
корректность ввода данных о пользователе и времени до до­
ставки заказа, после заполнения пустых мест.
Здесь п т б ер яет ся, не
м е н я е т с я ли значение
S
nam e п у с т о й ст ро
Если им я не введеноJ
т о появляет ся окно
с сообщением.
f ui c t i o n p l a c e O r d e r о
V
if
Кб " "•
{
getElementByld
docmaent
J(
.........
„
(Ь
a le rt( " I'm sorry
e R n b m ittin g an o r d e r . " ) ;
^ getElementByld
else
if
a l e r t ("" before
getElementByld
s u b m i t t i n g an o r d e r . '
else
/ / Отправка з а к а з а на сервер
f o r m . s u b m i t {);
глава 2
| ( "pickupminutes"
' У value
(
is N a N j
106
Э т у ф разу с ко м п ью т ер но ­
го языка на обычный можно
перевест и так: «если значе­
нием являет ся пуст ая с т р о ­
ка ИЛИ значение не являет ся
числом».
^
^ pickupminutes"
)
1 T
.1
value
хранение данных
и сноВа Вы спасли Дункана!
Н овая, улучшенная ф орм а прием а заказов полож ила конец
вредоносной деятельности Ф ренки и сделала страницу более
устойчивой. П рим енение 5ауаЗспр1 для защ иты целостности
вводимых клиентами данны х —беспроигры ш ны й вариант,
особенно в ж естоком ресторанном бизнесе!
Duncan'»
0 0© „
о Т
ОопиЦ^
CD
Duncan’S aust4n-T5ni0 Donuts
М donuts 50 cents each, cake or glazed!
Name: Г
# of cake donuts: pL8
# of giazed donuts; j5o
Minutes 4it ptekup; jwwen
^
1$24ЛСГ
Tax:[S2.22~
Total; |$26.гГ
P lace O rd er
j
.O '
Tenept>j если поле
пат е ост ает ся н е ­
заполненны м, вм ест о
от правки заказа п о ­
являет ся окно с со ­
общением.
Ctone
П е р еста л быть
проблемой и ввод
данных неподходяще­
го ф о рм ат а в полв^
предназначенное для
времени доставки.
I’m sorry but you must provide your name
submitting an order.
before
i'm sorry but you must provide the number of minutes
ur>ti! pick-up before subm ittmg an order.
C ~ oT J
дальше >
107
спросите... в а м
же хочет ся
чаопо
зад аваем ы е
В опросы
Как оператор (+) распознает,
складывать ему или соединять?
Q ; Как это часто бывает в JavaScript,
функциональность определяется
контекстом. То есть оператор смотрит,
что он «складывает», и определяет,
осуществлять ему арифметическое
сложение или соединение строк.
Проблемы возникают, когда вы путаете
тип данных. Это дополнительная причина,
по которой стоит перепроверять данные
перед операцией сложения.
страницу, а браузер. На самом деле
код JavaScript изолирован от кода НТМ1
и получает доступ к нему при помощи
специальных механизмов. Один из таких
механизмов включает в себя атрибут
усовершенствованный тип данных
JavaScript, объединяющий в себе
i d , позволяющий языку JavaScript
воспользоваться элементом НТМ1.
Пометив элемент страницы атрибутом Ю,
вы даете JavaScript возможность работать
с ним.
как свойство является его переменной
или константой. С практической точки
зрения JavaScript использует объекты для
А как именно код иауаЗспр1
осуществляет доступ к элементам
НТМ1-кода?
Что произойдет при попытке
сложить строку и число?
parseint
p a r s e F l o a t ().
— ---
{) или
Что будет, если методу
p a r s e i n t о дать в качестве
параметра строку с десятичной точкой?
Q ; Ничего страшного. JavaScript решит,
что вам просто не интересна дробная
часть, и вернет только целую.
Каким образом атрибут i d
связывает элементы с кодом
JavaScript?
g e t E l e m e n t B y l d ()
d o c u m e n t является ключом,
Q ; Метод
объекта
дающим доступ к элементу HTML из
JavaScript. Этот метод использует
атрибут i d для поиска элемента на
странице. Идентификаторы HTML,
как и идентификаторы JavaScript,
должны быть уникальны в пределах
страницы. В противном случае метод
g e t E l e m e n t B y l d O не сможет
определить, какой из элементов следует
вернуть.
я помню, что мы будем
рассматривать эту тему в главе 9,
! Представим атрибут i d в виде
портала, через который код JavaScript
получает доступ к коду HTIVIL. Говоря,
что код JavaScript запускается на веб­
странице, обычно имеют в виду не саму
108
глава 2
представления всего на свете — и окно
браузера, и веб-страница являются
объектами. Именно поэтому вызов
метода g e t E l e m e n t B y l d ()
осуществляется посредством объекта
d o cu m en t .
А теперь вернемся
к материалу главы 2 ...
Я так и не понял, в чем разница
между элементом веб-страницы и его
значением.
Q ; Так как в JavaScript преобразование
чисел в строки происходит автоматически,
такая операция приведет к объединению
строк. Поэтому сначала число
преобразуется в строку, а потом две
строки соединяются. Чтобы сложить
два числа, сначала преобразуйте
строку методом
методы, константы и переменные.
Метод — это всего лишь функция,
являющаяся частью объекта, в то время
но объекты уже неоднократно
упоминались. Что же это такое?
Q ; Мы в данном случае слегка забегаем
вперед. Объектами называется
; Элементы веб-страницы с точки
зрения JavaScript являются объектами.
Это означает, что у них есть свойства
и они могут управляться методами.
Одним из таких свойств является v a l u e ,
содержащее хранящееся в элементе
значение. Например, значением поля
формы являются введенные в него
данные.
Зачем мне знать, что значение не
является числом? Может быть, лучше
проверять, я в л я е т с я ли оно числом?
; в большинстве случаев
предполагается, что вы имеете дело
с числами, поэтому имеет смысл
проверять исключения. Этим вы делаете
код более устойчивым и избегаете
странных вычислений, в которые могут
быть включены данные неподходящих
типов.
хранение банных
интуитивный ВВод данных
Т еперь, когда Дункан реш ил основны е проблемы, он хочет улучшить форму
заказа пончиков. Н а вывеске его заведения красуется «горячий пончик», и всем
проходящ им мимо сразу понятно, что находится внутри. Такой ж е интуитивно
п онятной Дункан м ечтает сделать форму заказа. О н знает, что пончики обы чно
берут дюжинами. Редко кто просит 12 или 24 штуки —спраш иваю т 1 или 2 дю­
жины. Так почему бы не дать клиентам возмож ность вводить данны е в привы ч­
ном им виде.
П роблем а в том, что наш сценарий не восприним ает слово «дюжина» как руко­
водство к действию и п ерестает понимать, сколько ж е пончиков требуется.
Duncan's Just-In-Time Oojnuts
# 0 0
Duncan's Just-In-Time Donuts
A ll c k m u ts 5» c e n ts e a c h , c a k e o r g la z e d !
Name
# o f cake donuts: |3 dozen
М е т о д p a rs e ln tO
'Преобразует
с у оку «3 d o z e n .
# o f glazed donuts
о число 3.
M inutes 'til pickup: jso
Subtotal; |$1 50
Tax; [$0.14
Total; j$1.64
parseint("3 dozen")
Done
С ценарий не прекращ ает работы , когда пользователи вводят
слово «dozen» вслед за числом. М етод p a r s e i n t () просто иг­
норирует данны й текст. П оэтому в сухом остатке мы получаем
число, а слово «дюжин» отбрасы вается.
Это ‘^ucAOj
а не ст рока.
Ш ТУРМ
Можно ли сделать так, чтобы пользователь вводил или количество пончиков одним чис­
лом, или же число дюжин и слово «dozen» следом? Как этого добиться?
дальше V
109
дюжинами дешевле .. или нет
Можно ли воспользоваться поис­
ком по введенному тексту и найти
слово «dozen»?
— V
Если клиент хочет считать дюжинами, умножим на 12!
Ч тобы добавить в сценарий возмож ность заказы вать пон­
чики дю жинами, нужно п ровери ть введенную клиентом
и нф орм ацию на наличие слова «dozen» до вы числения
промеж уточной суммы. Если такое слово присутствует, вве
денное число умножается на 12. В противном случае число
используется для вы числений без редактирования.
# of cake donuts; j3 dozen
# of саке donuts; p J
parseint("3 dozen")
parselnt("18")
Введено точное
количество з а ­
казанных п о н ­
[
чиков.
Так как в данных
^присут ст вует слово
« d o ze n » , умнож им чис­
ло на 1 2 ..
©
3 * 12 =
0
SSSSSSSSSSSS
'
I
COTTER
110
глава 2
' sssssssss
хранение данных
ощ оБ ьШ К °Д
JaVa^cfipt
П ользовательский метод p a r s e D o n u t s () обрабаты вает инф орм а­
цию о количестве заказанны х пончиков. Сначала он преобразует
введенны е данны е в численны й ф орм ат, затем п роверяет наличие
там слова «dozen». П р и обнаруж ении этого слова введенное число
уножается на 12. П олучите р ец еп т по адресу http://www.headfirstlabs.
сот/books/hfjs/.
fu n c tio n parseDonuts (donutString) {
numDonut s = p a r s e i n t ( d o n u t S t r i n g ) ;
i f ( d o n u t S t r i n g . i n d e x O f ( " d o z e n " ) != - 1 )
numDonut s *= 12;
r e t u r n n u mDo nu t s;
}
ест ь
слово «dny^Mi,^
Умножаем число
пончиков на i-2..
Анализируя дю)кины пончиков...
М етод p a r s e D o n u t s () вы зы вает метод u p d a t e O r d e r () , вы ­
числяю щ ий на основе введенны х клиентом данны х промежу­
точную и конечную суммы.
Получаем число за
казанных пончиков
из поля формы.
И нициализация
двух конст ант .
function updateOrderо {
const TAXRATE = 0.0925; ^
const DONUTPRICE = 0.50;
7
Л
j
var numCakeDonuts = ParseDonuts(document.getElementByld("cakedonnh<,-M
ir
i
^
<
(^IsStL'Ske^D^nu^sn^"^^""''
"glazeddonuts")":aiue
numCakeDonuts = 0;
.if-— -- Если 6 поля Эля Шода данный о количест в.
If (isNaN (numGlazedDonuts) )
введены не числа, присвоим эт им
numGlazedDonuts = 0;
значение G
var to ta l
.
s u b lo ta l + t a , ;
j
f« Z “
document.getElementByldC'subtotal").value =
a o o ™ e „ t . g e t E l e m e „ t B y I d ( " t a x - , . v a lu e
-
+ subTotal
"5 " * ta x . t o F lx S ^ )
document.getElementByld("total").value = "$■' + total.toFixed(2);
Показываем на
ст ранице су м м у
в долларах.
сум м ц
l lo M ^ p a x до двух
Гкпл
запят ой
(количест во центов)
дальше >
111
горячее не бывает!
Полный успех предприятия!
И дея Дункана о доставке горячих пончиков к указанному
клиентом времени заработала благодаря JavaScript, которы й
п озволяет тщ ательно п роверить вводимы е в форму данные.
Теперь люби­
тели пончиков могут за­
казывать их через Интернет
к указанному времени.
і е д а їе р
@ 0 0
Duncan's lust-lt»“Tim< Don s
О
Duncan's Just-In-Time Donuts
All donulB 50 cents each, cake or giszedi
Name; {Alan
# of сяке donuts; fl5
Пончики
# of glazed donuts: |4 t o e n
Minutes -to pickup: |Ї0
Subtotal: j$31.50
Вовремя!
Tax: jS 2 jT
Total: р м Г
Place Order
Done
112
глава 2
хранение данных
Вкладка
Согните страницу
по вертикали, чтобы
совместить два мозга
и решить задачу.
Чего мы все хотим для данных нашего
сценария?
у.у хороШо, а ДВа -ііу'Шіе!
Вводимым пользователями данным
доверять нельзя. Предполагать, что
пользователи при вводе данных будут
их проверять, неразумно.
В этом деле следует положиться на Ла¥а8епр1.
исследование кл и е н т а
Иногда иауаЗспр! хочет знать, что происходит в окружающем
мире. Ваши сценарии могут существовать в качестве кода на веб-страницах,
но по большей части они живут в мире, создаваемом браузером или клиентом.
Умным сценариям часто необходимо знать больше о мире, в котором они
живут, в этом случае они могут общаться с браузером, чтобы узнать про него
как можно больше. Независимо от того, что требуется узнать: размер экрана
или нажата ли кнопка в браузере, они постоянно поддерживают отношения
с браузером.
любовный треугольник JavaScript, клиент и сервер
Клиент, сервер и JavaScript
П осле щ елчка на ссылке или ввода и К Ь в адресную строку браузер
требует указанную страницу с сервера и доставляет ее клиенту.
JavaScript не начинает работу, пока страница не будет доставлена. Его
код встроен в страницу и работает вместе с браузером, отвечая на
действия пользователя. Ч асть браузера, запускающая код JavaScript,
назы вается интерпретатором.
©
Браузер требует страницу
с сервера.
Клиент
©СО
Duncan's Jost-in-Time Donuts
Duncan's Just-ln-TIm® Donuts
CD
( з ) Браузер отображает
страницу.
All donuts 50 cents each, cake or glazed!
Name: jAlan
# of cake donuts; jlS
# of glazed donuts: |4 dozen
©
^
Minutes ’til pickup:
иауаЗспр! проверяет
поля формы в момент ^ ^
ввода данных.
г
Subtotal: j$31.S0
T a x :|$ 2 jT "
Total:
|$34.4Т
©
Код Ja vaScript
выполняется
полност ью на
ст ороне клиент а.
О
116
глава 3
Запрос...
П осле откры ти я страницы в браузере сервер вы­
ходит из игры. Н ачиная с этого момента все, что
делает JavaScript, ограничивается только браузером.
Это увеличивает скорость взаимодействия со
страницей, ведь вам не приходится ждать, пока сер­
вер обработает и верн ет данные. И м енно поэтому
JavaScript назы вается языком клиента.
знакомство с браузером
З а п р о с с тр ан и ц ы
S i'
Connection; close ^
Accept-Encoding: gzip
^
/„-1„вгт
image/jpeg, image/p]peg, . ..
HTML описывает
, с т р у к т у р у документа.
Ответ на запрос
<html>
<head>
<title>Duncan's Just-In-Time Donut..</t ^м .s
_
I
"
IP.- ri-ГГ--ГГ-p...........
g”""’
<sc
^
type "text/javascript">
unction u p d a t e O r d e r () {
parseDonuts(donutString)
function p l a c e O r d e r
0
{
__
------------------- --
{
JavaScript добавляет и н ­
терактивность). В дан
ном случае он проверяет
введенные пользоват е
леМ данные.
Сервер отправляет
запрошенную
страницу.
( 1)
<body>
<div id="frame">
л-
<div c l a s s = 4 u b h e a d i n g " > A i r d o n u t r s r ' ^ ^ ^ ^ Donuts</div>
<drv i d = " l e f f >
®
50 cents each, cake or
glazed '</div>
</<xmg src="donuttime.png.. alt=-Just-In-Ti^e Donuts" />
<div id="right">
</div>
</div>
</body>
</html>
U iT V P M
Какие еще задачи разумнее выполнять на стороне клиента, а не на стороне сервера?
далее >
117
спроси не то, что т ы можешь сделат ь д ля браузера...
Ч то браузер мо)кет сделать для Вас?
Ваш браузер отвечает за запуск кoдaJavaS cript, давая сценариям до­
пуск к клиентской среде. Н априм ер, сценарий мож ет узнать ш ирину
и высоту окна браузера или историю посещ ений веб-страницы. Дру­
гими интересны м и функциями браузеров, откры ты м и для JavaScript,
являю тся тайм еры и возмож ность сохранения куки. Так назы ваю тся
создаваемые серверам и ф рагм енты данных, которы е хранятся на ком­
пью тере пользователя даже после того, как он ушел со страницы или
вообщ е закры л окно браузера.
изме|>ения браузера
Вы мож ете узнать не только
разм ер окна браузера и видимой
части веб-страницы, но и и н ф о р ­
мацию о производителе, и даже
ном ер версии.
история браузера
С п ом ощ ью ]ауа8спр1вы
мож ете получить доступ к спи­
ску последних посещ енны х
страниц и п ерей ти н а любую
и з них, эф ф екти вн о с о з д а в ^
ваш и собственны е элементь
управления браузером.
Таймеры
Кука
Тайм еры позволяю т
запускать код 5ауа8спр1
по истечении заданного
времени.
Куки подобны перем ен­
ным, которы е сохраняю т­
ся браузером на жестком
диске пользовательского
ком пью тера после заверш е­
ния веб-сессии. То есть вы
мож ете покинуть страницу,
снова на нее вернуться, но
они все равн о никуда не
Это далеко не все функции, которы е клиент предоставляет сцена­
денутся.
риям. Мы всего лиш ь попы тались дать вам представление о том,
что JavaScript умеет намного больше, чем просто присутствовать на
странице. Б олее того, часто возникаю т ситуации, когда им еет смысл
выглянуть за пределы страницы и получить от браузера помощь.
118
глава 3
знакомство с браузером
Часто
____ <аДаВаеМые
-------
БоГЦроСЬ!
Итак, иауаЗсг1р1 является частью
клиента?
О ; Да. Поддерживающие иауаЗспр!
браузеры имеют встроенный
интерпретатор, отвечающий за чтение
и запуск кода на странице.
3 * Если код иауаЗспр! запускается
на стороне клиента, как он связан
с сервером?
Позволяет ли иауаЗспр!
контролировать клиента?
Q ; Код JavaScript не имеет прямого
доступа к серверу, так как он работает
на стороне клиента. Обычно он
используется для перехвата данных,
транслируемых с сервера в браузер. Но
можно написать и сценарий, который
будет запрашивать информацию
с сервера, а затем обрабатывать ее
и отображать на странице. Эта техника
называется Ajax. О ней мы поговорим
0 ; И да и нет. Браузеры дают
иауаЗспр! доступ к определенным
частям клиентской среды, но он весьма
ограничен по причинам безопасности.
Например, большинство браузеров
не позволяет сценариям открывать
и закрывать окна без согласия
в главе 12.
пользователя.
Объект iRocl( слишком счастлив
П ом ните объект iRock? Ваш код JavaScript имел такой успех,
что его выкупил молодой п редприним атель Ален. Н о он снова
обратился к вам, так как появилась проблема... П ользователей
раздраж ает вечное счастье объекта 1Коск. Разумеется, мы все
хотим, чтобы наш и домаш ние лю бимцы были счастливы, но
в данном случае диапазон эм оций уж слишком ограничен.
Я полагал, что домашний
любимец все время должен быть
счастливым, но пользователи хо­
тят большего реализма. Поэтому
давайте перепишем код...
Один щелчок...
и я буду улыбаться
вечно.
д ден.
0«
^ ^ 8о »«лоМ
,ллитЬ,
Hft
И так, вам следует подстроиться под ожидания пользователей.
П остараем ся сделать вашего виртуального домаш него лю бимца как
мож но более реальным. Вам следует понять, как нужно поменять по­
ведение объекта 1Коск. И кажется, в реш ен ии проблемы вам мож ет
в н екоторой степени помочь браузер клиента.
далее
►
119
эмоции объекта гйоск
^Rock дод}кен быть более отзыВчиВым
Рассмотрим возможны е варианты поведения объекта 1Коск, которы е
сделаю т его более реалистичным и привлекательны м для пользователя,
не говоря уже о больш ей интерактивности. В идеале нам следует увели­
чить диапазон испы ты ваем ы х объектом эмоций.
Разгневанный
Последнюю версию кода /Ш ск г.О вы найдете по
адресу nttp://w w w .keadfirstlab< ,.com /books/hfjS.
Камеш ек мож ет без
причины разгневаться,
и владельцу нужно будет
его успокаивать.
/^о д а В лен н ы й
К а д раз, когда вы
закры ваете страницу
камеш ек начинает
плакать, требуя,
чтобы пользователь
оставил окно браузе­
р а открытым.
Одинокий
Если долго не обращ ать
вним ания на 1Коск, он на­
чинает чувствовать себя
одиноким. Щ елкайте на
нем периодически, чтобы
он чувствовал вашу заботу.
ШТУРМ
Какие из этих эмоций имеет смысл приобрести объекту 1Коск? Каким об­
разом их можно реализовать при помощи иауаЗспр!?
120
глава 3
знакомство с браузером
Мне нравится идея, что камешек может
почувствовать одиночество, так как именно такое по­
ведение свойственно реальным домашним животным
Можно ли сделать так, чтобы поведение объекта
iRock менялось с течением времени?
J a v a S c rip t п о зв о л я ет у зн а ть , ко гд а
пол ьзовател ь вы полняет н е к и е д ей ств и я ...
И ко гд а он это го н е д ел а ет.
Бы ло бы и нтересн о заставить камеш ек испы ты вать
одиночество, так как это подтолкнет пользователя
к взаимодействию и вознаградит позитивны м от­
ветом объекта 1Коск. В опрос в том, как п ри помош;и
JavaScript заставить объект 1Коск со временем менять
свое эм оциональное состояние. Нужно сделать так,
чтобы 1Коск начинал грустить, если в теч ен и е опреде­
ленного врем ени пользователь ни разу не ш;елкнул на
нем.
...5 секунд
спуст я.
далее
►
121
время работает на меня
Таймеры
Т айм еры вJavaScript по принципу действия напоминаю т
будильники. Н о если будильник вы устанавливаете на опреде­
лен н ое время, то в случае тайм ера следует указать, сколько
врем ени осталось до собы тия. П о прош ествии этого времени
вы полняется указанный кусок кода.
П родолж ит елш ост ь
Задерж ка
Сейчас
Л й м е р а определяет именно
задержка.
П озднее
Таймер начинает
работ ат ь сразу же
после его настройки.
а І е г Ь («Просьшайся!)
После завершения
тс я
отсчета
кодП о истечении заданного тайм ером врем ени вы мож ете за­
пустить лю бой код. Если содерж им ое страницы регулярно
редактируется, тайм ер мож но использовать для ее п ери о­
дического обновления. В других случаях тайм ер помогает
определить отсутствие активности пользователя в течение
заданного времени.
122
глава 3
После т ого как
указанное время
кончит ся, т а й ­
м ер заверш ит
работ у.
Таймеры позволя­
ют запускать код
1ауа8спр1 через
нужное вам время.
знакомство с браузером
Как работает таймер
Ч тобы запустить таймер, вам нужно 1) указать время задержки; 2) ука­
зать код, которы й следует запустить после указанного времени. Таймер
начинает работу сразу ж е после его настройки.
В ремя задерж ки отсчиты вается
в миллисекундах, то есть в ты сяч­
ны х долях секунды, к примеру,
2 секунды это 2000 миллисекунд.
О т образит ь
сообщение.
Код, которы й запускается по истечен и и срока
действия тайм ера, зависит только от вашего
ж елания. Это мож ет быть один оператор, набор
операторов (каждый из которы х
1
заверш ается точкой с запятой),
refreshO; setTimeout(refresh.
и даже вызов встроенного или
пользовательского метода.
Обновить
ст раницу.
alert («П росьш ай ся !»)
П осле заверш ения отсчета тайм ер запускает код JavaScript
и исчезает. М ожно создать таймер, которы й будет запу­
скать код ч ерез определенны е промеж утки времени, пока
вы его не остановите. Н о в данном случае нам потребуется
одноразовы й таймер.
~
\
ш нгнт
Совместите одинаковые показатели.
500 мс
5 минут
300 ООО мс
5 секунд
5000 мс
1/2 секунды
далее >
123
времени мало, дейст вуй сейчас
Вот как соотносятся различные записи.
п^ражнение
решение
500 мс
5 минут
300 ООО мс
5 секунд
5000 мс
1/2 секунды
Метод setTimeoutO
в Jav aS crip t о д н о р а зо в ы е т а й м е р ы запускаю тся п р и пом ощ и
в с т р о е н н о г о м ето д а s e t T i m e o u t {). Д л я его р а б о т ы вам нуж но
указать в р ем я зад ер ж ки и код, к о т о р ы й следует зап усти ть (до­
ступен п о адресу http://www.headfirstlabs.com/books/hfsd/). Р ассм о­
т р и м н е б о л ьш о й п р и м ер :
М етод setTimeoLit( )
уст анавливает одно­
крат ны й т аймер.
равняет ся <ьоо с е к З ^ ^ '
м и н ут а м
6 0 0 0 0 0 );
s e t T i m e o u t (" a l e r t ('Wake
НикогЭд не от деляйт е
разряды даже при н а -
КоЭ JavaScript, к о т о ­
рый следует вы п о лн и т ь.
по т а й м ер у, передает ­
ся м ет оду setTim eoutQ
в виде т екст овой ст роки.
Вот почему он помеш,ен
в кавычки.
После завершения
от счет а появляет ся
окно с сообщением.
Ч и С ^ Т '^
В д ан н о м случае м етод s e t T i m e o u t () со зд ает
т ай м е р , к о т о р ы й ч е р е з 10 м инут в ы зы в а е т о кн о
с сообп 1;ением.
6С>С> ООО
миллисекунд!
за д е р ж к а 10 м и н у .
Wake up!
І
124
глава 3
знакомство с браузером
Анализ метода setTimeout()
В от си н так си с м ето д а setTimeout ():
Заклю чает
в себя ода
аргум ент а
setTimeout
Код, запускаемый
после прекращ ения
работы т аймера.
Разделяет аргум ент ы . Задержка
в м иллисекундах-
Заверш ает
операт ор.
З ад а н и е та й м е р а , ср аб аты в аю щ его ч е р е з о п р е д е л ен н ы е пром еж утки
вр е м ен и , осу щ ествл яется с пом ощ ью м ето д а set Interval {). Его си н ­
такси с ан а л о ги ч е н преды дущ ему. В р езу л ьтате о д и н и т о т ж е код будет
запускаться м н о го раз:
var timerlD = setlnterval :" a l e r t ('Wake u p !')
Т
У ст анавливает
Хранимый о т повт оряющ ийся
делш о и д ен т и ф икат ор т а й т аймер.
XO м инут .
I
Wake up!
n o м инут .
1 - г
~~^iO м инут .
Wake up!
t-O м и н у т
Wake up!
М ногократный '
т а йм ер запускает
код через указанный
вами промеж ут ок _
времени.
Wake up!
р
с . 9,1.3
бООООО)
р а д ь те
о с т о р 'о ж н
М инут ы
в м и лл и се к у н ­
дах.
ы1
Задержка
таймера
указывается
в миллисе­
кундах.
Миллисекунды являются до­
лями секунд, поэтому, забыв,
что надо их использовать,
можно получить несуразно
быстрые или, наоборот,
медленные таймеры.
Возьми 8 руку карандаш
Создайте свою
версию файла
irock.htm l и п р о ­
т ест и р уй т е
свой вариант —
кода перед т ем ,
как перевернут ь
ст раницу.
Напишите код, меняющий после 5 минут изображение объекта iRock
со счастливого на одинокое. Подсказка: идентификатор изображения
элемента iRock называется rocklmg, а файл с изображением одино­
чества — rock.png.*
* Э т от ф айл находится по адресу k t t p : / / w w w .kea d firstla b s.co m /b o o ks/kfjs/
далее >>
125
решение упражнения
возьми в руку карандаш
Решение
Вот как выглядит код, меняющий через 5 минут изображение
камешка со счастливого на одинокое.
Кавычки и а п о ст р о ф ы ^
позволяют о с у щ е с т в и т ь
к о р р е к т н о е влож ение
м ет одов.
Л
^^^Т'!^УУ?:9}^Ж!!^Р^!^'^^пЬ.^еЬЕ{етен±Ву1с1^госк1тд‘).5гс = 'г о с к .р п д ';",
.. .5.*. . Ш
м и л л и L-CKyИJ^,
с е к у н д ^ /'
гД ,л я 'перевода ив /V^iЛ/\/Ш
оы п я т
и м и н у т н о й' за д’ е р ж ки
.......
сначала н у ж н о п р е о б р а зо в а т ь
все в м и н у т ы (х& О ), з а т е м о м и л л и с е к у н д ы ( х ± 0 0 0 ).
ХРР.а);............ . Л ...................................................... ^
Л
(
Замена изображения
(Я оск о сущ е ст в л я е т ся
п о д с т а н о вко й нового
граф ического ф айла
в а т р и б у т $гс.
Идентификатор
•изображения.
Изображе­
ние кйМешка.,
кот ором у
одиноко.
Теперь îRock чуВстВуеш одиночестВо!
Н е забудьте в н е с т и вы ш еу казан н ы е и зм е н ен и я в ф ай л i r o c k . h tm l
и п р о в е р ь т е , как все р а б о т а е т . О б ъ е к т iR ock д о л ж ен д ем о н с т р и р о в ат ь
о д и н о ч е с тв о , есл и в т е ч е н и е п я т и м инут н а н ем н и разу н е ш;елкнул
п о л ьзо в ател ь. Н еб о л ьш ая в р е м е н н а я за д ер ж к а м о ж ет п р и в е с т и к тому,
ч т о кам еш ек п о к а ж е тся вам ч ер есч у р т р е б о в а т ел ь н ы м , н о ведь мы и х о ­
т е л и все в р е м я д ер ж а ть п о л ь зо в а т е л я зан яты м . К ак будто рядом с ни м
д ей с тв и те л ь н о ж и в о е суш;ество со св о и м и нуж дами.
Т а й м е р ведет о б р а т н ы й
о т счет «счаст ливого
о р е м е н и » о б ъ е кт а ÎRock.
п оДсказка
М имолетность
сча ст ливого с о ­
ст о я н и я сделала
объект iRock более
живым.
126
глава 3
Ускорить смену эмоциональных
состояний объекта можно, умень­
шив задержку вызова метода
s e t T i m e o u t () . Это позволит
протестировать сценарий без долгих
ожиданий.
знакомство с браузером
П ользователи бы ли
правы . С б о л ь ш и м к о ­
л и ч е с т в о м э м о ц и й 1Роск
бо л е е п р и в л е ка те л е н .
Таймер заверш ил работ а
и счаст ье сменилось на
одиночество.
_
Ч асто
<аДаБаеМые
Б о г1|= »ос:ь1
Если объект іРоск должен пере­
ходить в одинокое состояние через
каждые 5 минут, почему не задать для
него временной интервал?
! Дело в том, что периодическое
ощущение одиночества нашего объекта
следует за периодом счастья. Таймер за­
пускается по щелчку, когда через 5 минут
он завершает работу, объект переходит
в грустное состояние и остается в нем
до следующего щелчка. Для реализации
подобного сценария многократный таймер
не подходит, ведь он будет срабатывать
каждые 5 минут независимо от действий
пользователя.
Можно ли создать таймер, кото­
рый будет запускать код в определен­
ное время?
! Таймеры не пользуются абсолютным
временем, поэтому для выполнения по­
добной задачи нужно вычислить задерж­
ку, вычтя текущее время из желаемого
времени срабатывания. Эти подсчеты
выполняются при помощи объекта D a te ,
с которым вы познакомитесь в главе 9.
Данные на моей странице часто
редактируются, поэтому я хотел бы
обновлять ее каждые 15 минут. Как это
сделать?
Как остановить таймер, срабаты­
вающий через заданные промежутки
времени?
! Для прекращения работы
таймера, запущенного методом
s e t l n t e r v a l ( ) , используется метод
Что произойдет, если закрыть
браузер до завершения обратного
отсчета?
! С помощью метода
s e t l n t e r v a l О установите таймер
на 15 минут, то есть на 900 ООО миллисе­
кунд (15 X 60 X 1000). Обновление стра­
0 ; Ничего. Интерпретатор иауаЗспр!
при этом прекращает свою работу, и все
сценарии иауаЗспр!, в том числе и таймер,
завершаются.
ницы реализуется методом r e l o a d {)
объекта l o c a t i o n вот таким образом:
lo c a t io n . r e lo a d ( ) ;
Можно также воспользоваться техноло­
c l e a r I n t e r v a l ( ) . Ему следует
передать идентификатор останавливае­
мого таймера, который возвращает метод
s e t l n t e r v a l ( ) . Сохранив возвра­
щенное значение, например, под именем
t i m e r ID , передайте его методу
c l e a r l n t e r v a l ( ) вот таким обра­
зом: c l e a r l n t e r v a l ( t i m e r l D ) .
гией Ajax, с которой вы познакомитесь
в главе 12, для динамической загрузки
данных.
далее ►
127
браузер в открытом доступе
В Р А У З Ё Р
О' c B B te
Интервью недели:
П р и з н а н и я в е б -к л и е н т а
Head First: С паси бо , ч то , н е с м о т р я н а за н я т о сть,
наш л и в р е м я и заш ли к нам в гости .
Head First: Д а, вы п р авы . Т ак ч т о ж е эт о т ак о е —
б ы ть веб-клиентом ?
Браузер: Д а, я к р а й н е зан ят. К ак будто м ало
м н е б ы ло H T M L и CSS и св я за н н ы х с н и м и
о с о б е н н о с т е й ви зу ал и зац и и с т р ан и ц , т е п е р ь м не
п р и х о д и тс я и м е т ь д ел о еш;е и с Jav aS crip t. Э то
совсем другой зв ер ь.
Браузер: Э то зн а ч и т б ы ть принимаю ш ;им ко н ц о м
кан ала до ставки веб-стран и ц , зап р о ш ен н ы х
с сер в ер а.
Head First: Ч т о вы и м е е т е в виду? Jav aS crip t д и к
и н еп р и р у чен ?
Браузер: К о н е ч н о , н ет. Я у п о тр е б и л сл ово
«зверь» в п е р е н о с н о м см ы сле. Я всего л и ш ь им ел
в виду н о в ы е п р о б л ем ы , к о т о р ы е п о я в и л и сь
вм есте с Jav aS crip t. Я д о л ж ен ч и т а т ь эт о т код,
м олясь, ч то б ы о н бы л н а п и с а н к о р р е к т н о ,
а п о то м запускать его, н е заб ы в ая п р и это м п р о
H T M L и CSS.
Head First: И как вы справл яетесь?
Браузер: К счастью , эт и т р и суш,ности п р е к р а сн о
р аб о т а ю т вм есте, х о т я и н о гд а Jav aS crip t ш алит
и и ск аж ает H T M L -код. П р о б л е м а в то м , ч то
я н и как н е могу н а эт о п о в л и я ть . В едь я всего
л и ш ь делаю то , ч т о м не п р и к а зы в а ю т делать.
Head First: Т о е с ть вы скл о н н ы к п о д чи н ен и ю ?
Браузер: М ож н о сказать и так, н о б о л ее т о ч н ы м
будет п р и зн а т ь , ч т о б ольш е всего я цен ю
взаи м о д ей ств и е. М оя зад ач а б р ат ь код, к о т о р ы й
о т д а е т м не с е р в е р , и п оступ ать с ни м так, как м не
п р и казы в аю т.
Head First: Д аж е если код я в л я е т с я ош иб о чн ы м ?
Браузер: Я стар аю сь р е ш а т ь п р о б л ем ы , когда
виж у их, н о эт о т я ж е л ая р аб о та. К р о м е то го , это
те м а для другого обсуж ден ия (из гл авы 11). А п о к а
д ав ай те п о го в о р и м о м о ей р а б о т е в ка ч е с тв е веб ­
к л и ен та.
128
глава 3
Head First: А как эт о св я зан о с JavaScript?
Браузер: О ч е н ь тесн о . Я вы п о л н я ю всю работу
по о т о б р аж ен и ю ст р а н и ц и о б р аб о т к е ввод и м ы х
п о л ьзо в ат ел ям и д ан ны х. A Jav aS crip t в эт о вр ем я
во все сует свой н о с и в н о си т и зм е н ен и я . Х о тя все
н е т ак плохо. М н о ги е вещ и я н и ко гд а н е см ог бы
сдел ать сам о сто я тел ь н о .
Head First: Н а п р и м ер ?
Браузер: Ну, я бы н е сделал н и ч его о со б е н н о го
в ситуации , когда п о л ьзо в ат ел ь н аво д и т указатель
м ы ш и н а и зо б р а ж е н и е и л и м е н я е т м ой р азм ер.
A Jav aS crip t п о зв о л я е т легко п о м ен я т ь вид
с т р ан и ц ы в о т в е т н а д ей ств и я п о л ьзо в ател я. Я не
возр аж аю , т а к как код Jav aS crip t запускается на
с т р а н и ц е и н а о с н о в е ст р ан и ц ы и в л и я е т то л ь к о
н а саму стран ицу.
Head First: Вы г о в о р и т е п р о Jav aS crip t как п р о
чуж еродную сущ ность. Н о р а зв е это н е ч ас т ь вас?
Браузер: Д а, Jav a S crip t о п р ед ел ен н о я в л я е т с я
частью м ен я, н о его м ож н о во сп р и н и м а т ь
и как с т о р о н н ю ю сущ ность, т а к как доступ
к кл и ен ту (ко м не) о н осущ ествл яет п о ср ед ств о м
о г р а н и ч е н н о г о и н т е р ф е й с а . Т о есть я н е даю
Jav aS crip t н е о г р а н и ч е н н о г о д оступа ко всему.
Э то б ы л о бы н е о с т о р о ж н о , ведь я н е знаю , кто
н ап и сал с ц е н а р и й и п о п р о с и л м ен я зап усти ть его.
Head First: П о н я т н о . С паси бо, ч т о п о д ел и л и сь
с н ам и п о д р о б н о с тя м и ж и зн и к л и ен та.
Browser: Рад, ч т о см ог вам пом очь.
знакомство с браузером
Зависимость о т размера экрана
Т о л ьк о А лен успел о б р ад о в аться новом у д и ап азо н у эм о ц и й о б ъ е к т а 1Коск,
как к о м п ан и ю зах лестн ула н о в а я в о л н а п о л ь зо в а тел ьс к и х ж алоб. О казы ва­
ется, р а зм е р о б ъ е к т а н е о ч е н ь стаб и л ен . Н е к о т о р ы е п о л ь зо в а т ел и ж алую т­
ся н а «син дром сх л о п ы в ан и я» , в т о в р е м я как другие и сп ы т ал и стр ах п ер ед
«гигантски м кам нем ». А лен д о в е р я е т т о л ь к о вам , т ак ч т о п р и ш л о вр ем я
' с н о в а п р и в е с т и 1Коск в п о р я д о к.
Н е ко т о р ы е п о льзо ва т е ли
го в о р я т , ч т о не м о г у т
X т о л к о м р а згл я д е т ь о б ъ ­
е к т /Rock.
/\р у г и е видят
т о л ь ко ч а с т ь
г и га н т ско го
ка м н я .
ГШ ТУРМ
Почему в разных браузерах камешек
имеет разный размер?
далее >
129
размер имеет значение
Ширина окна браузера
В о зн и кш ая п р о б л ем а св я за н а с тем , ч т о р а зм е р о б ъ е к та
1Коск н е м ен я е тс я вм есте с р а зм е р о м о к н а б раузера. М о­
ж е т п о к азаться, ч то это х о р о ш о , есл и н е у ч и ты вать, ч то
п о л ьзо в а т е л ь м о ж ет зах о д и ть в И н т е р н е т как с м о б и л ьн о го
у стр о й ств а, т а к и с н а с т о л ьн о го к о м п ью т е р а с ги ган тски м
м о н и то р о м . З н а ч и т , вам следует за р а н е е о п р е д е л и т ь ш и р и ­
ну о к н а и с о о т в ет с т в е н н о о т р е д а к т и р о в а т ь р а зм е р наш его
кам еш ка.
И зо б р а ж е н и е к а м е ш к а п оявляет ся
в к л и е н т с к о й ч а с т и о кн а б р а узе р а ,
и, следоват ельно, и м е н н о его п а р а м е ­
т р ы н у ж н о и с п о л ь зо в а т ь для и з м е н е ­
ний р а з м е р о в о б ъ е кт а 1Коск.
,Носк - ТЬе
Клиентской называется
та часть окна браузера,
в которой отображается
веб-страница.
Ре1 йрск ...
в о а
Г
.
docшnent. Ьос1у.с11еп'ЬНе1дЬЬ
В ы со т а
.к л и е н т с к о г о
окна.
Не о т н о с и т с я
к вы сот е к л и ­
ент ской т е т и
окна.
<1осшпвпЪ.Ьо<1у ■с 1 1 епЪ» 1 (1ЪЬ
................... .
Ш ирина окна
кл и е н т а .
130
глава 3
В аж н о о т л и ч а т ь ш и р и н у и вы соту к л и ен тс к о й ч асти о т обш;ей
ш и р и н ы и вы с о ты о к н а б раузера. О кн ом к л и ен та сч и тае тся
т о л ь к о т а ч асть, в к о т о р о й о т о б р аж ает ся веб-страни ца. С тр о к а
заго л о вка, п а н ел и и н стр у м ен то в и с т р о к а с о с то я н и я сю да уже не
входят. Р а зм е р о б ъ е к т а 1Коск вы ч и с л яе т ся , и сход я и з р а зм ер о в
к л и ен тск о й части.
знакомство с браузером
docioment
Задание ширины окна
О б ъ е к т d o c ijrn e p i
п р е д с т а в л я е т собой
в е б -с т р а н и ц у .
Р азм ер к л и ен тск о го
о к н а п л о т н о связан
с веб -стр ан и ц ей , доступ
к к о т о р о й в Jav aS crip t
осущ ествл яется п р и
п ом о щ и о б ъ е к т а
document. И м е н н о
эт о т о б ъ е к т давал вам
доступ к эл ем ен там
ст р а н и ц ы в м ето д е
<html>
<head>
< t i t l e > i R o c k - The V i r t u a l P e t R o c k < / t i t l e >
< s c r i p t t y p e = " t e x t / j a v a s c r i p t ">
v a r userName;
function greetUserO {
a l e r t ( ' H e l l o , I am y o u r p e t r o c k . ' ) ;
1
f u n c t i o n touchRockO {
i f (userName) {
a l e r t ( " I lik e the a tte n tio n ,
getElementByld().
else {
userName = p r o mp t ( " Wh a t i s y o u r name? ", " E n t e r y o u r name h e r e . " ) ,
i f (userName)
a l e r t C ' I t i s good t o me e t you, " + userName + " . " ) ;
С вой ства
body.clientWidth
и body.clientHeight
д окум ента со д ер ж ат
инф орм ацию о ш ирине
и в ы с о те кл и ен тск о го
окн а.
Тело документа
у\р& 3см й8ля&т с о ­
бой б и З и м у ю мастер
cm pam vp^> в кл ю ча я
ш и р и н у ы вы сот у
кл и е н т ско го окна.
" + userName + ". Thank y o u . " ) ;
}
}
document.getElementByld("rocklm g").src = "rock_happy.png";
s e t T i m e o u t (" d o c u m e n t . g e t E l e m e n t B y l d ( ' r o c k l m g ' ) . s r c = ' r o c k . p n g ' ; " ,
5 * 60 * 1 0 0 0 ) ;
}
</script>
</ he a d >
<body o n l o a d = " g r e e t U s e r 0 ; " >
<div styl e= "m ar gi n- top :l OO px; t e x t - a l i g n : ce n te r">
<img i d = " r o c k I m g " s r c = " r o c k . p n g " a l t = " i R o c k " s t y l e = " c u r s o r : p o i n t e r "
o n c l i c k = " t o u c h R o c k ( ) ; " />
J
</div>
</ body>
</html>
4aca»o
З ад авае м ы е
^
^ o "Hf j=
o >eo C b l'
B
^ !И |все-таки, чем различаются веб-клиент, браузер, окно
клие
клиента и окно браузера?
Почему мы собираемся менять размер объекта 1Коск
именно в зависимости от размера окна клиента?
! Да, запутаться тут легко. С глобальной точки зрения браузер
является веб-клиентом, так как при обслуживании веб-страниц
он находится на стороне клиента. Если же рассмотреть браузер,
слово «клиент» уже будет относиться к области, в которой появ­
ляется веб-страница. Так что окном клиента называется область
0:,
; Именно от размеров окна клиента зависит, какую часть
пространства будет занимать отображаемый объект. Осталь­
ные элементы браузера, например дополнительные панели
инструментов, крайне сложно учесть из-за их разнообразия при
переходе от одной платформы к другой. К примеру, при одина­
внутри браузера, в которую не входят строки заголовка, полосы
прокрутки, панели инструментов и т. д.
ковом размере окна клиента размер браузера Safari в Мае будет
отличаться от размера браузера Firefox в Windows.
О
далее >
131
насколько велико большое?
Высота и ширина объекта iRock
З н а н и е р а зм е р о в кл и ен тс к о го о к н а н е п о м о ж ет вам б ез в о зм о ж н о с ти м ен я ть
р а зм е р и зо б р а ж е н и я о б ъ е к т а iRock. К счастью , Jav aS crip t вм есте с CSS п о ­
зв о л я ю т это д елать. С в о й ств а w i d t h и h e i g h t и зо б р а ж е н и я даю т н е то л ь к о
и н ф о р м а ц и ю о р а зм е р е о б ъ екта, н о и в о зм о ж н о с ть его д и н а м и ч е ск и м ен ять.
style, h e i g h t ^
Высота
изображ ения.
s ty le .w id th
Ш и р и н а L-----
Д л я каж дого эл ем е н та с т р а н и ц ы сущ ествует о б ъ е к т s t y l e , п о зв о л я ­
ю щ и й узн ать ге о м е т р и ч е с к и е р а зм е р ы эт о го эл ем ен та. С н ач ал а вам
п о тр еб у ется доступ к сам ом у элем енту, т о есть к к а р т и н к е с кам еш ­
ком . К ак вы уже зн а е те , для это го нуж ен м етод g e t E l e m e n t B y l d ()
о б ъ е к т а d o c u m e n t:
К о д Н ТМ и карт инки
с к а м н е м дает ва м
дост уп к свойст вам
с т и л я изображ ения.
<img id="rockImg" s r c ="rock.png" alt="iRock"
/
d o c u m e n t .getEl e m e n t B y l d ("rocklmg").s t y l e .height
Д л я и зм е н ен и я р а зм е р о в о б ъ е к т а iR o ck д о с т а т о ч н о п о м е н я т ь зн а­
ч е н и я соответству ю щ и х сво й ств. Т о ч н е е , вы м о ж ете о гр ан и ч и т ь с я
р е д а к ти р о в а н и е м т о л ь к о о д н о го сво й ств а. В т о р о е и зм е н и т с я авто ­
м ати ч еск и , ч то б ы с о х р а н и т ь п р о п о р ц и и и зо б р аж е н и я :
Э т о т ко З п о з в о л я е т
„ з н а т е - в ы с о т у «зо
Ъражтия камешка.
С делайт е вы со т у
и зо б р а ж е н и я р а вн о й
1 0 0 пикселам .
d o c u m e n t .getElementByld("rocklmg").s t y l e .height = "lOOpx";
132
глава 3
данный
6 coo
... />
знакомство с браузером
^Rock доА)кен соошбетсшВоВать странице
П о к а ч т о р а зм е р и зо б р а ж е н и я кам еш ка н и к а к н е свя зан с р а зм е р о м о кн а
к л и ен та , в то в р е м я как о н д о л ж ен м е н я т ь с я п р о п о р ц и о н а л ь н о ему. П усть
его р а зм е р со с та в л я е т о п р е д е л е н н ы й п р о ц е н т о т р а зм е р а окна.
К а к о е и з и зм е р е н и й следует в ы б р ат ь д ля п р и в язк и ? Т ак как п о в е р т и к а л и
б раузер ы им ею т б о льш и е о г р а н и ч е н и я , и м е е т см ы сл в ы б и р а ть р азм е р кам ­
н я в за в и с и м о с т и о т в ы с о ты ви д и м о й области.
Высота окна
кл и ен та.
(clientWindowHeight - 100) * 0.9 = госк1тадеНе±дЬй
% от. того, что
остается по в е р т и ка л и .
М ы уч и ты ваем пустое п р о с т р а н с т в о сверху над кам еш ком
(100 п и к се л о в ), а затем ум еньш аем и зо б р а ж е н и е н а 90 % от
о став ш ей ся в ы со ты кл и ен тск о го окн а. Ф орм ула для п о д о б н ы х
р а с ч е т о в о б ы ч н о п о д б и р ае тс я м етод ом п р о б и ош ибок. Вам
следует п о см о т р е ть , как будет в р езу л ьтате вы гл яд еть 1Коск, но
далее ►
133
решение упражнения
^ В о з ь м и
В р у ку каранд аш
Решение
Вот как выглядит код метода resizeRock () и код обра­
ботчика события onload, вызывающего этот метод.
Р азм ер и зо бр а ж е н и я
кам еш ка в ы числ я ем ­
ся на основе вы сот ы
кл и е н т с ко г о окна.
IP к а р т и н к и с к а м е ш к о м
и с п о л м у е т с й для д о с т у п а
к элем ент у.
function resizeRock О {
П ри за гр узке с т р а н и ц ы
вы зы в а ю т ся два м е т о д а ,
т а к к а к обработ чик с о ­
бы т ий позв о л я е т п р и ­
вяза т ь к себе несколько
ку с ко в кода.
В ы ч т и т е 1 -0 0
п и ксе л о в для
от ст упа от
верхней границы
о кн а кл и е н т а .
1°
КЛЮЧЕВЫЕ
МОМЕНТЫ
ш
Метод setTimeout () создает однократный
таймер, который после завершения отсчета запуска­
ет код JavaScript.
■
Таймер, срабатывающий через заданные промежутки
времени, создается методом setlnterval ().
■
Время работы таймера указывается в миллисекун­
дах, то есть в тысячных долях секунды.
134
глава 3
Объект style элементов веб-страницы задает их
свойства, например, width и height.
Окном клиента называется часть окна браузера,
в котором отображается веб-страница.
Информация о ширине и высоте окна клиента содер­
жится в свойствах body.clientWidth и body.
clientHeight объекта document.
знакомство с браузером
îRock эволюционирует!I
Т е п е р ь о б ъ ек т iR ock ад ап ти р у ется к браузеру
п о л ьзо в ател я. Н е забудьте о б н о в и т ь ф а й л
iRock.html (его м о ж н о с к а ч а ть по адресу
http://www.headfirstlabs.com/books/hfjs/) и п р о ­
т е с т и р о в а т ь его в н еск о л ьк и х б р ау зер ах п р и
р а зн ы х р а зр е ш е н и я х эк р ан а. Вы м о ж ете п о ­
п р о б о в а ть зап у сти ть его даж е н а iP h o n e!
Т еп е р ь р а з м е р
кам еш ка м е н я е т ­
ся в з а в и с и м о с т и
о т р а з м е р о в о кн а
браузера.
П о л ь зо в а т ел и б ольш е н е п р и с ы л а ю т ж ал об , и А лен го то в дать
вам п р ем и ю . В се счастл и вы ... п о к а счастл и вы .
часзв°
ЛаДаБаеМые
-
БоЦ роСЬ!
• Я так И не понял, зачем нужно
было вычитать 100 пикселов.
: Код HTML/CSS для объекта iRock по­
мещает его изображение на 100 пикселов
ниже верхней границы страницы, чтобы
Свойства width и height
CSS-стиля позволяют менять ширину
и высоту любого объекта?
Почему не поменять размеры объ­
екта IRock в коде JavaScript в заголовке
страницы, не прибегая к событию
onload?
он не прилипал к верху окна. В вычисле­
ниях это смещение на 100 пикселов учи­
тывается до момента нахождения (90 %)
от высоты клиентского окна. Подобный
отступ нужен только для того, чтобы по­
Q l Практически так. Теперь вы мо­
жете представить, насколько мощным
инструментом управления содержимым
веб-страницы является JavaScript. В рас­
смотренном случае с его помощью вы
смогли узнать размеры окна и на основе
этих данных рассчитать размер изображе­
местить камешек на более удачное место
ния объекта.
; Дело в том, что содержимое
страницы не загружается до появления
события onload. Поэтому если ваш
код JavaScript имеет доступ к элементам
страницы, как в случае с кодом объекта
iRocl<, вы не сможете его запустить, пока
не произойдет событие
onload.
в большинстве браузеров.
далее *
135
динамическое изменение размеров
А что происходит при изменении размеров окна
браузера? Изображение сохраняет свой размер?
Нет, разм ер ка м е ш ка не является
д инам ическим .
Н е к о т о р ы е п о л ь зо в ат е л и м огут п о м е н я т ь р а зм е р о кн а
б р ау зер а, а о б ъ е к т iR ock п р и этом о с т ан е тс я тем ж е са­
мы м. В едь его р а зм е р о п р ед ел я е т с я п р и п е р в о й загрузке,
в м о м ен т с о б ы т и я o n l o a d . П о сл е это го н а вид о б ъ ек т а
уже н и ч е г о н е вл и я ет. Т о есть мы верн ул и сь к н аш ей и с­
х о д н о й пр о б л ем е;
«ее
1
136
глава 3
знакомство с браузером
Событие 0ПГе5|2е
Д ля т о го ч то б ы и зо б р а ж е н и е кам еш ка м о гл о м е н я т ь свой р а зм е р п р и и зм е н е­
н и и р а зм е р о в бр ау зер а, с ц е н а р и ю нуж но д ать п о н я т ь , ч то п р о и зо ш л о т ак о е
и зм ен ен и е . Д ля эт о й ц ел и служ ит с о б ы т и е опгез1ге.
Ч т о б ы о т в е т и т ь н а с о б ы т и е опгез1ге, и сп ользуй те
код}ауа8спр1 для атр и б у та опгез 12е т ега <Ьо<1у>.
нужно знать, когда менять размер
Возьми в руку карандаш _
г
ч
^
Решение
Какое из этих событий отличается от двух других и почему?
(^ l o a d ^
onresize
onclick
С обы т ия onresize и o n c lic k и н и ц и и р у ю т с я п о л ь зо в а т е л е м , а o n lo a d — нет .
Событие onresize для камешка
П р и ш л о в р е м я со зд ать м етод , меняю ш ;ий р а зм е р и зо б р а ж е н и я
кам еш ка. Ч т о б ы эт о п р о и с х о д и л о в о т в е т н а и зм е н ен и е р азм е­
р о в бр ау зер а, м ето д resizeRock () д о л ж ен в ы зы в а ться с о б ы т и ­
ем onresize:
В о зн и к а е т п р и и зм е н е н и и
р а з м е р о в окн а браузера.
^ В о зн и к а е т п р и пер во й
V за г р у зке ст р а н и ц ы .
<body onload="resizeRockО ; g r e e t U s e r ();" onresize="resizeRock();">
ч.
М е т о д ге^1х е к о с к () вы зы вает ся
п р и п ервой за г р у зке с т р а н и ц ы ,
заоаоая начальны е р а з м е р ы н а ­
ш его изображ ения.
\
О т вет о м на событие
мож ет с т а т ь выполнение
нескольких ф рагм ент ов
кода.
Т е п е р ь р а зм е р и зо б р а ж е н и я о б ъ е к т а 1Коск ав т о м ат и ч ес к и ме­
н я е т с я п р и и зм е н е н и и п о л ь зо в ател ем р а зм е р о в о к н а браузера.
Событие опге81ге позволяет
распознать изменение раз­
меров окна браузера и от­
реагировать на них.
138
глава 3
Т е п е р ь м е т о д гев1геЯоск()
вы зы вает ся еще и п р и
л ю д о м и зм е н е н и и р а з м е ­
р о в окн а браузера.
знакомство с браузером
1Воск- ТЬе
5адьш е
о С Ш о |^ о Ж Н Ь 1
Будьте аккурат­
ны, меняя
размер изобра­
жения при
помощи
и а у а З с п р !.
Особенно если вы увеличивае­
те маленькую картинку. Ведь
при этом ее качество может
ухудшиться.
опге81ге!
J a v a S c rip t за с е ка е т изм енение
к л и е н т а и д и н а м и ч е с ки м е н я ­
е т с о д е р ж и м о е в е б -с т р а н и ц ы
в соот вет ст вии с э т и м и зм е ­
нением .
опге81ге!
(^
^
(
^
—
Ч^
Пользователи
будут
в восторге от этого. А какие |
еще будут идеи?
у
А лен чувствует лю б о в ь со с т о р о н ы п о л ь зо в а т ел ей , ведь
т е п е р ь о б ъ ек т 1Коск н е в о с п р и и м ч и в к и зм е н ен и я м р азм е­
р о в брау зер о в. 1Коск н е т о л ь к о п о д с тр а и в а ет с я под р азм ер
к л и ен тск о го о к н а н а п ер в о м этап е, н о и д и н а м и ч е ск и
р еаги р у ет н а лю б ы е его и зм е н ен и я .
далее *
139
временный склероз браузера
Мы у)ке Встречались?
П р о б л е м ы с р а зм е р о м о б ъ е к т а 1Коск о то ш л и в п р ош л ое... т е п е р ь
реш и м , как б ы ть в ситуациях, когда п о л ь зо в ат е л ь щ ел к ает н а ка­
м еш ке н еск о л ьк о р аз, ч то б ы т о т н е чувствовал себ я од и н о к и м , и ли
в о зв р а щ ае т с я н а стр ан и ц у с кам еш ком п о сл е п ер езагр у зк и своего
ком п ью тер а.
Почему ты
меня не помнишь?
Я не произвел на тебя
впечатления?
15 уоиг п ате?
Л ю и л е р б о М ЗН йКО М С тбе
Л йм еш кол л
вводит свое им я.
О
о б ъ е к т !Я о ск о т в е ч а ­
е т п е р со н а л и зи р о в а н н ы м
п р и в е т с т в и е м — дюцжба
началась!
It is good to meet you, Paul.
■
Г ~ о к ~ Щ
What
15
уоиг п ате? -«£г
...ка м е ш е к у ж е не поаан и т п ользоват еля.
^
У
Х о тя 1Коск и в с т р еч ал с я со своим х о зя и н о м н е ­
к о т о р о е в р ем я назад, о н заб ы л его им я...
140
глава 3
знакомство с браузером
Время )кизни сценария
П о т е р я п ам яти о б ъ е к т а 1Коск св я за н а с в р ем ен ем ж и зн и
сц е н а р и я , о т к о т о р о г о за в и с и т, как и е и м е н н о д ан н ы е
х р а н я т с я в и сп ользуем ы х п ер ем ен н ы х .
В р а у зе р за г р у ж е н ,
а в о т с т р а н и ц а еще
нет . П ользоват ели)
н у ж н о у к а з а т ь ее
- ■--- •
U R L.
'fock.htm/
С т р а н и ц а за г р у ж е н а
с сервера — H T M L , CSS,
J a v a S c rip t и все ост альное.
-» М ......... ........
При закрытии браузера
или перезагрузке страницы onload!
JavaScript ликвидирует
ВСЕ переменные.
После собы т ия o n lo a d
п е р е м е н н ы м J a v a S c rip t
присваиваю т ся н а ­
чальны е значения.
С иенарш прекращ ает
свою работ у, Ja vaScrlpt
очищ ает все переменные,
и ст раница закрывается.
П ользователь закры вает
браузер или перезагруж ает
ст раницу,
Ш ТУРМ
Как бы вы решили проблему с объектом 1Роск, за­
бывающим имя пользователя?
далее *
141
к — эт о куки
Продление Времени )кизни сценария
П р о б л ем а, ко то р у ю м ы и м еем с о б ъ ек то м 1Коск, н азы в ае т ся п о ­
с т о я н с т в о . Т о ч н е е , его о тсутствие. И н о гд а нам треб ую тся д ан н ы е,
к о т о р ы е никуда н е и сч езаю т. К с о ж ал ен и ю , п е р е м е н н ы е в Jav aS crip t
ж ивут н ед о л го и ун и ч то ж аю тся п р и за к р ы т и и б р ау зер а и л и о б н о вл е­
н и и с тр ан и ц ы . В о зм о ж н о сть с о х р а н и т ь д ан н ы е д ля и сп о л ьзо в ан и я
и х даж е п о сл е п р е к р а щ е н и я р а б о т ы с ц е н а р и я р еал и зу ется с п о м о ­
щ ью т е х н о л о г и и ку к и .
Э ти м словом н а зы в а е т с я кусок дан н ы х , с о х р а н я е м ы й б раузером н а
к о м п ью те р е п о л ьзо в ател я. К уки во м н о го м н ап о м и н а ю т п ер ем ен н ы е
Jav aS crip t, н о в о т л и ч и е о т п о сл ед н и х никуда н е и сч езаю т даж е п осл е
за к р ы т и я б раузера, п ер езагр у зк и с т р ан и ц ы , вы к л ю ч е н и я ком п ью ­
т е р а и т. п. И м е н н о о н и п ом огут нам с о х р а н и т ь и м я п о л ьзо в ат е л я
в с ц е н а р и и iR ock.
П ри з а к р ы т и и окн а б р а у з е ­
р а сцен арий за п и с ы в а е т и м я
по л ьзо ва т е л я в к у к и .
^
,!.! М?
/.I
*
^ ___“ТНв
•>
П ри сле д ую щ е й з а куки
„ именем пользо­
ва т е ля б уде т п р о -
браузер управляет
н а б о р о м к у к и , создан
иых р а зл и чн ы м и веб­
ст раницам и.
Г
Ж е с т к и й диск.
142
глава 3
Б р а у зе р с о хр а н яе т к у к и
с им енем пользоват е­
ля н а ж е с т к и й ди ск его
^ом пь>ю & ^ера.
знакомство с браузером
Начало!
."EesBa®
П ри п е р в о м зн а к о м с т в е
п о л ьзо ва т е л я с о б ъ е к т о м
1К о с к и м я п о л ьзо ва т е л я
со хр а н яе т ся в п е р е м е н н о й
J a v a S c r ip t.
.
В р е м е н н ы е п е р е м е н н ы е 5ауа8спр1
зам е ч а те л ь н о сп р а в л я ю тс я с зад ач ей
в п р о ц е с с е р а б о т ы с ц е н а р и я , н о , есл и вы
х о т и т е и с п о л ь зо в ат ь их зн а ч е н и е и п о сл е
текущ ей сесси и , его нуж но с о х р а н и т ь
в ви д е куки. в н а ч а л е с ц е н а р и я п р и с в о й т е
п е р е м е н н о й зн а ч е н и е , к о т о р о е тр еб у ется
с о х р а н и т ь , а затем в м о м ен т за в е р ш е н и я
с ц е н а р и я п р и с в о й т е эт о зн а ч е н и е куки.
кймешек м о ж е т uM
пользоват ься-
^
iPaul
Конец!
«ее
mituii Ы Rocfc
переменная и куки: кт о кого
Беседа у камина
Переменная и куки обсуждают важность дли­
тельного хранения данных.
Переменная:
Куки:
я во о б щ е н е п о н и м аю , о ч ем с т о б о й р а з­
го в а р и в а т ь — ты ж е н е и м ееш ь о т н о ш ен и я
Т ы п о ч т и п рава. Я в ы п о л н я ю свою работу б ез
п ом о щ и Jav aS crip t, н о п р и этом я пом огаю
с о х р а н я т ь д ан н ы е с ц е н а р и ев надолго. А как
ты , в е р о я т н о , зн аеш ь, Jav aS crip t н е п о зв о л я е т
эт о го делать.
к J a v a S c rip t.
Я виж у, куда ты кл о н и ш ь. Т ы с ч и таеш ь м еня
м ен ее п о д х о дящ ей для х р а н е н и я д ан н ы х ,
т ак как о н и удаляю тся п р и каж дом за к р ы т и и
б р ау зер а и л и п ер езагр у зк е с т р ан и ц ы . Н о
я п р и это м о ч е н ь доступна, в о т л и ч и е о т н е ­
к о то р ы х ...
Я недоступно? Я всегда под рукой, в б раузере,
и м огу б ы ть в ы зв ан о в л ю б о й м ом ент.
Д опустим . Н о р а зв е т ы н е ж и в еш ь в тесн о м
со сед стве с м н о ж ество м д руги х куки?
Д а... и что?
Г о в о р я т , ч то о т ы ск а ть к о н к р е т н о е куки
к р а й н е слож но... вы ж е х р а н и т е с ь в ви д е
о гр о м н о го спи ска. В от ч т о я и м ел а в виду,
г о в о р я о т в о е й недо сту п н о сти .
Н у да, мы х р ан и м ся в ви д е спи ска, н о все куки
и м ею т у н и кал ьн ы е и м ен а, поэтом у о ты ск ать
нуж ное н е т а к уж слож но. Д о с та т о ч н о п о ­
н и м ать, как р а зб и т ь сп и со к н а ч асти и н ай ти
в нем к о н к р е т н о е имя.
Возьми в руку карандаш,
РбШ бН Иб
какие еще данные веб-страниц имеет смысл сохранять при
помощи куки.
с о д е р ж и м о е ко р зи н ы п о к у п о к , м е с т о ж и т е л ь с т в а , язык.
144
глава 3
знакомство с браузером
Переменная:
Куки:
А я в о т н е участвую н и в как и х списках. Д о ­
с т ат о ч н о н азв ать м о е им я... я и тут!
П р и всех св о и х д о ст о и н с тв а х п о с т о я н с т в о
не р е ш а е т каж до д н евн ы х пр о б л ем . Если
подум ать, то д ал ек о н е все д ан н ы е нуж но
со х р а н я т ь надолго. Б о л е е э ф ф е к т и в н о х р а ­
н и ть и х н е к о т о р о е вр ем я, а п о то м , за в ер ш и в
работу, удалять. В от тут н а сцену вы хож у
я - в р е м е н н а я ср ед а х р а н е н и я для д ан н ы х
сц е н а р и я.
В от т о л ь к о в сп о м н и , каким о б р азо м все эти
т о в а р ы и зн а ч а л ь н о о к азал и сь в ко р зи н е?
Ведь и м ен н о я х р а н ю врем енную и н ф о р м а ­
ци ю о п р ед л агаем ы х то в а р ах . Я в аж н а так
ж е, как и ты ... а м о ж ет б ы ть даж е больш е.
Д аж е н е с м о т р я н а с т р ем л е н и е б ы ст р о заб ы ­
вать д ан н ы е, с к о т о р ы м и рабо таю .
я п о н я л о ваш у точку зр е н и я . З а т о , когд а во
м н е с о х р а н я ю т и н ф о р м а ц и ю , я ее д ей с тв и ­
т е л ь н о зап ом и н аю . Н е важ н о, бы л л и за к р ы т
б р ау зер и л и о б н о в л е н а стр ан и ц а. Я вечн о...
до т е х п о р , п о к а п о л ьзо в а т ел ь н е р е ш и т п о ­
ч и с т и т ь куки. Н о это уже д ругой во п р о с.
Я все р ав н о убеж ден о, ч т о т ы н ед о о ц ен и в а­
еш ь важ н о сть д о л го в р е м ен н о го х р а н е н и я
дан ны х. Р азве н е в о с х и т и т ел ьн о , когд а п о ­
сле д олгого в р е м е н и п о л ьзо в ат ел ь зах о д и т
в и н тер н ет-м агази н и ви д и т, ч то все в ы ­
б р ан н ы е им р а н е е т о в а р ы все еш;е н ах о д ятся
в его ко р зи н е? И все эт о б л аго д ар я мне.
М не н а ч и н а е т казаться, ч т о м ы д о п о л н я е м
друг друга. А ведь я всегда сч и тал а те б я за­
кл я ты м врагом .
Д умаю , т ы право . М ы р еш аем р а зн ы е зад ач и
и д ел и ть нам н еч его . Х о тя д о л ж н а зам ети ть ,
ч т о я п р е д п о ч и т а ю л е гк и й доступ ко м не в о з­
м о ж н о сти п е р м а н е н тн о го х р а н е н и я дан ны х.
А я и сп ы ты в аю у д овольстви е о т м ы сли, что,
как т о л ь к о с т р а н и ц а будет п ер евер н у та, вы
забудете весь наш р а зго во р .
К ак о й разго во р ?
Ну, ч т о я говори л о?
далее ►
145
хранение куки на стороне клиента
А почему нельзя хра­
нить долговременные
данные на сервере?
Для сохранения небольших ф рагментов
инф ормации, например имени пользователя,
сервер не нуж ен.
Р азум еется, с е р в е р м о ж ет и сп о л ьзо в ат ьс я как д о л го в р е­
м ен н о е х р а н и л и щ е д ан н ы х, н о с к о р о о н о к аж ется п е р е п о л ­
н ен м ал ен ьки м и ф р а гм е н т а м и и н ф о р м а ц и и . С о х р а н ен и е
д ан н ы х н а с е р в е р е т р еб у ет р а б о т ы п р о гр ам м и с т о в и сп е­
ц и а л ь н о й ср еды , н а п р и м е р б азы д ан н ы х. Вам н е каж ется,
ч то эт о слиш ком б ольш ая р а б о т а для с о х р а н е н и я , н а п р и ­
м ер , и м е н и п о л ь зо в ат ел я в с ц е н а р и и 1Коск?
Куки с о х р а н я ю т д ан н ы е н а с т о р о н е кл и ен та, н и к ак н е
за т р а ги в а я се р в е р . П р и этом п о л ьзо в а тел ь всегда и м еет
в о зм о ж н о с ть удали ть куки со сво его к о м п ью тер а, есл и он
р еш и л , ч т о эт а и н ф о р м а ц и я ему больш е н е требуется. Т а­
ко е п р о с т о е уд ален и е д ан н ы х с с е р в е р а н ев о зм о ж н о .
Лауа8спр1
146
глава 3
Долговременное
хранение данных
на стороне оиента!
знакомство с браузером
CBoucmBa kyku
Куки с о х р а н я ю т м ал ен ьк и е ф р а гм е н ­
т ы д ан н ы х под у н и кал ьн ы м и и м ен ам и ,
п о ч т и к ак п е р е м е н н ы е. Н о , в о т л и ч и е о т
п ер ем ен н ы х , у куки есть с р о к х р а н е н и я .
П о сл е его д о ст и ж е н и я куки у н и ч то ж аю т­
ся. Т а к ч то куки н е я в л яю тся веч н ы м и ,
о н и п р о с т о ж ивут н ам н о го дольше п е р е ­
м ен н ы х . М ож н о со зд ать куки, н е им ею ­
щ ие с р о к а х р а н е н и я , н о в это м случае
о н и будут, как и п е р е м е н н ы е Jav aS crip t,
с т и р а ть ся п о сл е за к р ы т и я браузера.
имя
( Уникальное имя куки.
Значение
u s e rN a m e = P a u l
И стекает 3/9/2009
хранения
После ист ечения срока х р а ­
нения куки удаляются.
Куки с о х р а н я ю т с я н а к о м п ь ю т е р е п о л ь ­
зо в а т е л я в виде д л и н н о й с т р о к и текста,
с в я за н н о й с сай то м (и ли д о м ен о м ). Д руг
о т друга о н и о тд ел я ю тся т о ч к о й с за п я ­
т о й (;). И м е н н о э т о т р а зд ел и те л ь д ает
во зм о ж н о с ть н а й т и в сп и ск е к о н к р е т ­
н ы й куки.
Зуду
в а м и данные.
,od®
л"»-
С охраненное в к у к и значение
lang = fr_ca
И стекает 6/25/2010
cartlD = 1103
И стекает 11/4/2008
ф
ite m i = F lat panel television
И стекает 9/3/2008
Ж
'
Т ак как все куки х р а н я т с я в одном м есте, п о и ск к о н ­
к р е т н о г о куки т р еб у ет уси л и й , н о сущ ествую т м ето ­
ды , о б л егч аю щ и е ч те н и е , зап и сь и уд ален и е куки...
readCookieO
eraseCookieO
writeCookie О
далее ►
147
куки при помощи JavaScript
°щоБый к°Д
Если вы не поним ает е
смысл написанного, ни­
чего страшного. По мере
чтения книги все п о ст е­
пенно ст а нет ясно.
В от код т р е х в сп о м о гател ьн ы х м етод ов, п р е д н а зн ач е н н ы х
для ч т е н и я , за п и си и уд ален и я куки. И н о гд а п р ав и л ь н ее — за­
с т ав и ть р а б о т а т ь других. П оэтом у во зьм и те э т о т р е ц е п т (его
м о ж н о с к а ч а ть по адресу кир://гтт).кеа(1/гг5иаЬз.сот/ЬооЬ/Ь/]$/)
и и сп о льзу й те его для р а б о т ы с куки.
f f
х р /я н е н и я
_^аписы вает -
function writeCookie(name,
//
value,
days)
f e ju d e числа
которые
должны су щ есі^воват ь куки.
{
no умолчанию к у к и я в л я ю т с я временными,
не имея ср о к а хранени
var expires =
//
if
Указав число дней,
вы с д е л а е т е к у к и п о с т о я н н ы м и
(days) {
v a r d a t e = new D a t e O ;
* cn
d a t e . s e tT im e ( d a te .g e tT im e O
+ ( d a y s * 24
60
60
expires =
expires=" + date.toG M TStringO ;
Срок хранения
вычисляется
'^ре.оёразовани ем числа дней
о миллисекунды
и добавлением п о ­
лученного чис­
ла к т екущ ем у
оремени.
1000));
}
// П р и с в о и м куки имя,
d o c u m e n t .
значение и срок хранения
c o o k i e = n a me + " = " + v a l u e
+ expires
+
path= /";
}
f u n c t io n readCookie(name) {
/ / Н а йд е м к о н к р е т н ы й к у к и и в е р н е м
v a r s e a r c h N a m e = n a me +
v a r cookies = docum ent. c o o k ie . s p l i t ( ' ; ' ) ;
f o r ( v a r i= 0 ; і < c o o k i e s . l e n g t h ; І++) {
var с = cookies[і];
w h i l e ( c . c h a r A t ( O ) == ' ' )
с = с . s u b s t r i n g (1, с . l e n g t h ) ;
i f ( c . i n d e x O f ( s e a r c h N a m e ) == 0)
r e tu r n c . s u b s t r i n g (searchN am e.length,
Разделит ель
точка с з а ­
пят ой делит
список куки на
отдельные э к ­
земпляры .
c.length)
}
return null;
}
fu n c tio n eraseCookie(nam e) {
/ / Удалим выбранный к у к и
- 1)
w riteCookie(nam e.
var x;
ЩГ yt
ШтісЬіоп doXOI
}
eunctio« doYO
Дая удаления куки достаточно
cookie.js
148
глава 3
Создайте пуст ой ф айл
с им енем cookie.js
и добавьте в него
э т о т код.
]
Разрешение .js
указы вает , что
ф айл содержит
т олько код
JavaScript.
знакомство с браузером
Код JavaScript ВНЕ Веб-страницы
С о х р а н е н н ы й в о т д е л ь н ы й ф а й л код Jav aS crip t тр еб у ется и м п о р т и ­
р о в а т ь н а стран и ц у, для к о т о р о й о н п р е д н а зн а ч е н . С о о т в е тс т в ен ­
но, ф а й л cookie.j s нуж но импортировать на стр ан и ц у iRock.html.
Э то р еал и зу ется в теге <script>:
Не забудьт е закры т ь
его т&гоАЛ </scn pt> .
<script type="text/javascript" src="cookie. js"X/script>
Для JavaScript знамение
^ м я файла с кодом
сценария обычно з а ­
канчивается на
a m p u S y m a t y p e всегда
равно text/ja va scrip t.
, д
Д л я и м п о р т а н а стр ан и ц у кода JavaScript и з ф а й л а и сп ользуйте
<script>. М н о го к р атн о и сп ользуем ы е сц е н а р и и всегда
и м е е т см ы сл п о м ещ ать в о т д ел ьн ы й ф ай л и п о то м п р о с т о им п о р т и р о в а т ь в веб-страницу,
I'Rock h tm l
T y ^ e d u m e c t, ч т о ф а й л
cookie.js на хо ди т ся в т о й
ж е п а п ке .
<htinl> ~
<head>
’
« itle > « o c k
------- — -— ....
* "
-
а ,
~
------ ---------------------— ....___ __
R o c k < / u t l. >
;< s c r ip t t № e = " S 7 ja v ^ 3 c r ip t : . - - s r c = " ^
.............................
; ..............................................................
^ ° ° ^ ie o s - - X /s c r ip t> -
.........................
f u n c t io n r e s i z e R o c k о i
d o c u m e n t. g e tE le m e n f RvTw /(d o c u m e n t.b o d y c l i L f H
J
У- l e n t H e i g h t - 100)
function greetUserо
ИМпортировансценарий
помещается на
. h e ig h t =
* 0 .9 ;
стрлнмцу
загрузке.
ее
I
Как ВЫ считаете, почему многократно используемый код имеет смысл помещать в отдель­
ный файл?
далее ►
149
пользователь хочет к у ш ?
Почему код многократного использования имеет смысл поместить в отдельный файл?
пражнение
г 2Ш2НУ12
к й к п р и н е о б хо ди м о ст и его м о ж н о б уд е т легко о т р е д а кт и р о в а т ь .
Приветствие пользователя
u se rN am e = Paul
Истекает 3/9/2009
Н ам нуж на н о в а я в е р с и я с ц е н а р и я 1Коск, в к о т о р о й
п е р с о н а л и з и р о в а н н о е п р и в е т с т в и е п о л ьзо в ат ел я
р еал и зу ется н а о сн о в е п р е д п о л о ж е н и я , ч т о его и м я
уже с о х р а н е н о в куки. В п р о т и в н о м случае п о я в л я е тс я
о б ы ч н о е , не л и ч н о с т н о е п р и в е тс т в и е .
П рочит аем им я
п о л ьзо ва т е л я из
куки и сохраним
его в пе р е м е н н о й .
Переменная
J a v a S c r^ p t.
userName =
Это имя пользователя?
Здесь б уд е т или и м я
пользоват еля... или
ничего!
П ерсональное
привет ст вие
О бщ ая ф о р м а
У
(
Hello, I am your p e t rock.
sir«"
150
глава 3
знакомство с браузером
Ц о Д |э о б Н о HJ>o К ° Д -
К ц к и , хранящ ее и н ф о р м а ц и ю
и м е н и п о л ьзо ва т е л я, долж но
и м е т ь зн а ч и м о е им я. Э т о и з о ^о и т вас о т п у т а н и ц ы , если
в б уд ущ е м вы р е ш и т е добавит ь
оругие к у к и в данный сценарий.
00
М е т о д g re e tU s e rO о т в е ч а е т за
п р и в е т с т в и е пользо ва т е ля п р и
перво й за гр узке ст р а н и ц ы .
Э т о не слож ение.
function greetUser
■э т о соединение
userName = readCookie ("irock_username" ) ;^
ст рок.
if (userName)
^
alert("Hello " + userName + ", I missed you.");
else
a l e r t ('Hello, I am your pet rock.');
И м я п о льзова т е ля
<^итается из кц ки
‘^ ^ Р л н и т с я в п е р е ­
м ен н о й u se rN a m e
Т1ри наличии к у к и с и м е ­
н е м п о л ьзо ва т е л я п о к а ж е м
ет. п о т о м у
д
а
Х
1
что
Х
е
«" S
не
а
»
“ ' ’ “'®“ " “
" f '“ -
ф орме.
Memog greetUserl) иа осиоВе kyku
Т е п е р ь в м ето д е greetUser {) р а б о т а ю т дуэтом и п е р е м е н н ая ,
и куки. И м я п о л ьзо в а т е л я ч и т а е т с я и з куки и с о х р а н я е тс я в п е р е ­
м ен н о й . Н о н а т о т ф акт, ч т о и м я с о х р а н е н о в куки, п о л агаться
н ел ьзя , в к о н ц е ко н ц о в, с ц е н а р и й м о ж ет запускаться в п е р в ы й
раз, зн а ч и т , п о л ь зо в а те л ь ещ е н е указы вал св о и х л и ч н ы х дан н ы х.
И м е н н о по это м у в коде п р о в е р я е т с я в о зм о ж н о сть для п е р е м е н ­
н о й по л у ч и ть и м я и з куки, и н а о сн о в е э т о й п р о в е р к и в ы б и р а е тс я
нуж ны й т и п п р и в е тс т в и я .
далее ►
151
Ну-ка посмотрим
Создание куки
И с п о л ь зо в а т ь куки для н аш его о б ъ е к т а 1Коск —о т л и ч н а я и д ея, н о сн ач а­
л а и х тр еб у ется создать. З а п и с ь куки осущ ествим в м етод е 1 о и с Ь К о с к () ,
к о т о р ы й в ы зы в а е тс я п р и щ ел ч ке п о л ь зо в а т е л я н а кам еш ке. К ак вы
п о м н и т е, эт о т м ето д п р ед л агает п о л ьзо в ател ю вв ес ти его и м я —т е п е р ь
о н будет ещ е и за п и с ы в а т ь куки п о сл е вво д а э т о й и н ф о р м а ц и и .
Но
Если и м я не
у к а за н о , его
нужно узнать.
ли
Если и м я у к а з а н о , п о б л а го д а р и м
ш л ь з о в а т е л я за в ним ание.
function touchRockO {
^ if (userName) {
^
alertC'I like the attention, " + userName + ". Thank you.");
}
else {
userName = prompt("What is your name?", "Enter your name here.");
if (userName) {
У бедит есь,
alert ("It is good to meet you, " + userName + ".");
чт о им я
writeCookie("irock_username", userName, 5 * 365);
введено.
}
K~
^
к
}
document.getfelementByldV"rocklmg") .src\ = "rock_happy.png";
setTimeout ("nocument.getElementByld ('roNcklmg') .src = 'rock, png
5 *
60
*
/OOO)
}
И м я имеет ся, п о ­
эт ому попривет ­
ст вуйт е пользова­
т ел я и за п и ш и т е
его данные в к у ки .
И менно эт о им я
использует ся при
чт ении куки. К у к и
не и с п о л ь з у ю т
С т и льВ е р блю д а , они
больш е н а п о м и н а ю т
идент иф икат оры
Н ТМ Ь.
И м я пользоват е­
ля за пи сы ва е т ся
из пер е м е нно й .
/Г
< im g
152
глава 3
id = " r o c k Im g "
s rc = " ro c k .p n g "
С охраним куки
с именем п о л ь­
зо ва т е ля на
^ лет .
Э т о т м е т о д в ы зы ­
вает ся п р и щ елчке
на ка м е ш ке .
o n c lic k = " t o u c h R o c k ( ) ; "
/>
знакомство с браузером
onclick!
П ользоват ель
щ & лкает на
объ ект е iR o ck
В б о л ьш и н ств е случаев м етод to u c h R o c k () и г р а е т р о л ь,
п р о ти во п о л о ж н у ю р о л и м етод а g r e e t U s e r ( ) , по к р а й н е й
м ер е, с т о ч к и зр е н и я куки. И м я ввод и тся п о л ьзо вател ем , со­
х р а н я е т с я в п е р е м е н н о й и затем зап и с ы в а ет ся в куки.
пользователя известно?
'
Ч
What is your name?
Paul
С охраняем и м я п о л ь з о ­
ват еля в пе р е м е н н о й .
userName =
"Paul"
З а п и сы ва е м
перем енную
в к у ки .
М е н я е м изображ ение
ч у ё ы п р и в е с т и iR o ck
о счаст ливое
сост ояние.
It is good to meet you, Paul.
f
далее >
153
руки прочь от куки
Влияние на безопасность
^уд ьш е
Б о л ь ш и н ств о п о л ь зо в а т е л е й о б ъ е к т а 1Коск в в о с т о р ге от
та к о го л е к а р с т в а п р о т и в скл ер о за, как куки, н о н е к о т о р ы е
и з н и х о за б о ч е н ы в о п р о с о м б езо п асн о сти . Э то п р ав и л ь н ы й
во п р о с, так как в куки ч ас т о со х р а н я ю т п е р с о н а л ь н ы е д ан н ы е,
х о т я и не ставят под угрозу б езо п асн о сть... по м ен ьш ей м ер е
в п л ан е д оступа к х р ан я щ и м ся н а ваш ем к о м п ью тер е уязви ­
мы м д ан ны м . Н о сам и п о себ е куки н е я в л яю тся б езоп асн ы м
сп осо б о м х р а н е н и я и н ф о р м а ц и и , п о это м у с о х р а н я т ь с и х п о ­
м ощ ью уязвимые д ан н ы е н е сто и т.
оС Ш ороЖ Н Ь!
То, ЧТО ВЫ
можете, не
означает, что
вы должны.
Хотя в куки
можно сохранить что угод­
но, они являются не слишком
безопасным способом хране­
ния данных. Поэтому уязви­
мые данные, например пароль
пользователя, таким спосо­
бом сохранять не стоит.
Куки — это всего лишь ф раг­
менты текстовой инф ормации,
сохраняемой к вам на ком­
пьютер.
■ Л **
Не являясь исполняемы ми
Хотя куки и хранят­
ся на ж естко м диске,
они не имею т доступа
программами, куки не могут
стать источником вирусов
или червей.
к остальной хранящ ейся там инф ормации.
;
Черви... ф у !
154
глава 3
Куки могут сохранять персональны е
данны е, но только после того, ка к
пользователь сознательно у ка за л
их на веб-странице.
знакомство с браузером
Часщо
"^ а Д а Б а е М ы е
БоП роС ь!
То есть куки всегда сохраняются
на жесткий диск компьютера?
! Нет. Просто большинство браузеров
сохраняет куки именно на жесткий диск,
Но при этом есть и браузеры, которые
не имеют туда доступа. К примеру,
некоторые мобильные устройства
используют для этого специальную
память. При этом с точки зрения браузера
(и сценария) куки помнят присвоенные им
значения вне зависимости от того, куда
они были сохранены.
Как понять, что куки имеют
уникальные имена?
0 » Уникальность имени нужна для куки
только в пределах рассматриваемой
страницы, ведь они сохраняются
со ссылкой на нее. Таким образом,
эффективной частью имени куки является
название страницы, что гарантирует его
уникальность.
J'
Куки сохраняются для всех
браузеров?
Q * Нет. Каждый браузер имеет свою,
уникальную базу куки. То есть куки,
созданные в Internet Explorer, не будут
видимы в Firefox или Opera.
Имея куки, зачем вообще
сохранять данные на сервер?
Q * Ну, во-первых, куки позволяют
сохранять только относительно
небольшие (менее 4 Кбайт) фрагменты
текста. Это одно из их самых больших
ограничений. Кроме того, куки
недостаточно эффективны, и вряд ли
вы захотите постоянно записывать
и читать оттуда данные. Для подобных
целей обычно используются базы
данных, которые находятся именно
на серверах. Несмотря на то что куки
прекрасно подходят для сохранения
небольших фрагментов информации,
которые необязательно помещать
в базу на сервере, они не помогут вам
в случаях с другими видами данных.
Также их не стоит применять для
сохранения уязвимых данных, так как это
небезопасно.
Можно ли создавать
действительно вечные куки?
0 » Нет. Нравится вам это или нет,
все куки имеют срок действия. Они
предназначены для достаточно
длительного хранения данных, но
никто не предполагал использовать их
в качестве вечного хранилища. Куки
хранят данные дни, недели, месяцы. Для
более длительного хранения данные
стоит поместить на сервер. Нет, куки
тоже потенциально могут хранить данные
годами, но пользователи обновляют
компьютеры, переустанавливают
браузеры и т. п.
Какие недостатки есть у хранения
кода иауаЗспр! во внешнем файле?
0 » Недостатков нет. Просто следует
помнить, что целью сохранения сценария
во внешний файл является доступ к нему
из нескольких источников. Если ваш
сценарий появляется всего на одной
странице, нет никакого смысла сохранять
его во внешний файл. Ну разве что только
в случаях, когда код выглядит запутанным
и вы хотите упростить его, распределив
сценарии по отдельным файлам.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
Куки — это фрагменты текстовых данных, которые
браузер сохраняет на компьютер пользователя.
Поместив сценарий во внешний файл, вы сделаете
его доступным для других страниц.
Куки позволяют сценариям сохранять данные,
которые могут потребоваться в следующей сессии.
Куки не имеют доступа к жесткому диску пользо­
вателя и не распространяют вирусы, они просто
сохраняют введенные пользователем на страницу
персональные данные.
Все куки имеют срок хранения, после истечения
которого они уничтожаются браузером.
далее *
155
вам куки не положены
Мир без куки
П о п р и ч и н а м б езо п а с н о с т и и л и из-за о г р а н и ч е н и й б р ау зер о в
н е к о т о р ы е п о л ьзо в а т е л и о б ъ е к т а 1Коск н е м огут с н и м р аб о тать,
т а к как у н и х за п р е щ е н ы куки. Э то б о льш ая п р о б л ем а, т а к как
1Коск бы л созд ан в п р е д п о л о ж е н и и , ч т о куки п о д д ер ж и ваю тся
везде. П о к р а й н е й м ер е, нуж но д ать п о н я т ь п о л ьзо вател ям , ч то
о н и н е и м ею т д оступа ко всем ф у н кц и ям о б ъ е к т а 1Коск.
Уменьшение количе­
ства пользователей —
это недопустимо.
Проблема!
+
Неработающи(
К счастью , б р ау зер ы могут п р о в е р я т ь д о сту п н ость куки.
С во й ств о cookieEnabled п р и н а д л е ж и т об ъекту navigator,
п ред о ставл яю щ ем у Jav aS crip t и н ф о р м а ц и ю о б раузере.
navigator.cookieEnabled
Если к у к и
дост упны J
ж изнь п р е ­
красна.
156
глава 3
tru e
false
Вы не м о ж е т е
чит ат ь и за­
писы ват ь к у к и ,
если к ним н е т
дост у>лл.
знакомство с браузером
возьми в руку карандаш
Напишите недостающий код для проверки доступности
куки в методах greetUser {) и touchRock {). В метод
touchRock () также добавьте код, сообщающий пользовате­
лю о недоступности куки.
function greetUserо
{
userName - readCookie{"irock_username");
if (userName)
alert ("Hello " + userName -i- ", I missed you ")•
else
alert ('Hello,
I am your pet rock.');
)
function touchRockO
if (userName) {
{
^ alert ("I like the attention,
" + userName + ". Thank you.");
else {
alert ("It IS good to meet you, " + userName + ".");
writeCookie ("irock_username", userName, 5 * Зб'ь')"-"
else
d o c u m e n t . g e t E l e m e n t B y l d ( " r o c k l m g " ) . s r c = " r o c k h a p p y .p n g " s e t T i m e o u t ( - 'd o c u m e n t . g e t E l e m e n t B y l d ( 'r o c k l m g ') . s r c = ' r o c k , p n g ' ;
далее >
157
решение упражнения
возьми в руку карандаш_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
^бШ бНИб
должен выглядеть код, проверяющий поддержку куки
для методов greetUser () и touchRock (), а также код
для второго метода, дающий пользователю понять, что куки
недоступны.
Если куки поддерж иваю т сяпрочит айт е
имя пользоват еля из куки iRock.
function greetUserО
{
if (navigator.cookieEnableo
userName = readCookie("irock_username");
if (userName)
alert("Hello " + userName + ", I missed you.");
else
alert('Hello, I am your pet rock.');
}
function touchRockO {
if (userName) {
alert("I like the attention, " + userName + ". Thank you ")•
}
else {
userName = prompt("What is your name?", "Enter your name here.");
if (userName) {
r-,,
1 4- /МТ4- ■
,
Если куки поддерalert( It is good to meet you, " + userName + "."); ж иваются, за п и ...— —
---------— -----uAume куки с uMi
if (n a vig a to r.co o kieE n a b lec^:;--''''''^
кем пользоват е/
writeCookie("irock_username", userName, 5 * 365);
else
alertC 'Sorry. Cookies a ren ’t sup p o rted /en a b led in uour brow ser I w on’t
}
■f'em-ember -y o u -in te r. ............................................... ■•■ .................. . ............................. .
\
J
/\a u m e пользоват елю знат ь,
чт о от сут ст ви е куки ограни-
d o c u m e n t . g e t E l e m e n t B y l d l - r o c k l m g " ) .src - ~
setTimeout("document.getElementByld('rocklmg').src = 'r o c k . p n g ,
5 * 60 * 1000);
}
на
выше, и п р о т ест и р уй т е полу
ченнмы результ ат .
158
глава 3
знакомство с браузером
ЧэсЗЦо
Задаваем ы е
БоЦ роС ы
Зависит ли поддержка куки от типа или версии браузера?
Q ; Распознавание типа и версии браузера в данном случае ведет к непредска­
зуемым результатам. К сожалению, верить тому, что сообщают о себе браузеры,
нельзя. Поэтому, чтобы проверить, поддерживаются ли куки, используйте свойство
navigator.cookieEnabled.
Разговор с пользователями... это лучше,
чем ничего
Е сли куки н едоступ ны , и с п р а в и ть ситуацию н ел ьзя. Н о по к р а й ­
н е й м е р е и м е е т см ы сл со о б щ и ть п о л ьзо в ател ям о и м ею щ ей ся
п р о б л ем е.
е в 0
iRock - The Virtual Pet Rock
О
Cookies aren't supported/enabied tn your browser, which
means I won't remember you later. I'm sorry.
Гч"
f
Ален сноба
доволен... м
п о л у ч м л к е,1Ме,
оЭин чек-
далее *■
159
играем с îRock 2.0
iRock — король иауаЗспр!
Вы п р и л о ж и л и м н о ж еств о у силий , со в ер ш ен ству я код сц е­
н а р и я и вн о ся в н его все н ео б х о д и м ы е для успеха о б ъ ек т а
1Яоск и зм е н ен и я . Б л аго д ар я о тзы в ам п о л ь зо в ат ел е й 1Коск
п р и о б р е л больш ую эм о ц и о н а л ьн о с ть , в о зм о ж н о с ть м ен я ть
сво й р а зм е р и даж е улучш ил пам ять!
Параметры бра­
узера и свой­
ства CSS даю т
объекту ÎRock
возможность
подстраиваться
под среду.
Тайм еры расш ирили
эм оциональны й д и а­
п а з о н о б ъ е к т а ÎR o c k .
Жмк - Ths Vimalfet «оск
Спасибо за вашу
тяжелую работу, !Коск
теперь твердокаменный
домашний любимец.
u serName = "Paul
160
глава 3
Куки позволяют
объекту iRock помнить данны е д аж е
после заверш ения
сценария.
О
знакомство с браузером
Г
7 ';1
С огни те стран ицу
по верти кали , ч тоб ы
с о в м е с т и т ь д в а м о зг а
и р е ш и т ь задачу.
^
Вкладка
Почему JavaScript должен заботиться
о клиенте?
Ь-- -хо|>оШо, а ДВа ЯуЧШе!
------------------------- -
Клиент — это место запуска кода 1ауа8спр1,
то есть Дауа8спр1 связан
с браузером. Это хорошая новость,
потому что в результате серверу
не приходится сохранять 1Ц1«и!
]=ч»няп1ие решений
%
^
Если на дороге развилка...
Жизнь неотделима от принятия решений. Стоять или
идти, пойти
на сделку с негодяем или пойти в суд... Результата невозможно добиться без
выбора. То же самое происходит в иауаЗспр1 — вам приходится выбирать
между различными вариантами сценария. Приходится то и дело при­
нимать р е ш е н и я - Стоит ли поверить данным, введенным пользователем,
и отправить его охотиться на львов? Или же проверить еще раз, может быть,
он всего лишь пытался заказать билет до Львова? Выбор за вами!
выбери меня
Счастливчик, спускайся ко мне!
в сего дн яш н ем эп и зо д е зах ваты ваю щ его шоу «Заклю чи м
сделку?» мы в ы б ер ем у ч астн и ка, ко то р о м у ул ы б н ется удача.
Удачливый участник
Эрмк
В е дущ и й игрового
ш оу.
Н е со м н ев аем ся, ч то вы уже п о д п р ы ги в ае т е
н а стуле в пред вкуш ен и и д ем о н с тр а ц и и Э р и ­
ком ум ен и я закл ю ч ать сделки. Н о в о т какой
во п р о с: п очем у ведущ ий шоу вы б р ал и м ен н о
Э рика?
164
глава 4
принятие решении
Выбор — это принятие решения
Все п р о с то . И м я Э р и к а б ы ло н а п и с а н о н а кар то ч ке! О б р а т и т е вн и м ан и е
на то , ч т о ф а к т п р и н я т и я ведущ им р е ш е н и я н а о сн о в е зап и сан н ы х н а
ка р т о ч к а х и м ен вы п р и н я л и как д о лж н о е. Ведь о н ч ел о век , а л ю ди ум ею т
о б р аб а т ы в ат ь и н ф о р м а ц и ю и п р и н и м а т ь р е ш ен и я . А во т есл и б ы о н бы л
сц ен ар и ем ...
В от ведь как о й во п р о с: каки м о б р азо м с ц е н а р и й м о ж е т ис­
п о л ь зо в а ть ф р а гм е н т ы и н ф о р м а ц и и в кач е с тв е о сн о в ы для
д ей стви й ? У знать, ч ье и м я п о я в и т с я н а в ы б р а н н о й к ар т о ч к е , —
то л ь к о п о л о в и н а дела. А ведь нуж но ещ е и о ц е н и т ь п р о ч и т а н ­
н о е и в ы б р ат ь у ч астн и ка с ан ал о ги ч н ы м им енем .
далее ►
165
если нужно решение
«если» так, то сделай что-нибудь
Н а сам ом дел е Jav aS crip t у м еет о б р аб а т ы в ат ь и н ф о р м а ц и ю
и п р и н и м а т ь р е ш е н и я и д ел ает это , н а п р и м ер , п р и п ом ощ и
оператора
. Э то т о п е р а т о р запускает к o д Jav aS crip t по резуль­
татам п р о в е р к и какого-либо условия.
11 (п р о в е р к а
Д е л а е м что-то;
Е сли взглянуть н а п р и м е р с и гр о в ы м ш оу с т о ч к и зр е н и я о п е р а ­
тора
, вы п о л уч и те следую щ ий код:
П роверим , совпадаю т
ли два э л е м е н т а .
Совпадение!
Brie
if (chosenContestant == "Eric")
alert("Eric, come on down!");
а „
П р о ве р ка условия бсегт
за к л ю ч а е т с я о скобки.
1
I
I
/
/
/
конец о п е р а т о р а .
п о э т о м у т о ч к а с за п я т о й не
ст а в и т с я .
А в о т э т о конец
операт ора.
Оператор if запускает \
фрагмент кода по
результатам проверки
условия.
166
глава 4
_____
Eric, come on down!
принятие решений
Оператор if
О п е р а т о р 1 £ всегда и м еет о д и н и т о т ж е си н так ­
сис. Вы уже п о зн а к о м и л и с ь с н и м , д о б ав и в куки
к об ъ екту iR ock, н о н а в с я к и й случай сделаем его
п о д р о б н ы й анализ:
Э т о т ко д Д О Л Ж Е Н
о е р н у т ь значение
~~ triAe или false.
Проверка условия
if
У
а
Оператор
О т с т у п ы о блегча ю т чт ение
кода. Н а пи са н н ы й с о т с т и п о м
о п е р а т о р являет ся ч а с т ь ю
операт ора
В о т ч то следует зн а т ь об о п е р а т о р е i f . В о-первы х, запустить
м о ж н о т о л ь к о од и н ф р а гм е н т кода, к о т о р ы й п и ш ется с отсту­
пом сразу под п р о в е р к о й условия. О тступ н е я в л я е т с я о б я за ­
т ел ьн ы м т р е б о в а н и е м , н о о н п о зв о л я е т о п р е д ел и ть, ч т о в т о р а я
с т р о ч к а т а к ж е о т н о с и т с я к о п е р а т о р у ± f. В от о сн о в н ы е п р и н ­
ц и п ы н а п и са н и я эт о го о п ер ат о р а :
П р о в е р я е м о е условие закл ю ч ается в скобки.
О тступ н а пару п р о б е л о в во в т о р о й стр о ч к е.
К од, запускаем ы й в случае со б л ю д ен и я условия.
У праж нение
Укажите, какие действия должны следовать за каждым из операторов ±±.
i f (hungry)
numDonuts *= 12;
i f (countDown == 0)
userName = r e a d C o o k i e ( " i r o c l i _ u s e r n a m e " ) ;
i f (donutString.indexOf("dozen")
!= -1)
a w a r d P r i z e () ;
i f ( t e s t S c o r e > 90)
g oE a t ( ) ;
i f (Iguilty)
a l e r t ( " H o u s t o n , we ha ve l i f t - o f f . " ) ;
i f (winner)
a le r t( " S h e 's innocent!");
i f ( n a v i g a t o r . cookieEnabled)
g r a d e = "A";
далее >
167
решение упражнения
Вот какие действия должны следовать за каждым из операторов
ажнение
угш гш г
Равно tr u e , если с т р о к а с о д е р ж и т с л о ­
во " d o z e n " (д ю ж и н а ).
i f (hungry)
numDonuts *= 12;
i f (countDown == 0)
userName = r e a d C o o k i e ( " i r o c k _ u s e r n a m e " ) ,
i f ( d o n u t S t r i n g . i n d e x O f ( "dozen' ' )
!= - 1 ) -
a w a r d P r i z e ();
i f ( t e s t S c o r e > 90)
g o E a t ();
if
(Iguilty)
a l e r t ( " H o u s t o n , we ha ve l i f t - o f f . " ) ;
''i f
(winner )
a l e r t ("She's in n o c e n t!" );
( n a v i g a t o r . cookieEnabled)
g r a d e = "A";
if
Ig u ilty ознйЧйбт. H E g u ilt y ,
т о е ст ь п а р а м е т р g u ilt y
и м е е т значение false.
И м е е т значение tr u e , если
в бр а узе р е вкльочсил п о д д с р ж ка к у к и .
А что делать, ЕСЛИ
вариантов несколько?
О
Д елайте это... или вот то.
С т о и т вам подум ать, ч то т е м а р ас к р ы т а , к ак п о я в л я е тс я
н е ч т о вы х о д ящ ее и з р я д а вон. Х отя в ситуац и и , когда
п р и х о д и тс я в ы б и р а ть и з н еск о л ьк и х в ар и а н т о в , н е т н и ­
ч его эк с тр а о р д и н ар н о го ... Ш о к о л ад н о е и л и в ан и л ьн о е,
б ез к о ф е и н а и л и о б ы ч н ы й , к аж ется, ч т о м н о ж еств е н ­
н ы е в а р и а н т ы сво д ятся к п р ед л ож ен и ю : вам о д н о го или
другого. И м е н н о п оэтом у о п е р а т о р 1 f ум еет н е то л ь ко
п р и н и м а т ь р е ш е н и я , но и п р о д ел ы в ат ь одну и з двух во з­
м о ж н ы х о п ер а ц и й .
168
глава 4
принятие решении
Когда Вариантов дВа
О п е р а т о р 1£ ум еет д ел ать в ы б о р и з двух п р е д л о ж ен ­
н ы х в а р и а н то в . В ер н ем ся к наш ем у шоу. Э р и к п ы т а ется
п р и н я т ь р е ш е н и е , какую и з двух п р е д о с та в л е н н ы х ему
во зм о ж н о с те й п р ед п о ч есть.
ш
П ервы й в а р и а н т
че м о д а н А...
if (проверка условия)\
д е л ай что-то;
—а в т о р о й
чем одан В.
e ls e
д е л а й что-то ещ е;
<
В ж и зн и о б ы ч н о п р е д о с та в л я е тс я в ы б о р и з б олее
чем о д н о го в ар и ан та. О п е р а т о р И д ае т нам (и
Э рику) в о зм о ж н о сть в ы б р ат ь ч ем о д ан А и л и ч е­
м одан В. В от как эт о в ы гл яд и т в JavaS cript:
if (chosenCase =
"А")
openCaseC'A") ;
напислт ^у
» Г и ё > е
далее *■
169
если вариантов больше одного
сделать
Вы мо}кете V мно)кестВенный Выбор
в случае м н о ж ес тв е н н о го
в ы б о р а о п е р а т о р 1£ п р ев р а щ ает с я
в о п е р а т о р 1 £ / е 1 з е , д аю щ и й в о зм о ж н о с ть в случае н есо б л ю д ен и я
зад ан н о го усл о ви я зап у сти ть другой ф р а гм е н т кода. Ф ак ти ч ески
вы го в о р и те: «если условие соблю ден о, запустим эт о т ф р агм е н т
кода, а если н е т — в о т эт о т ф р агм ен т» .
if (chosenCase == "А")
openCase("А"); ^
собы т ий. О дин
^ о л н е н и я у сл о в и я Г
его
else
openCase ("В") ;
Э р и к в ы б и р а е т чем о д ан В, т о есть п е р е м е н н ая c h o s e n C a s e будет и м еть
зн а ч е н и е «В». Т ак как за д ан н о е усло ви е н е в ы п о л н я ет с я, у п р авл ен и е п е р е ­
х о д и т к коду, стоящ ем у п о сл е о п е р а т о р а e l s e . К н есч астью д ля Э ри ка,
в ы б р ан н ы й им ч ем о д ан н а п о л н е н п о н ч и к ам и , а вовсе н е п ач кам и д ен ег,
как о н надеялся.
Чемодан 8.
Я могу поменять
свое решение?
9
170
глава 4
■
^ развит ия
принятие решений
Ключевое слоВо else
С и н так си с о п е р а т о р а i f / e l s e п р а к т и ч е с к и н е о т л и ч а е т с я о т
си н так си са уже и зв е с тн о го вам о п е р а т о р а i f . П р о с т о д о б ав л я е т ­
ся кл ю ч ев о е сл о во e l s e с ещ е од ним ф р а гм е н т о м кода, к о т о р ы й
запускается п р и н есо б л ю д ен и и условия:
Условие
-I-
Оператор!
Всли э т о неверно, за ­
пускается эт от коа
К л ю ч е в о е слово else
н а п р а в л я е т дейст вие
----------------------------- 1
\-------- 1
В от каким о б р азо м м ож н о д о б а в и т ь в т о р о й в а р и а н т д ей ств и я к о п е р а т о р у i f :
К л ю ч ев о е сл ово e l s e п о сл е п ер в о го о п ер ат о р а .
©
О тступ н а пару п р о б е л о в д ля следую щ ей стр о ч к и ,
е
К од, запускаем ы й п р и н есо б л ю д ен и и условия.
чааюо
ЛаДаБаеМые
-
БоДроС ьі
Почему после скобок в операторе 1 £ отсутствует
точка с запятой?
0 ; визуаЗспр! принято ставить точку с запятой после каждого
оператора, и i f не исключение. Однако оператор i f — это
не просто запись i f { п р о в е р к а у с л о в и я ) , это еще
и код, который выполняется в случае положительного результата
S Ничего, в этом случае по результатам проверки условия не
предпринимается никаких действий.
Можно ли использовать несколько ключевых слов
e l s e для выбора из большего числа вариантов?
проверки. И вот эт от код венчает точка с запятой. Так что
; Да. В структуру i f /е 1 s е можно добавить дополнительные
варианты, но это вовсе не сводится к написанию еще одного
оператор i f заканчивается так, как нужнр, если учесть, из каких
ключевого слова
фрагментов он состоит.
вкладывать целиком, что легко может привести к путанице.
Поэтому в JavaScript для такой ситуации предусмотрена другая
Что происходит, если условие не выполняется,
а ключевое слово е 1 з е отсутствует?
e l s e . Конструкцию i f / e l s e приходится
структура — оператор
s w i t c h / c a s e , с которым мы таюке
познакомимся в этой главе.
далее ►
171
приключения нарисованного человечка
Пишем приключения
Э лли п и ш ет и н тер ак ти в н у ю и с т о р и ю « П р и к л ю ч ен и я н а р и с о ­
в а н н о го ч ел о веч ка» . Н а каж дом эт а п е п р и х о д и тс я п р и н и м а т ь
р е ш е н и я , и о н а н ад еется со зд ать с ц е н а р и й н aJav a S c rip t, к о т о р ы й
п о зв о л и т п о м е с т и т ь е е т в о р е н и е в И н т е р н е т д ля п о л ьзо вател ей .
Пользователю представлена
ж т ориТ
Sttck f »S“«
инт еракт ивная
V J e lc o r A G - t o
STICK FIGURE
adventu re
Л
^
Click e'rtber
buttoM ■to
I
S b r iPleasc choose; A J - i J
° Р ^^зличны х
не знает, как их вопло­
пока
т ит ь в реальность.
Э л ли х о ч ет , ч то б ы п о л ь зо в а т е л и н а каж дом этап е
ее и с т о р и и вы нуж дены б ы ли д ел ать вы б о р . Вы
м о ж ете сразу ск ач ать все н ео б х о д и м ы е ф а й л ы по
адресу http://w w w. headfirstlabs. com/books/hfjs/ .
172
глава 4
Я надеюсь, что JavaScn■pt
сделает мою историю понастоящему интерактивной.
принятие решений
Схема приключений
« П р и к л ю ч ен и я н а р и со в а н н о го ч ел о веч ка» п р ед ставл я ю т
со б о й н а б о р сц ен , каж дой и з к о т о р ы х с о о тв етству ет рисун ок
и о п и с ан и е . И каж ды й р а з для п е р е х о д а к следую щ ей сц ен е
вам п р и х о д и тс я в ы б и р а ть о д и н и з двух в а р и а н т о в р а зв и т и я
со б ы ти й .
В сценах 2 и 5 вам
также нужно при пят ь реш ение, чтобы
двигаться дальше.
Сцена 2
В каждой сцене п р и ­
с у т с т в у е т два в а ­
риант а дальнейшего
развит ия событий.
Хажмнй в лесу
^
С цена 1
■ ■
Развилка на дороге
L
Сцена 3
Каждая сцена
и м еет свой
уникальный
номер.
М ост через реку
«Текущ ая сцена» показы ва. ет положение пользоват еля
в данный м ом ент времени.
Возьми в руку карандаш
Напишите код принятия решений для первых трех сцен с оператором i f /
e ls e . Подсказка: переменная d e c i s i o n хранит информацию о выборе
пользователя, в то время как переменная c u r S c e n e содержит сцену,
к которой происходит переход.
далее
173
решение упражнения
Возьми в руку карандаш _
Решение
П е р е м е н н ая ie c is о
Вот как выглядит написанный на основе оператора i f / e l s e
код для первых трех сцен «Приключений нарисованного
человечка».
_____—
„ .л f ГЛеКУ^М*^*^ “
\
Г о 1 "о б й т е Д ^ ^ ^ ,Д о р о е
М0ЛЛеК1АА
АЛО/кет рйЬнЯ 1А^
J. UA« я .
^
_
, f (d e c is io n == 1 )
C M rS cm e - Z } < г
else
-^ c u rS c e n e = 3 ;
П ерем енная сигЗсепе х р а н и т
инф орм ацию о т е к у щ е й сцене
переход к к о т о р о й я в ы л с я ^ е
Щ А ь т а т о м принят ого п о л ь ­
з о в а т е л е м решения.
П ереход к сцене Z .
Переход к сцене 3.
Переменные как двигатель истории
П о с м о тр и м в н и м ате л ь н о н а п е р е м е н н ы е, к о т о р ы е ф и гури рую т в на­
ш ей и с т о р и и . И х зн а ч е н и е за в и с и т о т р е ш е н и я , п р и н я т о г о п о л ьзо в а ­
тел ем , и и м е н н о о н о я в л я е т с я д в и гател ем н аш ей и ст о р и и .
С«еиа■
Сцена 2
d e c is io n
Н уж н о в ы б р ат ь между
з н а ч е н и я м и 1 и 2. Э то
о п р е д е л и т , в как о й с ц ен е
п о л ьзо в а те л ь о к аж ется
н а следую щ ем этапе.
Р ем
curScene
С ц ен а, в к о т о р о й н а ­
х о д и т ся п ол ьзовател ь.
Ее н о м е р о п р е д е л я е т с я
п ерем ен н ой d e c is io n :
сц ен а 1, сц ен а 2 и т. д.
П е р е м е н н ы е d e c i s i o n и c u rS c e n e р а б о т а ю т совм естн о , со х р ан я я
в ар и а н т , в ы б р ан н ы й п о л ь зо в ател ем , и затем н а его о сн о в е осущ ест­
вл я я п ер ех о д к следую щ ей сц ен е. П р о ц е д у р а п о в т о р я е т с я о т сц ен ы
к сц е н е до к о н ц а и с т о р и и . С п аси бо за эт о о п ер ат о р у i f / e l s e .
174
глава 4
Сце
И З е М >^01
м осту
по1
принятие решении
Недостающие части истории
О п е р а т о р 1 £ / е 1 з е п р е к р а сн о р а б о т а е т в к ач еств е
«двигателя» « П р и к л ю ч ен и й н а р и со в а н н о го ч ел о в е ч ­
ка», н о о н , к со ж ал ен и ю , н е п о зв о л я е т р а с с к а зат ь и с т о ­
р и ю цел и ко м . К аж д о й сц ен е с о о тв етств у ет не то л ь ко
и зо б р а ж е н и е , н о и т е к с т о в о е о п и сан и е. И зм е н е н и е
н о м е р а текущ ей с ц ен ы п о зв о л я е т п е р е й т и к другому
и зо б р а ж е н и ю , о став и в за кадром и зм е н и в ш и й ся текст.
«Н овая»
т екущ ая
сцена.
Г
1
Сцена 2
Пользователь
выбрал в а р и ­
ант
« эт о
п ривело его
Х и ж и н а в лесу
к сцене Я-
Сцена 1
J
Р йзвилкй на дороге
с ч .« «
0ДрйЗним
веЗі>М^і
«Вы прибьши в симпатичную
маленькую хижину в чаще
леса».
© Обойде
Для з а д М
д о ст а т о ч н о н о м е р а си,еиьь
ка к э т о т ном ер содерж ит ся
iiio to e
в имени соот вет ст вую щ его
c o l Ofс
граф ического ф айла.
la ia n i
.—
ф о р м а т РЫО —
новы й, ш и р о ко
^
распрост раненны й
^лtлл
слтлалнI д а р
т.
О п и са н и е сце~
н ь / о с т а е т с я за
кадром ,, т а к к а к
рР^ЗЦЛЬИА/]1
е з у л ь т а талл
е 1п рI, и ­
н ят о го р е ш е н и я
м о ж е т бы т ь в ы один
document.getElementByldC'sceneimg").src = "scene" + curScene + ".png
Т ак как п о сл е каж до й ч ас т и о п е р а т о р а i f /
else м о ж н о зап у сти ть т о л ь к о о д и н ф р а гм е н т
кода, к о л и ч е с т в о в а р и а н т о в р а зв и т и я с о б ы ти й
о гр а н и ч е н о . Д р у ги м и сл овам и, вы н е м о ж ете
о т о б р а зи т ь н о в ы й т е к с т и н о в о е и зо б р а ж е н и е
о д н о в р ем ен н о .
Ш ТУРМ
Как бы вы реализовали выполнение
набора операций в ответ на принятие
решения?
далее ►
175
больше одного
СоВмецение усилий
Э л ли нуж но, ч то б ы н а каж д о й ветв и о п е р а т о р а i f / e l s e в ы п о л н я л о с ь
н еск о л ьк о ф р а гм е н т о в кода. П р и п е р е х о д е к следую щ ей с ц ен е о н а хоч е т м е н я т ь н е т о л ь к о и зо б р а ж е н и е , н о и с о п р о в о д и т е л ь н ы й текст:
И зм енение к а р т и н к и
б р а н н о с ^^^ ^^ ^
document.getElementByldC'sceneimg").src = "scene" + curScene + ".png";
alert(message);
О т ображ ение описания в ы ­
бранной п о л ш о в а т е л е м новой
сцены.
Вам нуж но п р о и зв е с т и н еск о л ьк о о п е р а ц и й , н е с м о т р я н а т о ч то
Jav aS crip t в это м случае п о зв о л я е т запускать всего од и н ф р а гм е н т
кода. Р еш ен и ем я в л я е т с я с о с та в н о й о п е р а т о р . Д л я его с о зд ан и я до­
ст ат о ч н о зак л ю ч и ть н а б о р о п е р а т о р о в в ф и гу р н ы е скоб ки ({ } ).
Ага! Составной оператор
позволяет превратить
набор фрагментов в один
кусок кода.
О
d o T h i s ();
d o T h a t ();
З оператора
doSomethingElse ();
>
Количество
открывающих
и закрывающих
скобок должно
совпадать.
{
doThisO;
doThat();
1 оператор
doSomethingEise();
_____
С о ставн о й о п е р а т о р п о зв о л я е т со зд ать к о н струк ц и ю i f / e l s e ,
реализую щ ую в о д н о й в е т к е н еск о л ьк о о п е р а ц и й :
if (chosenDoor == "А") {
prize = "donuts";
alert{"Вы выиграли коробку с пончиками!");
}
else {
prize = "pet rock";
С х ґ'
alert("Вы выиграли камешек!");
}
176
глава 4
Выполняйте
»абор действий
о каждой ветке
оператора if/else.
принятие решений
чааво
ЧаДаБаеМые
Б оЛ рось!
Каким образом переменные
влияют на развитие сюжета
Зачем соединять несколько
операторов в один?
3 * Почему в конце составного
оператора нет точки с запятой?
в «Приключениях»?
0 ; в иауаЗсг1р1 часто требуется всего
; в каждый момент переменная
c u r S c e n e содержит номер текущей
сцены. При этом демонстрируются
соответствующее изображение
и описание, а пользователю предлагается
указать, к какой из следующих сцен
он предпочитает перейти. Выбор
пользователя — 1 или 2 — сохраняется
в переменной d e c i s i o n . Вместе
с переменной c u r S c e n e она
определяет следующую сцену. На основе
значения этой переменной выбирается
новая картинка, и во всплывающем окне
появляется новое описание.
один оператор. В качестве аналогии
вспомним про авиакомпании, которые
позволяют взять с собой только два
места багажа. Ничто не мешает вам
перевозить произвольное количество
вещей, главное — упаковать их таким
образом, чтобы они занимали всего два
места. Также устроены и составные
операторы. Это своего рода контейнер,
воспринимаемый сценарием как один
оператор.
0 ; Точка с запятой обозначает конец
обычного, одиночного оператора.
Соответственно, она завершает каждый
составной оператор из формирующих
операторов.
3 * Относится ли метод к составным
операторам?
! Разумеется. Вы уже могли заметить,
что код методов заключен в фигурные
скобки. Поэтому на данном этапе методы
можно воспринимать как большие
составные операторы, которым вы
передаете данные и от которых получаете
результат.
решение упражнения
Возьми в руку карандаш,
Решение
Номер новой сцены
определяет реш ение
'пользователя.
Вот как должен выглядеть новый вариант кода для первого
оператора i f / e l s e , направляющего героя «Приключений»
к следующей сцене.
if (decisioiA
1) (
curScene = 2:
Описание Выбира­
ет ся в с о о т в е т - ...............message = ‘'You have arrived a t a cute little house in th e w oods ” •
ст вии с ном ером Г
сцены.
...................................................................................................................................... .
-----^
}
Начните сост авной
о п е р а т о р с ф игур ной
открывающ ей скобки.у<С‘'ИГ?сепе ~ з .
strea m .”;
Все содержимое
составного о п е ­
р а т о р а пиш ем
с от ст упом .
8 конце составного
о п ер а т о р а с т а ви м
закры ваю щ ий} ф и гу р н у ю скооку.
КЛЮЧЕВЫЕ
МОМЕНТЫ
178
<1
bridge overlooking а ^eaceful_
tv
Д л я сцены 3 задано
другое описание.
------------------------------------------------
Оператор i f запускает фрагмент кода JavaScript
при соблюдении заданного условия.
Составной оператор позволяет запустить набор
фрагментов кода JavaScript вместо одного.
Результатом проверки условия в операторе i f
является значение t r u e или f a l s e .
Для создания составного оператора достаточно за­
ключить набор операторов в фигурные скобки ( { } ) .
Оператор i f / e l s e позволяет по результатам
проверки условия запустить два фрагмента кода
JavaScript.
Составные операторы позволяют осуществлять на­
бор действий в конструкциях i f и i f / e l s e .
глава 4
принятие решений
Приключения начинаются
Н а б о р со став н ы х о п е р а т о р о в вм есте с ко н стр у к ц и ей
i f / e l s e п р е в р а т и л и « П р и к л ю ч ен и я н а р и со в а н н о го
чел овеч ка» в и н тер ак ти в н у ю и сторию !
0 Дразним
, 'веЭЬАЩ ,
К но п ка X
п ер е во д и т
п о ль зо вй т е ля
к сцене Z-
f
Pleasechoosc:
YOU have
»
«
' «
*"
-Ч»
Pltecl»»: _ lj j J
Y our jou rn e y b e g in s “ ®
wmmmniHiaH
Т е к с т с о п и са ни ем сцены
во в с п лы ва ю щ ем окне.
Сцена 3.
К н о п ка Я
п ер ево д и т
п о ль зо ва т еля
к сцене 3.
—
Первые сцены
истории выглядят
замечательно!
jJ - iJ
You are s ta n d in e o n th e brid g e overlo o k m g a peaceful
Stream .
далее *
179
корни дерева решений
Остальные приключения
Е д и н ств ен н о е р е ш е н и е п о л ь зо в а т е л я в р я д л и п о зв о л и т со зд ать
и н тер есн у ю и сто р и ю . Н о Э лли п л ан и р у ет вк л ю ч и ть в п о в ест в о ­
в ан и е д о п о л н и т е л ь н ы е сц ен ы . В р езу л ьтате п ол уч и тся древо­
видная структура, по к о т о р о й вы будете п р о д в и га ться дальш е.
Сцена 2
Х и ж и н а в лесу.
Д л я перехода о т начальной
сцены к сцене 1 р е ш е н и я п о л ь ­
зоват елей не т р е б уе т ся.
ИЯІ
Сцена 1
Сцена О
^
И д ем п о д о р о ге.
Н ач ал о
и с т о р и и . Рйзбылка Нй аоВведение
роге
И д ем н а мост.
Сцена 3
Заглавная сцена с л у ж и т
введением 6 « П р и к л ю ч е н и я
нарисован ного человечка».
К р о м е н о вы х сц ен , обеспечиваю ш ;их д о п о л н и т е л ь н ы е п о в о р о т ы сю ­
ж ета, Э лли со зд ал а вводную сцену, к о т о р а я будет п о я в л я ть ся п ер ед
с ц ен о й 1. О н а ун и кал ьн а тем , ч т о н е т р еб у ет п р и н я т и я р е ш е н и я
для п ер ех о д а. Все м а те р и а л ы , н ео б х о д и м ы е д ля эт о го урока, м ож н о
ск ач ать п о адресу http://xvw w .headfirstlabs.com /books/hfjs/.
180
глава 4
М о с т через р е к у
принятие решении
С цена 8
С цена 4
К рад ем ся
Продолжение
следует...
^
ВедШ й в окне
С цена 5
Д р азн и м
ведьму.
^
Д р азн и м ведьму.
Съеден ведомой
КО НЕЦ
Э т о т уп и к о в ы е
в е т ки .
С цена 6
Э т и в а р и а н т ы возвра^
щ а ю т нас к т у п и к о ­
в ы м сценам .
Съеден т р о ллем
КОНЕЦ
^
^ П е р е х о д и м м ост.
Г о в о р и м трол«П ривет».
ЛЮ
С цена 9
С цена 7
С м о тр и м
Продолжение
следует...
ТроллЕ? на м ост у
П р ы гаем
в реку.
Ш ТУРМ
Как будет выглядеть это дерево решений, написанное при помощи операторов if / e ls e ?
далее >
181
я не знаю... это зависит от...
Запись при noMoui^u if/else
If (cu rSce n e is 2)
Н е с м о т р я н а т о ч т о в ы б и р а ть каж ды й р а з п р ед л агается всего и з
двух в а р и а н т о в , Э лли р е ш и л а сделать так, ч то б ы последую щ ие р е ­
ш ен и я зав и сел и о т преды дущ их. Н а п р и м е р , для п ер е х о д а к сц е н е 5
о т н а ч а л а и с т о р и и нуж но п р о д е л а ть следую щ ий путь:
If (d e cision is 1)
К сц ен е 4
E lse
С цена 2
Сцена 1
Разбидкй I
Хижина
в леей
ц й дороге I
Съеден
ведьм ой.
С цена 2
Сцеиа 1
разбилка
нй дороге
^
Хижина
лесу
If (cu rSce n e is 4)
If (d ecision is 1)
Можно ли вкладывать
операторы if/else друг
в друга?
К сц ен е 8
E lse
К сцене 5
З н а н и я , как о й в а р и а н т в ы б р ал п о л ьзо вател ь, н е д о с та т о ч н о для
п е р е х о д а к следую щ ей сц ен е. Э то всего л и ш ь од и н и з ф а к то р о в .
М о ж н о и сп о л ьзо вать н а б о р о п е р а т о р о в i f / e l s e , сн ач ал а п р о ­
в е р я я текущую сцену, а затем п р е д п р и н и м а я д ей с тв и е н а о сн ове
п р и н я т о г о п о л ьзо в ател ем р еш ен и я . Н о в этом случае вы получите
н а б о р в л о ж ен н ы х о п е р а т о р о в i f , ч т о к р а й н е неудобно.
Н о ведь в р е ал ьн о м м и р е мы п р и н и м ае м р е ш е н и я п о этап н о . Вы
ведь о т в е ч ал и н а воп рос: «Вы будете за к азы в ать к а р т о ф е л ь ф ри?»
Его о б ы ч н о н е задаю т, есл и вы зак азал и салат. Д ругим и словам и,
ч то б ы по л уч и ть т а к о й в о п р о с, нуж но п ер ед эти м д ать о п р ед е л ен ­
н ы й о тв е т, н ап р и м ер : «Я буду чи зб ургер». Т о есть б олее п о зд н и е
в о п р о с ы (к а р т о ф ел ь ф р и ?) зав и ся т о т о т в е та н а во п р о с преды ду­
щ и й (ч и зб ургер и л и салат?).
182
глава 4
принятие решении
Вло)кенный оператор ^f
Jav aS crip t п о зв о л я е т вклад ы вать
операторы
друг в друга. Д руги­
ми сл овам и, н и ч т о н е за п р е щ а е т
вам зад ать н о в ы й во п р о с, полу­
ч и в о т в е т н а преды дущ ий. Т акая
к о н стр у к ц и я н а зы в а е т с я в л о ж е н ­
ны м о п е р а т о р о м
.
В ло ж е н н ы й о п е ­
рат ор if р а ссм а ­
т р и в а е т с я только
в т о м случае, к о г ­
да внешний опера­
тор возвращает
значение true.
if (order == "cheeseburger")
if (wantFries)
order += " fries";
else if (order == "salad")
if (wantFruit)
order += " fruit";
}
/
Ynpou^eHHi^iu вариант за п и с и order
" order -r ... на
8t>! получите
{
{
реш ение упражнения
Возьми В руку карандаш
Рр\\\рЦ\АО
г СШ СпИС
В Ы Г Л Я Д И Т код п р и н я ти я р е ш е н и й для сцены о и сцены 1
« П р и к л ю ч е н и й н а р и с о в а н н о го чел овечка».
Сцена О всегда см ен я ет ся
сценой 1 , п о э т о м у вам
не т р е б у е т с я влож енный
операт ор
Текстовое описание
ОЛЯ сцены 1,
if (curScene == о) I
В ели м ы находим ся
не е сцене о , п р о б е -
curScene = 1;
щ т е ^ бы т ь,
message = "Your joum&y begins a t a fork /n the road-“;
^else if (curScene - - 1) {
if (decision == i ) {
Влож енный о п е р а т о р
if/else обрабат ы вает
реш ение п о л ь з о в а т е ЛЯ для сцены t .
. curScene = Z;
message = "You have arrived a t a cute, little house in the woods.":
else.f ^
curScene = 3;
>mesSAge ~ "You are sta n d in ^o n the bridge overlooking a peaceful stream.";
}
O m xm ym t помога­
ю т определить, какие
операторы являются
вложенными.
184
глава 4
\
Важно, чт обы количест во
о т кр ы ва ю щ и х скобок с о ­
от вет ст вовало количе­
с т в у закры ваю щ их.
принятие решении
Управление при помои^и методов
П о л ь зо в а т ел ь п е р е х о д и т о т о д н о й с ц ен ы к другой п р и пом ощ и
п ар ы к н о п о к («1» и «2»). Щ ел ч о к н а л ю б о й и з к н о п о к вы зы в ае т
м етод с Ь а п д е З с е п е ( ) , о тв е ч а ю щ и й за п ер ех о д к следую щ ей
сцене.
function changeScene(option)
{
}
</script>
</head>
<body>
<div style="margin-top:100px; text-align:center">
p " a ,;
\
- p n ,-
x
A C v X tu re .. / > < ь Л >
<input type="buttOn" id="decision1 "
^
<input type="button" id="decision2" v alue="?"
(1]
</div>
° ^ d i c k - " c h a n g e S c e n e (^
</body>
</html>
М етод c h a n g e S c e n e () по л у ч ает р е ш е н и е п о л ьзо в ате л я
(«1» и л и «2») в к ач еств е аргум ента. Э то й и н ф о р м а ц и и
д о ст а т о ч н о д ля п е р е х о д а к следую щ ей сц ен е. М етод
c h a n g e S c e n e () д ел ает следую щ ее:
На ве б -с т р а н и ц е находит ся Ъве
кнопки, о п р ед еля ю щ и е, к какой
сцене п о л м о в а т е л ь п е р е й д е т на
с лед ую щ ем эт апе.
Присваивает п е р е м е н н о й c u r S c e n e н о м е р н о в о й сцены.
©
О
П р и с в а и в а е т п е р е м е н н о й m e s s a g e н о в о е о п и сан и е.
М е н я е т и зо б р а ж е н и е н а о сн о в е зн а ч е н и я п е р е м е н ­
н о й c u r S c e n e и в ы в о д и т н о в о е о п и сан и е.
далее ►
185
псевдо что?
Псевдокод
Э лли п р и м е р н о п р ед став л я ет, как н а п и с а ть н а Jav aS crip t код м етод а c h a n g e S c e n e ( ) ,
реал и зу ю щ и й д е р е в о р е ш е н и й н аш ей и с т о р и и . Н о из-за б ольш ого к о л и ч ес т в а р е ш е ­
н и й в коде л е гк о запутаться. П о это м у и м е е т см ы сл сн ач ал а н а п и с ать п севдокод, к о т о ­
р ы й п р о щ е в о с п р и н и м а е т ся , а уже н а его о с н о в е м ы зай м ем ся п р о гр а м м и р о в а н и е м .
Т а к о й подход п о зв о л я е т и зб е ж а ть путан и ц ы и ош ибок.
С цена
Г
Каждый о п е р а т о р
if/else верхнего уровня
представляет свою
сцену.
о
If (c u rSc e n e is 0) < г
введение
К сцен е 1
Т екст с ц е н ы 1
V ---- -------------- 3!» E ls e и (c u rSc e n e I s 1)
- > If (d ecision is 1)
В н у т р е н н и е опера­
торы if/else вы­
полняют действия
ы выбору п о л ь з о в а ­
т еля.
К сц ен е 2
Т екст сц ен ы 2
E lse
С цена 2
К сцен е 3
Хижина
в лесу
Т екст сц ен ы 3
E lse If (c u rSc e n e Is 2)
Часзпо
5
^аД аБаеМ ы е
Боц|=»ос:ь1
=
Псевдокод похож на код JavaScript. Зачем он нужен?
; Он позволяет упростить процесс преобразования сложного
логического дерева в код JavaScript и минимизирует риск ошибок.
Псевдокод имеет меньший уровень детализации, поэтому вы
можете сфокусировать внимание на логике происходящего
и переходе от одной сцены к другой. Привыкнув работать
с псевдокодом, вы сможете практически на автомате переводить
его в обычный код ивуаЗспр!.
186
глава 4
5=
Требуются ли фигурные скобки для вложенных
one
операторов i f ?
0
!: Нет. Если вы вкладываете всего один оператор
,
фигурные скобки проще игнорировать, так как технически вам
не нужен составной оператор. А вот при сложном вложении
операторов 1 £ скобки могут пригодиться, так как они
структурируют код и делают его более читабельным.
принятие решении
Магниты JavaScript
в м ето д е c h a n g e S c e n e ( ) не хв атает н е с ко л ь ки х ф рагм ентов . В оспользуйтесь м агн и та м и ,
чтобы пол учи ть код, в о с п р о и зв о д я щ и й д и а гр а м м у на с тр а н и ц е 180. П о м н и те , что показаны
д а л е ко не все варианты р а зв и ти я и с то р и и — не ко то р ы е сцены н а м е р е н н о были оставлены
за ка д р о м .
лее >
187
решение задачи с магнитами
^ Решение задачи с магнитами
Вот ка ки м о б р а зо м тр е б о в а л о с ь д о п о л н и ть м ето д c h a n g e S c e n e { ) , чтобы пол учи ть код,
в о с п р о и зв о д я щ и й д и а гр а м м у со страниц ы 180.
188
глава 4
принятие решении
Приключения продол}ка1отся
Т е п е р ь с ц е н а р и й « П р и к л ю ч ен и й н а р и со в а н н о го ч е­
л овечка» о т о б р а ж ае т все д е р е в о р е ш е н и й , п о зв о л я я
н а п р ав л я т ь с о б ы т и я по р а зл и ч н ы м веткам . В от од и н и з
вар и ан то в :
W e lc o n e t o
ADVENTUI^E
Click either
b u tto N f o
start...
далее >
189
потерпев неудачу
Проблемы нарисованного человечка
к со ж ал ен и ю , Э лли уже столкнулась с п р о б л ем о й . П о п р о с и в
св о и х друзей п р о т е с т и р о в а т ь с тр ан и ц у с « П р и к л ю ч ен и ям и » ,
о н а узнала о п о я в л е н и и пустого окна. « О кн о-призрак» в о зн и ­
к ае т п р и п е р е х о д е о т о д н о й с ц ен ы к другой. Т о есть п р о б л ем а
каким -то о б р азо м св язан а с в о зв р а щ ен и е м к с ц ен е 0.
О к н о - п р и з р а к не содерж ит
никакого сообщения?
WelcOHG t o
STICK FIGURE
A D V E M T i i Pc
CZ5HZ3
О
РЬаж choose:
О казал о сь, ч т о две с ц ен ы д ей с тв и те л ь н о в о звр ащ аю т нас к с ц ен е 0. И х
н о м е р а 5 и 6 , и о н и со о тветству ю т тупиковы м веткам и с т о р и и . В п р и н ­
ц и п е и м е е т см ы сл, п о сл е то го как и с т о р и я сто л ь б ессл авн о за в ер ш и ­
л ась, вер н у ться в нач ало. И м е н н о п о это м у Э лли н ап и сал а код м етод а
c h a n g e S c e n e () таки м о б р азо м , ч то б ы п о сл е э т и х с ц ен п р о и сх о д и л
п ер ех о д к с ц е н е 0:
else if (curScene == 5
curScene = 0;
}
else if (curScene ==
curScene = 0;
Сцены s и <ь м е н я ю т
значение пер ем ен н о й
cu rS cen e, но ничего не
д е л а ю т с пер ем ен н о й
m essage.
К аж ется, ч то т а к о й п р о с т о й код н е д о л ж ен бы л п р е п о д н е ст и
н ам н и к ак и х с ю р п р и зо в , н о в згл ян ем н а посл ед н ю ю стр о ч к у м е­
т о д а c h a n g e S c e n e ( ) , о тв еч аю щ его за и зм е н ен и е и зо б р а ж е н и я
и о п и с ан и я п р и п е р е х о д е к следую щ ей сцене.
document.getElementByldC'sceneimg").src = "scene" + curScene + ". png"
alert(message);
О т ображ ает т е к с т с описанием
сцены , хр анящ ийся в п ер ем ен н о й
m essage.
190
глава 4
принятие решении
! = m-c-c‘ c, мне нечего тебе сказать...
П р о б л е м а в то м , ч то код « П р и к л ю ч ен и й » всегда в ы зы в ае т о кн о
с о п и с ан и е м сц ен ы , даж е есл и о п и с ы в а т ь н е ч е го , как, н а п р и м е р ,
в сц е н е 0. К аки м ж е о б р азо м п р о в е р и т ь , со д е р ж и т л и п е р е м е н н ая
m e s s a g e какой-нибудь текст?
(
.3
Нужно с д ела т ь т а к ,
чт обы п р и о т с у т с т в и и
у п ер ем ен н о й message
значения окно диалога не
появлялось.
Условие соблюдаеился
для всех сцен, кроме
сцены 6.
if
П е р ед вы зо во м о к н а нуж но п р о в е р и т ь , н е со д е р ж и т л и
п е р е м е н н а я m e s s a g e пустой с т р о к и (" ")• М ож н о п о ­
ст ав и ть и другое условие. В ы зы вать о к н о ди ал ога, если
п е р е м е н н а я m e s s a g e н е р а в н а пустой стр о ке. Э то вы гл я­
д и т как р е ш е н и е п р о б л ем ы задом н ап ер ед , н о в д ан н ом
случае м ы рассуж даем в т е р м и н а х п р о в е р к и условия.
В то в р е м я к ак о п е р а т о р (==) п р о в е р я е т р ав ен с т в о двух
эл ем ен то в , о п е р а т о р (! =) п р о в е р я е т и х н ер авен ств о .
{curScene != 6)
a l e r t ("Thankfully, you haven't been eaten by the troll.");
далее ^
191
операции сравнения
Возьми в руку карандаш
'ешение
Условие с о б л ю д а е т ­
ся, ссли п&р&менная
m essage содерж ит
н е п у с т у ю ст р о ку.
Вот к а к б удет вы глядеть код, вы зы ваю щ ий о к н о д и а л о га в слу­
чае, если п е р е м е н н а я m e s s a g e с о д е р ж и т текстов ы е данны е.
if (m essage !- "")
alert(m essa g e)i
Операторы сравнения
Д о эт о го м о м ен та м ы р а с с м ат р и в а л и п р о в ер к у условий, со зд ан н ы х
т о л ь к о п р и п о м о щ и о п е р а т о р о в р а в е н с т в а и н ер а в ен с тв а. А ведь
н аш и в о зм о ж н о с ти эти м н е о гр а н и ч и в а ю тс я . Р ассм о тр и м и другие
о п е р а т о р ы с р ав н ен и я.
Равенство
X == у
Неравенство
X
Меньше чем
»=
X
Значение tr u e ,
если X Р А В Е Н у.
Отрицание
Значение tr u e , если х
НЕ РА В Е Н у.
< у
Значение tr u e , если х
М Е Н Ь Ш Е , ЧЕМ у.
Меньше UAU равно
X
Значение false, если х
и м е е т значение tr u e ,
и наоборот .
< =
З начение tr u e , если х
З О А Ь Ш Е , ЧЕМ у.
у
Значение tr u e , если х
М ЕН ЬШ Е И Л И Р А В Е Н у.
Больше иди равно
X
>= у
Значение tr u e , если х
5 0 Л Ь Ш Е И Л И Р А В Е Н у.
= и == вовсе не одно
и то же.
О п е р а т о р ы с р а в н е н и я Jav aS crip t исп ользую т­
б у д ,ыпе
ьте
ся д ля п о с т р о е н и я выраженийг, к о т о р ы е затем
Для проверки равенства
осторож ны !
ком б и н и р у ю тся в е д и н о е зн а ч е н и е . Э то зн а ч е н и е
двух значений следует ис­
п р и н а д л е ж и т к ло ги ч еск о м у типу ( t r u e / f a l s e ) ,
пользовать оператор ==
ч то д ел а е т его н езам ен и м ы м в кач е с тв е п р о в е р я е ­
и ни в коем случае не оператор =. Послед­
м ого усл о ви я в о п е р а т о р а х i f / e l s e .
ний осуществляет присвоение значения.
192
глава 4
чааюо
принятие решении
Задаваем ы е
Б о п р о сгь!
Почему оператор отрицания использует всего одно
значение?
Q l Этот оператор реализует очень простую задачу. Он меняет
значение операнда на противоположное. В результате t r u e
превращается в f a l s e , и наоборот.
Я видел оператор отрицания рядом со значением,
которое не имеет отношения к сравнению. Как он работает?
• А что такое n u l l ?
; n u l l — это специальное значение, указывающее
на отсутствие данных. Его смысл вы лучше поймете при
рассмотрении объектов, которым будут посвящены главы 9 и 10.
! В таких случаях все зависит от того, каким образом
JavaScript определяет «правдивость» значения. Используя не
имеющие отношения к сравнению значения в ситуации,
ажнение
где сравнение ожидается, мы интерпретируем любое значение,
отличное от n u l l , о или " " , как t r u e . Другими словами,
как t r u e рассматривается само наличие данных. Поэтому,
когда вы видите оператор отрицания с несравниваемым
значением, n u l l , О и " " дают в результате t r u e , а все
остальные значения — f a l s e .
Этот код выводит сообщение «I love stick Figure Adventure!» Какие значения должны иметь
переменные а , Ь , с и d , чтобы получился именно такой результат?
v a r q u o te -
a
if
(a != 1 0 )
q u o t e += "Som e g u y " ;
e ls e
q u o te += " I " ;
i f (b = = (a * 3)) {
i f (c < (b / 6 ) )
q u o te += " d o n 't c a re f o r " ;
e l s e i f (c > = (b / 5 ) )
q u o t e += " c a n ' t r e m e m b e r " ;
b
с
d
e ls e
q u o t e += " l o v e " ;
}
e ls e {
q u o t e += " r e a l l y
h a te s";
}
if.(!d ) {
q u o t e += " S t i c k F i g u r e " ;
}
e ls e {
q u o t e += " R o c k ,
P aper,
S c isso rs
;
}
a l e r t
(q u o te + " A d v e n tu re !" );
далее ►
193
решение упражнения
значения должны иметь переменные а , Ь, с и d, чтобы во всплывающем окне
rto 2 ^ 1 6 H V l2
появилось сообщение «I love stick Figure Adventure!»
var quote
if
Й должно р а вн я т ься Ш
(a != 10)
q u o te += "Some g u y ";
e ls e
quote += "I";
if (b == (a * 3)) {
if (c < (b / 6) )
quote += " don't care
else if (c >= (b / 5))
q u o t e += " c a n ' t r e m e m b e r
e ls e
quote += " love";<i
}
П ерем енная d должна
и м е т ь значение false,
чт о5ы выраж ение !d
и м ело значение tru e.
В о т сообщ ение, ко т орое
н а м м ребовалось.
else {
quote += "
}
if (!d) {
quote += "
I love Stick Figure Adventure!
}
else {
quote += "
}
a le rt(q u o te
+ " A d v en tu re!
Комментарии
«П р и к л ю ч ен и я» я в л яю тся х о р о ш и м п р и м ер о м с ц е н а р и я с н е за в е р ш е н н ы м и ф р а гм е н т а ­
м и кода, ведь и с т о р и я еш,е н е д о п и сан а. К пр и м еру, сц ен ы 8 и 9 п о м е ч е н ы сл о в о со ч ет а­
н и ем « П р о д о л ж ен и е следует». Н е за к о н ч е н н ы е о б л асти код а и м еет см ы сл п о м еч ать ком ­
м ен т а р и я м и , ч то б ы н е за б ы ть за п о л н и т ь и х п о зд н ее. К о м м ен т ар и и вJav aS cгip t н и к о и м
о б р азо м н е в л и я ю т н а запуск и р або ту сц ен ар и я.
К о м м е н т а р и и на чинаю т ся
п арой косых ч ерт .
194
глава 4
-ь ^ Комментарий
Т екст к о м м е н т а р и я
м ож ет быть любым.
Инт ерпрет ат ор
J a v a S c rip t его все
равно не видит.
принятие решении
КоАЛАленшарии начинаются с / /
Н а ч и н а я с ь с / / , к о м м е н т а р и и п р о д о л ж аю тся до к о н ц а стр о ки .
Д ля со зд ан и я м е с то за п о л н и т е л я п о с та в ьте две к о сы е ч е р т ы
и о став ь те за н и м и п р и м е ч а н и е о том , ч т о код ещ е н е нап и сан .
Сцена 8
else if (curScene == 8) {
11 Продолжение следует
Э т и ст р о ч ки
и гн ори р ую т ся-
С ц ен а 9
}
else if (curScene == 9) {
11 Продолжение следует
ПроЭоАжгиие
слеЗает-..
}
К о м м е н т а р и и н е то л ь к о и гр а ю т р о л ь м е с то за п о л н и т ел ей . О н и исп ользую тся
в ка ч е с тв е п р и м еч а н и й , д ел аю щ и х код б о л ее п о н ятн ы м . Т о , ч т о вы сей ч ас
п о м н и т е п р е д н а зн а ч е н и е то го и л и и н о го ф р а гм е н т а кода, н е о зн а ч ае т, ч то
вы будете п о м н и т ь эт о и ч е р е з год. К р о м е т о го , ваш код м о ж ет п о п асть
в чуж ие руки, и и м е н н о п р и м е ч а н и я п о зв о л я т б ы ст р о п о н я т ь , ч т о для ч его
п р ед н азн ач ен о .
К ом м ент а­
р и й объясняет
ин и ц и ализацию
>л&ременной.
// Выбираем в качестве текущей сцену О (Введение)
var curScene = 0 ;
И н и ц и а л и за ц и я п е р е м е н н о й c u r S c e n e в « П р и к л ю ч ен и ях» стал а
п о н я т н е й б лаго д ар я ко м м ен тар и ю . А н ал о ги ч н ы м ко м м ен тар и ем
м ож н о сн аб д и ть и н и ц и а л и за ц и ю п е р е м е н н о й m e s s a g e .
И сноЬа к о м м е н т а р и й
по я сн я ет назначение
ф р а гм е н т а кода.
// Удаляем описание сцены
var message =
С ущ ествует в о зм о ж н о сть со зд ав ать к о м м е н т а р и и , за н и ­
м аю щ ие н еск о л ьк о строк.
М ногост рочны е
к о м м е н т а р и и Ha™
чи и а ю т ся с / *
Еще комментарий
}
Однострочные комментарии
начинаются с / / , в то
время как многострочные
комментарии заключены
между / * и * / .
К он ец коммент ария
8 конце м н о г о ­
ст рочного к о м ­
м ент ария с т а б ы тс я */.
________ ;
К о м м е ш а р и й м о ж е т и м е т ь п р ои звол ьн ую длину
и зан и м ать скол ьк о угодн о стр о к. Д о с та т о ч н о п о ста­
в и ть в н ач ал е / *, а в к о н ц е * / .
/* Эти три строчки кода представляют собой один
большой комментарий. Серьезно, я не шучу.
Кроме шуток, это все еще один комментарий. */
далее ►
195
ну и куда мне деть эту переменную?
Комментарии несут смыс­
ловую нагрузку, но я не понимаю,
почему переменные curScene и message
создаются в различных местах. Что это
означает?
П ерем енная cu rS cen e
со зд а ем ся вне м ет о д а
c k a n g e S c em Q .
<script type="text/javascript">
(В ведение)
- ^ / / Выбираем в к а ч е с т в е тек у щ ей с ц е н у О
var curScene = 0;
function changeScene(decision)
/ / У даляем о п и сан и е сцены
var message =
{
</script>
П ерем енная m essage
создает ся в н у т р и
changeSceneQ .
Место создания переменных
К ак п р и покупке н ед в и ж и м о сти , в Jav aS crip t б ольш ое зн а ч е н и е и м еет
м ес то п о л о ж е н и е . В « П р и к л ю ч ен и ях » у ч и ты в а ется м есто со зд ан и я
п ер ем ен н ы х . Н е случайн о п е р е м е н н а я c u r S c e n e п о я в и л а сь вн е м етод а
c h a n g e S c e n e ( ) , в т о в р е м я как п е р е м е н н а я m e s s a g e — в н утри него.
Все д ел о в о б л а с т и в и д и м о с т и , управляю ш ;ей ж и зн е н н ы м ц и кл ом п е р е ­
м е н н о й и о п р ед ел яю щ ей , как о й код и м е е т к н е й доступ.
196
глава 4
принятие решении
Область Видимости
в Jav aS crip t о б л асть в и д и м о сти о п р е д е л я е т сп особ д оступа к д ан ­
ны м. Н е к о т о р ы е д ан н ы е ви д и м ы для всего с ц е н а р и я , в т о в р е м я
как в и д и м о сть других о г р а н и ч е н а ф р а гм е н т о м кода, н а п р и м е р
м етодом . Р ассм о тр и м п е р е м е н н ы е, ж и вущ и е в р а зл и ч н ы х об ла­
стях:
v a r х;
f u n c t i o n d o S o m e th in g (2 )
Глобальная п ер ем ен н а я ,
видим а для всего сценария.
{
var у;
Л о ка ль н а я п ер ем ен н а я ,
видим а т о ль к о вн у т р и
м ет ода.
}
В д ан н о м коде х н а зы в а е т с я глобальной п е р е м е н н о й , т а к как
о н а б ы ла со зд ан а в н е м ето д а и л и л ю б о го другого ф р а гм е н т а кода
и, сл ед о в ател ьн о , ви д и м а для всего с ц е н а р и я . Б о л е е то го , х «жи­
вет», п о к а р а б о т а е т сц е н а р и й . А во т у — эт о локальная п е р е м е н ­
н ая, в и д и м о сть к о т о р о й о г р а н и ч е н а м ето д о м d o S o m e th in g () .
О н а сущ ествует т о л ь к о во в р е м я р а б о т ы это го м ето д а — созд ается
п р и его запуске и у н и ч то ж ается п о сл е зав е р ш е н и я .
Глобальные п ерем енны е
с у щ е с т в у ю т все вр ем я
жизни сценария.
А ч т о м о ж н о сказать п р о ар гу м ен т м ето д а d o S o m e th in g {) — г?
А ргум енты м ето д о в а н а л о ги ч н ы уже и н и ц и а л и зи р о в а н н ы м
ло кал ьн ы м п ер ем ен н ы м . Т ак ч т о г и м е е т ту ж е самую об ласть
ви д и м о сти , ч то и у, и доступн а то л ь к о в н у тр и метода.
Л ока льны е п ер ем енны е с о з ­
д а ю т ся и уни ч т о ж а ю т ся
о с о о т в е т с т в и и со своей
о б ла с т ь ю ви ди м о ст и
П о во зм о ж н о с ти следует о г р а н и ч и в а т ь в и д и м о сть дан ны х. Э то
п о м о гает и зб е ж а ть и х сл у чайн ого р е д а к ти р о в а н и я . П оэтом у в ез­
де, где т о л ь к о м о ж н о , и сп о льзу й те л о к а л ь н ы е п е р ем е н н ы е.
Ш ТУРМ
Как использовать локальные и глобальные переменные в коде «Приклю­
чений нарисованного человечка»?
далее ►
197
приключения с местом переменных
ПроВерилл область Видимости
Т е п е р ь , в о о р у ж ен н ы е сведен и ем об о б л асти в и д и м о сти , взгл ян ем
ещ е р а з н а п е р е м е н н ы е н аш его с ц е н а р и я. Э то п о зв о л и т лучш е п о ­
н ять, почем у п е р е м е н н ы е следует со зд авать в р а зн ы х м естах.
Значение п ер ем енно й
m essage каждый р аз
сбрасы вает ся м е т о д о м
changeSceneQ , п о э т о м у
сд ела ем ее локальной.
<script type="text/javascript">
// Выбираем в качестве текущей cueHv П т
var curScene = n ■_
сцену О (Введение|_
function ChangeScene(decision)
// Удаляем описание сцены
{
var message =
Значение п е р е ­
м енной cu rS cen e
задает ся между
вы зовам и м ет о д а
changeScene()., з н а ­
ч и т , э т о гл о б а л ь ­
ная перем енная.
if (curScene == 0)
curScene = 1 ;
,
{
^ ° - n e y begins at a fork in the road.
\ ^ e l s e if (curScene == 1) {
if (decision == 1) {
curScene = 2
,
-
-Y O U
^
l i t t l e . . , . . ;
else {
curScene = 3 ;
on t h e b t i d , , . . . . . ,
,
else if
(curScene == 2)
{
</script>
В оп р о с в то м , нуж но л и с о х р а н я т ь зн а ч е н и е п е р е м е н н о й вн е об ла­
сти в и д и м о сти м ето д а changeScene ( ) . Д л я п е р е м е н н о й message,
зн а ч е н и е к о т о р о й с б р асы в ается каж ды й р аз п е р е д н ач ало м р аб о ты
м етод а, это го н е тр ебу ется. А в о т п е р е м е н н ая curScene и сп ользует­
ся для п р о в е р к и усл о ви я в н еск о л ьк и х о п е р а т о р а х i f / e l s e , поэтом у
е е зн а ч е н и е д о л ж н о с о х р а н я т ь с я в н е за в и с и м о с ти о т в ы зо в а м етода.
В итоге получаем, что переменную message имеет смысл сделать
локальной, в то время как переменная curScene в нашем приме­
ре должна быть глобальной.
198
глава 4
принятие решении
Где )кивут мои данные?
Е сли п о н я т и е о б л а с ти в и д и м о сти все ещ е о с т ает с я д ля вас н е­
я сн ы м , р а зл и ч н ы е ч ас ти с ц е н а р и я м о ж н о п р е д став и ть в виде
к о н т е й н е р о в , в к о т о р ы х ж и вут н аш и д ан н ы е. К п р и м еру, сц е­
н а р и й « П р и к л ю ч ен и й » и м е е т н еск о л ьк о о б л астей ви д и м ости ,
к о т о р ы м м огут п р и н а д л е ж ат ь дан н ы е.
А о к а л ш й Я об ласт ь
ГАобал»наЯ^^
^ереМ бН КйЯ .
^ ^
Глобальная о б ласт ь
ви д им ост и или
уровень сценария.
видимости или
и р о б е н ь мгт ода
< s c п p t t y p e = " te x t/jQ V a S C r lp t" > '
скапдеЗсепеО^
^
'
function сИапдеЭсепеО {
if (сигЗсепе == 0) {
■!
е1зе if (сигЗсепе == 1) { |
Локальная '
врем енная, ''s
}
Сущ ествует то л ь к о о д н а гл о б ал ьн ая о б л асть в и ­
д и м о сти , все о ст ал ьн ы е я в л я ю т ся л о кал ьн ы м и .
Все, со зд ан н о е н а гл о бал ьн о м ур о в н е, видим о
и з л ю б о й ч ас ти с ц е н а р и я , в то в р ем я как ви д и ­
м о сть л о к а л ь н ы х д ан н ы х о гр а н и ч е н а .
</ЗСГІрП
’
част°
зад аваем ы е
Б о І їр о с Г ь і
Локальная область
видимости для каждого
из составных оп ера"Шоров.
в переменной какого типа сохранить мои данные: локальной или глобаль­
ной?
0 ; Это зависит от способа, которым вы собираетесь использовать данные. Хотя есть
и обобщенное правило. Все переменные нужно стараться делать локальными, превра­
щая в глобальные только те, которые иначе не работают.
далее >
199
локальная переменная против глобальной
Беседа у камина
Локальная и глобальная переменные обсуждают важность рас­
положения данных.
Локальная переменная:
Ф о к у си р о вать ся нуж но т о л ь к о н а то м , ч то
п р о и с х о д и т вокруг теб я. Я п о н я т и я н е им ею ,
ч т о п р о и с х о д и т у со сед ей , и о ч ен ь эти м до­
вольна.
Глобальная переменная;
Д руж ищ е, т е б е следует р а с ш и р и т ь свой кру­
го зо р . В ы йди и з своего к о к о н а и исследуй
о ст ал ьн ы е ч аст и н аш ей всел ен н о й .
З ву ч и т с о б л азн и тел ьн о , н о м н е н р а в и тс я
б езо п а с н о с т ь м о его п о л о ж ен и я . В едь м ен я
н е м о ж е т д о стать н и к т о и з в н еш н его м ира.
М ож ет б ы ть и так, н о п о н и м аеш ь л и ты ,
ч т о т в о я м ал ен ькая ж и зн ь б ессм ы сл ен н а
в о б щ ей схем е сц ен ар и я? Т ы рож д аеш ься
и ум и раеш ь каж ды й раз, когд а в о зн и к ае т
т в о й м ал ен ьк и й м и р о к , в т о вр ем я как я тут
надолго. П о к а ж и в с ц е н а р и й , ж и в а и я.
Ч е с т н о го в о р я , я н е вер ю в р е и н к а р н а ц и ю ,
а для х р а н е н и я д ан н ы х я т а к ж е важ н а, как
и ты . Я п р о с т о н е даю с м о тр е т ь н а себ я всем
и каждому.
З а т о , когда сц е н а р и ю нуж но, ч то б ы н е к о т о ­
р а я и н ф о р м а ц и я б ы ла нед о сту п н а вн е о п р е ­
д ел е н н о го ф р а гм е н т а кода, я н езам ен и м а.
Э то да. Н е могу н е п р и зн а т ь , ч то р а з и л и два
м ен я и сп о л ьзо в ал и н е п р ав и л ь н о , н о м оим
преи м ущ еством я в л я е т с я с п о со б н о сть со­
х р а н я т ь зн а ч е н и е п р и в сех о б стоятел ьствах.
К ак то л ь к о сц е н ар и ю тр еб у ется ф р а гм е н т
д ан н ы х, п о м н ящ и й свое зн а ч е н и е и доступ­
н ы й отовсю ду, зовут м еня.
Зву ч и т зам ан ч и во , н о я все-таки п р е д п о ­
ч и таю п р и в а тн о с т и д оступ н ость и п о с т о я н ­
ство.
И м е н н о п оэтом у л ю ди с ч и таю т, ч т о о б е мы
о д и н а к о в о п о л езн ы .
200
глава 4
принятие решении
часагю
ЧаДаБаеМые
Б оД роС Ь !
Что получится, если в коммента­
рий написать код JavaScript?
; Ничего! Комментарии игнорируются
интерпретатором изуа8сг1р1, поэтому, что
бы вы туда ни поместили, он этого просто
не заметит. Именно поэтому комментарии
порой используются в качестве временно­
го хранения кода при попытках отследить
проблему или попробовать другой подход
к решению задачи.
Может ли строчка кода JavaScript
заканчиваться комментарием?
0 ; Да. в этом случае код все равно за­
пускается, так как он не является частью
комментария. Плюс комментарий вовсе не
обязан занимать целую строчку — он на­
чинается с / / и заканчивается с концом
строки. Поэтом если за / / находится
фрагмент кода, он будет работать.
Почему в конце комментариев не
ставится точка с запятой?
! Комментарии не являются операто­
рами JavaScгipt. Они всего лишь предо­
ставляют дополнительную информацию,
как сноски в книге. Вам следует помнить,
что интерпретатор иауаЗсг1р1 коммента­
рии игнорирует — они предназначены для
людей, а не для программы.
Что означает «уровень сценария»
при создании глобальных перемен­
ных?
; Это самый верхний уровень, рас­
положенный сразу в теге < s c r i p t > .
Уровень сценария располагается вне
методов и других фрагментов кода, и все,
на этом уровне созданное, считается
глобальным. То есть оно существует
все время жизни сценария и доступно из
любой его части.
Локальные переменные хранят временную
информацию, в то время как глобальные
сохраняются все время жизни сценария.
Переменная, созданная внутри со­
ставного оператора, является глобаль­
ной или локальной?
! Составной оператор создает новую
область видимости, поэтому все пере­
менные, возникшие внутри него, являются
локальными. Их можно рассматривать
как временные, так как они возникают
и исчезают при каждом вызове составного
оператора.
Материал, посвященный локаль­
ным и глобальным переменным, вы­
глядит крайне сложным. Это на самом
деле так?
; Не совсем. Главное — запомнить,
что локальные переменные идеальны
для хранения временной информации,
которую не нужно помнить вне метода или
другого фрагмента кода. Если же данные
требуются все время жизни сценария,
нужно использовать глобальные пере­
менные. Вы удивитесь, но большинство
данных в сценариях обычно является
временным, поэтому локальные перемен­
ные используются чаще глобальных.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
Комментарии, в частности, напоминают о коде,
который необходимо добавить позднее.
Не бойтесь писать много комментариев, так как это
делает код более понятным.
Начало однострочного комментария отмечают
двумя косыми чертами ( / / ) .
Глобальные переменные создаются на уровне сце­
нария и сохраняются до конца сценария.
Локальные переменные создаются внутри фрагмен­
тов кода и не видны извне.
Лучше использовать локальные переменные, так как
доступ к ним больше контролируется.
Многострочные комментарии начинаются с / *
и заканчиваются * / .
далее >
201
выбор из многих вариантов
Выбор из пяти
П о м н и т е н аш его сч а с тл и в ч и к а Э рика? К аж ется,
он п о к о н ч и л с п о н ч и к а м и и п ер еш ел н а следующ;ий тур шоу «Заклю чи м сделку?» И т е п е р ь п ер ед
н и м с т о и т д ей с тв и те л ь н о сл о ж н ая зад ач а — нуж но
в ы б р ат ь о д и н и з п я т и в ар и ан то в .
О боже... кажется,
мне не обойтись без
помощи.
Ш ТУРМ
Каким образом вы написали бы на
иауаЗспр! сценарий выбора из пяти
вариантов?
202
глава 4
принятие решении
А нельзя ли для этой цели
воспользоваться набором
вложенных операторов if/else?
Выбор из пяти
З а м е ч а т е л ь н а я идея! Сам по себе о п е р а т о р i f / e l s e п о ­
зв о л я е т в ы б р ат ь о д и н в а р и а н т и з двух, н о н а б о р и з таки х
о п е р а т о р о в , вл о ж ен н ы х друг в друга, п о зв о л я е т в ы б и р а ть
и з какого угодн о к о л и ч е ст в а в ар и ан то в.
if
( c h o s e n C a s e = = "А ")
o p en C ase("А ");
e ls e
if
( c h o s e n C a s e = = "В ")
o p en C ase(" В " );
e ls e
if
( c h o s e n C a s e = = "C ")
o p e n C a se ("C ");
e ls e
К од р а б о т а е т , но., чт обы
добрат ься до последнего
чем одана, нужно вы п о лн и т ь
п р о ве р к у п я т и услойии,
ч т о неэф ф ект ивно-
if
(c h o se n C a se =
"D ")
o p e n C a se ("D ");
e ls e
if
(c h o se n C a se =
"E ")
o p e n C a se ("E ");
ПереусАО)кнение конструкции
В л о ж ен н ы е о п е р а т о р ы i f / e l s e п р е к р а с н о р аботаю т... н о он и
н е э ф ф е к т и в н ы в о сн о вн о м потом у, ч то н е п р е д н а зн а ч е н ы для
в ы б о р а и з б о л е е чем двух в ар и ан т о в . Д о с та т о ч н о п о сч и тать,
ско л ьк о р а з п р и д е т ся осущ естви ть п р о вер к у услови й , п реж д е
ч ем м ы д о б е р ем с я до п о сл ед н его ч ем о д ан а Е. Ч т о б ы его о т ­
к р ы ть, н ам п о тр еб у ется п р е д в а р и т е л ь н а я п р о в е р к а ещ е ч е т ы ­
р е х условий.
далее ►
203
желания, надежды и выбор
Разве не здорово было бы вы­
бирать из множества вариантов без
набора эти х неэффективных опера­
торов if/e ls e ?
204
глава 4
принятие решений
Оператор switch / case
позволяет эффективно
выбирать из множества
вариантов.
Оператор switch/case
Д л я т е х случаев, когд а тр еб у ется сдел ать в ы б о р и з м н о ­
ж еств а в а р и а н т о в , в Jav aS crip t сущ ествует с п е ц и а л ь н ы й
о п е р а т о р . О н н а зы в а е т с я s w i t c h / c a s e , по п робуем с еего
пом ощ ью о б л е гч и т ь в ы б о р Э рика:
В т о р а я ч а ст ь н а ­
звания о п е р а т о р а
никак не связана с
и м е н е м п ер ем енно й , s w i t c h
(c h o se n C a se )
{
Содерж имое чем одана, выбранного
Э р и ко м , — э т о к о н т р о л и р у е м ы й
кусок и н ф о р м а ц и и для о п ер а т о р а
sw itch /ca se.
К од, определян)ш ,ий, какие дейст вия
с ле д у е т п р е д п р и н я т ь , р а сп о ла га ет с я
сразу п о сле о п ер а т о р а case.
О п е р л т о ^ case
п р е д с т а о ля е т
в а м все возмож ные
вариант ы .
openC ase("С ");
b re a k ; ^
_
кЗ и т
зл к а н и а б й е т
S h
возмож ных ве т о к
выбора, нем едленно заверш ая
р а б о т у о п ер а т о р а s w itc h /
case.
О п е р а т о р sw itc h /c a se по
с т р у к т у р е н а п о м и н а ет
больш ой сост авной опер а т о р .
:нени2
Правда или ложь? Оператор s w i t c h / c a s e обладает той же функциональ­
ностью, что и оператор i f / e l s e .
П
П равда
О
Ложь
далее >
205
выбираем
^.
—
П рЗЖ Н бНИ б
Правда или ложь? Оператор s w i t c h / c a s e обладает той же функциональностью, что
и оператор i f / e l s e .
решение
и
П равда
И
Ложь
У оператора i f / e l s e в качестве проверяемого
условия может выступать выражение, в то время
как у оператора s w i t c h / c a s e это должен быть
просто фрагмент данных.
Анализ оператора switch
Т еп е р ь , когда вы п о с м о т р е л и н а о п е р а т о р s w i t c h / c a s e в д ей ств и и ,
п о с м о тр и м б о л ее в н и м ате л ьн о н а его си н так си с и ф ун кц и о н ал ьн о сть.
switch
Выражение д л я с р а в н е н и я
С о вп а д е н и е 1
Каждый из ва р и а н т о в
выбора начинает ся
с клю чевого слова case,
за к о т о р ы м с ле д у е т
значение для сравнения.
Оператор
break
3 - а ' ^
з-а
J - Q - Ш
В качест ве у с л о ­
вия и с п о ль зует ся
ф р а г м е н т данных,
а не выраж ение —
с о о т ве т с т ве н н о , оам
не нужно оцениват ь
его и ст и н н о ст ь.
После ф р а гм е н т а данных,
с к о т о р ы м о су щ ест в ля е т ся
сравнение, с т а в и т с я двоет очие
й не т очка с запят ой.
default
г
Необязательный блок
"d e fa u lt” ^содержит код,
ко т о р ы й за п у с к а е т с я
при отсутствии со­
впадений.
а
Оператор
□ • а
О п е р а т о р break
предот вращ ает з а ­
п у с к кода из д р уги х
вет ок.
break
Тело о п ер а т о р а заклю чено
о ф игурны е скобки.
206
глава 4
принятие решении
Ваш собственный оператор Switch
С о зд ать о п е р а т о р s w i t c h / c a s e с л о ж н ее, ч ем о п е р а т о р i f / e l s e ,
зато о н я в л я е т с я б о л ее эф ф е к т и в н ы м в случае м н о ж ест в ен н о го вы ­
бора. С ледуйте прави лам :
У сл о ви е зак л ю ч и те в ско б ки и о т к р о й т е со став н о й
оператор ({ ).
©
О
Н а п и ш и т е c a s e и у словие, а п о то м д в о е т о ч и е ( : ).
Н а п и ш и т е код, запускаем ы й в случае с о в п а д е ­
н и я . О н м о ж ет б ы ть м н о го стр о ч н ы м . С о став­
н о й о п е р а т о р тут н е нуж ен.
Q
Д о б ав ь те о п е р а т о р b r e a k и то чку с за п я т о й ( ; ).
^
П о ж ел ан и ю со зд ай те б ло к d e f а и 1 1 для
случая, когда с о в п ад ен и я отсутствую т.
З а к р о й т е с о с та в н о й о п е р а т о р ( } ) .
_
часл1°
_^адаБаеМые
БоЦ|=»ос;ьх
То есть оператор s w i t c h / c a s e не
принимает решений на основании выраже­
ний вида t r u e / f a l s e ?
Q ; Да, в отличие от операторов i f
и i f / e l s e , s w i t c h / c a s e принимает ре­
шение на основе тестовых данных. Именно это
позволяет выбирать из множества вариантов.
То есть нам всего лишь нужно совпаде­
ние с тестовыми данными?
Q ; Да. в качестве тестовых данных использу­
ется переменная, со значением которой и идет
сравнение.
Что произойдет при отсутствии ключе­
вого слова b r e a k ?
)удыпе
осЗХ Ю роЖ Н ь!
1
Break для
безопасно­
сти.
Этот
оператор
устраняет возможность
случайного запуска ненуж­
ных фрагментов кода.
Q ; Оператор b r e a k является разделителем
между блоками кода оператора s w i t c h /
c a s e . Без них все фрагменты кода были бы за­
пущены просто в порядке очереди, что не имеет
никакого смысла, так как выбор при этом не
делается. В случае же совпадения запускается
код после соответствующего оператора c a s e
вплоть до оператора b r e a k . После этого
s w i t c h / c a s e завершает свою работу.
далее >
207
операт ор switch о себе
О П Е Р А Т О Р
о
Й Ё Б Ё
Интервью недели:
М астер н а все руки
Head First: С паси бо , ч то со гл аси л и сь п о б е ­
сед о в ать с нам и. П ож алуйста, о п и ш и те себя
о д н и м словом .
Switch: Р азб о р ч и в ы й .
Head First: У то ч н и те , пож алуйста.
Switch: Я п р ед о став л яю в о зм о ж н о с ть в ы ­
б и р а ть между м н о ж ество м веш:ей. И н о гд а до­
с т а т о ч н о в ы б р ат ь между ч ер н ы м и б елы м , но
и н о гд а следует у ч и ты в ать ню ансы . В от тут-то
и п о я в л я ю сь я.
Head First: Н о го в о р я т, ч т о о п е р а т о р I f
ум еет д ел ать т о ж е сам ое, и н о гд а с м еньш им
ко л и ч еств о м кода.
Switch: М о ж ет б ы ть и так. М ож но и о тр у б и ть
кусок д ер е в а м о л о тк о м , есл и б и ть п о нему
д о ст а т о ч н о д олго. Н о л и ч н о я п р е д п о ч и т а ю
пилу. П усть каж ды й за н и м ае т с я своим делом .
Н и ч е г о н е и м ею п р о т и в о п е р а т о р а If, н о эт о т
и н стр у м ен т п р е д н а зн а ч е н д ля другой р аб о ты .
Head First: Вы го в о р и л и об эф ф е к т и в н о с т и .
К аки м о б р азо м о н а в л и я е т н а ваш у работу?
Switch: Я п р и н и м а ю р е ш е н и е н а о с н о в е зн а ­
ч е н и я ф р а гм е н т а д ан ны х. П р о и зв о ж у с р а в н е ­
н и е и о п р ед ел яю , как о й код запустить. Я н е
вы ч и сл яю зн а ч е н и я в ы р а ж е н и й и н е требую
вл о ж ен н о сти . Я всего ли ш ь б ы стр о п р и н и ­
маю р еш ен и е.
Head First: Р асскаж и те о ваш ем друге, о п е р а ­
т о р е B reak. Г о в о р я т, вы неразлучны ?
Switch: Д а, б ез о п е р а т о р а B reak я н е см ог бы
р а зд ел и ть ф р а гм е н т ы кода. О н д ае т м н е п о ­
н я т ь , когда следует о с т ан о в и т ь в ы п о л н е н и е
в ы б р ан н о го блока, и я прекраш ;аю работу, не
т р о га я о стал ьн ы е блоки.
208
глава 4
Head First: А ч т о н а с ч е т о п е р а т о р а Case?
Switch: С о п е р а т о р о м Case у м ен я о ч ен ь
б л и зк и е о т н о ш ен и я , ведь и м ен н о о н п о к а­
зы в ае т м не ва р и а н т ы , с к о т о р ы м и следует
ср а в н и в а т ь т е с т о в ы е д ан н ы е. Б е з н его я н е
см ог бы п р и н и м а т ь р еш ен и я .
Head First; Т о есть о п е р а т о р Case п р ед о с тав ­
л я е т вам в ар и а н т ы , а вы н а и х о сн о в е о п р ед е­
л я е т е , ч т о д елать. А ч т о п р о и сх о д и т , когда
со вп ад ен и й нет?
Switch: Если н а эт о т случай н е д об авл ен о т ­
д ел ьн ы й код, т о н и ч его . Н о м ой д о б р ы й друг
D efault д ает во зм о ж н о сть д о б ави ть т а к о й код.
О н и запускается п р и о тсутстви и совп ад ен и й .
Head First: Я и н е знал. А как D efau lt уж и вает­
ся с Case?
Switch: П р е к р а с н о . И м н е ч его д ел и ть,
каж ды й п р о с т о в ы п о л н я е т свою работу. Case
о б р аб а т ы в ае т совп ад аю щ и е р езул ьтаты , в т о
в р е м я как D efau lt за б о ти тс я о ситуац и и , когда
со в п ад ен и й н е оказы вается. Б о л е е т о го , м не
к аж ется, ч т о C ase чувствует себя с п о к о й н е й
в п р и су тстви и D efault, т ак как, есл и совп ад е­
н и й н е о б н аруж и вается, о н н а ч и н а е т н е р в н и ­
ч ать.
Head First: П он и м аю . Ч т о ж, н аш е вр ем я
зак а н ч и в ается . Х о ти те что-нибудь сказать
нап оследок?
Switch: К о н е ч н о . П о м н и те, ч то н е т н и ч его
хуже н е р е ш и т е л ь н о сти . Т ю ф я к о в н и к т о н е
л ю б и т. Н а л и ч и е сли ш ком м н о ги х во зм о ж ­
н о с т е й н е о зн ач а ет, ч т о нуж но опускать
руки. З в о н и т е м не, и я пом огу вам п р и н я т ь
р еш ен и е, к о т о р о е лучш е всего п о д х о д и т для
ваш его сц ен ар и я.
принятие решений
Возьми в руку карондаш
П е р е п и ш и те перв ы е д в е сцены « П р и кл ю ч е н и й » , за м е н и в о п е р а ­
то р i f / e l s e о п е р а т о р о м s w i t c h / c a s e .
if
( c u r S c e n e == 0)
(
Ь«1»= = . . « " rt “
^
Lise i f (cutscene == 1) I
Э т о исходная в е р ­
сия кода, в кот о р о й
и с п о л ь зуе т с я опера^
т о р if/else.
■if ( d e c i s i o n — i) i
Г е Г з Г .Г /'4 о и h av e a r r i v e d a t a c u t e U t t i e h o u s e i n t b e wood . ,
^ 'i s b r / 4 ; u
a r e s t a n d i n g on t b e b r i . . e o v e r i o o K i n . a p e a c e f u l
s t r e a m . ";
далее >
209
решение упражнения
щ^ьт в руку карандаш
Вот к а к будут вы глядеть перв ы е д в е сцены « П р и кл ю ч е н и й » п о ­
сле зам ены о п е р а т о р о в i f / e l s e о п е р а т о р о м s w i t c h / c a s e .
Решение
if
( c u r S c e n e == 0)
{
m e s s a g r = ^ 4 o u r jou rney b eg in s a t a fo rk in th e ro a d ." ;
e l s e i f ( c u r S c e n e == 1)
i f ( d e c i s i o n == 1) {
Исходная версия
кода.
{
m e s s a g r / 4 o u h ave a r r i v e d a t a c u t e l i t t l e h o u s e i n t h e w o o d s ." ;
}
e lse {
m e s s a g r = ^ " ? o u a r e s t a n d i n g on t h e b r i d g e o v e r l o o k i n g a p e a c e f u l
s t r e a m . ";
}
З а д а ет новый ном ер
и описание сцены , как
и в преды дущ ей версии.
1
swiicn {CUrScene) I
Оператор case
'предост авляет
для сравнения
н о м е р Сцены.
case О:
curScene = 1 ;fce^fns at a fork in the road.”;
break;
В н у т р и каждого о п е ­
р а т о р а case и м е е т
СМЫСЛ во с п о л ь зо в а т ь СЯ о п е р а т о р о м if/else
для обработ ки р еш ения
п о ль зо в а т е ля о переходе
к след ую щ ей сцене.
case i :
if (decision == i) {
curScene = Z
.............................
message ~ "You have arrived a t a cute little house in the woods.”',
.L .
else {
Для остальных
curScene - 3;
сцен использу­
ется аналогичная
ст рукт ура.
message = You are standing on the bridge overlooking a peaceful stream ,”;
Закроем операт ор
s w itc h /c a se п р и п о ­
м о щ и }.
210
глава 4
принятие решений
Тест-драйВ нового Варианта «Приключений»
Т е п е р ь , когда в о с н о в е п р и н я т и я р е ш е н и я в « П ри к л ю ч ен и ях» л е ж и т совсем
другая л о ги ка, Э лли н е т е р п и т с я п о с м о т р е т ь н а результат. Н а в е р н о е , и зм е н е ­
н и я будут зам етн ы н ев о о р у ж ен н ы м глазом ...
VJelcONVe t o
ST IC K FIGURE
Click e'rtber
buttoN to
StariPlease
Не всегда правка сце­
нария меняет его внеш­
ний вид. Но это вполне
можно пережить.
У дивл ен ы , ч то н и ч е го н е изм ен и л о сь! Н о ведь о п е­
р а т о р s w i t c h / c a s e п о м ен я л т о л ь к о структуру кода
н аш и х « П р и к л ю ч ен и й » , а н е в н е ш н и й вид. К ак ви д и те,
и н о гд а и зм е н е н и я п р о и с х о д я т за в аш ей с п и н о й ... в бук­
вал ьн о м см ы сле слова!
далее *
211
на чем же мы ост ановимся?
Приключения продол)каются...
Н а сам ом деле м ы то л ь ко н ач ал и р а б о т а т ь над и с т о р и е й . Д л я со ­
зд ан и я д ей с тв и те л ь н о и н т е р е с н о г о в еб -п р и л о ж ен и я п о тр еб у ется
х о р о ш и й с ц е н а р и й , к а ч е с тв е н н а я г р а ф и к а и д о п о л н и т е л ь н ы й код
Jav aS crip t. Куда бы нам т е п е р ь н ап р ави ть ся?
Сцена ?
Сцена 8
Сцена ?
Сцена ?
Сцена 9
КОНЕЦ
Сцена ?
212
глава 4
принятие решений
Вкладка
Согните страницу
по вертикали, чтобы
совместить два мозга
и решить задачу.
Когда не хватает if/e lse ...
_
хоРоШо, а ДВа Jiyiffle
С це на 7
ВбеЭенме
f,OMV^O
(Svv^t^p) I
С ценаї
Р азвилка
на дороге
Хотя оператор if / else кршне
полезен, оп имеет ограничения.
Например, невозможно выбрать из
множества вариантов. Если
вы не верите, убедитесь сами.
U -K JT b i
Говорят, что повторение — мать учения.
Заниматься новыми и ин­
тересными делами здорово, но наши дни, как правило, состоят из рутины.
Доведенное до автоматизма мытье рук, нервный тик, щелчок на кнопке Reply
То АН при получении любого дурацкого сообщения! Кажется, повторение не
самая лучшая вещь в этом мире. А вот в мире JavaScript без него никак. Вы
удивитесь, как часто бывают востребованы одни и те же фрагменты кода.
Здесь вам на помощь приходят циклы. Без них пришлось бы снова и снова
набирать один и тот же код.
"стадии" поиска сокровищ
М есто помечено крестом
С ам ое с о б л а зн и т е л ь н о е в м и р е —эт о чуж ие зар ы
т ы е со кр о ви щ а. В от кар та, к о т о р о й вы см о ж ете
в о с п о л ь зо в аться п р и по м о щ и JavaS cript.
3 7 шагов.
О И д и те, п о к а н е увидите
скалу в ф о р м е поч атк а.
С н ач ал а 37 ш а­
гов н а восток.
;т указы вает место!
С н ач ал а вам нуж но п о в т о р и т ь д ей ств и е (ш аг) у казан н ое к о л и ч е ­
ств о р аз (37). С д елать 37 ш агов — о зн а ч а е т п о в т о р и т ь о д и н ш аг
37 раз.
Ш аг я вля ет ся п о ­
вт о р я ю щ и м с я Эей
ст ви е м .
4,7
сскро.
ГОВ « а
3 7 циклов
3 7 ш агов ~ эт о
на сам ом деле 1
-ш аг, повт оренный
37 раз.
О стал о сь п о н ять, каким о б р азо м в Jav aS crip t р еал и зую тся п о в т о р е н и я .
216
глава 5
циклы
Цикл for позволяет
повторить код
нужное количество
раз.
U снова де)кавю... цикл for
П о в т о р е н и е в Jav aS crip t р еал и зу ется п р и п о м ощ и ц и клов.
Н а п р и м е р , ци кл f o r п о зв о л я е т п о в т о р и т ь ф р а гм е н т кода
нуж ное ко л и ч е с т в о раз. О н п р е к р а с н о п о д х о д и т для п о д сч ета
к о л и ч е с т в а п о в т о р я ю щ и х с я д ей стви й .
С о ст о и т э т о т ц и кл и з ч е т ы р е х частей:
И н и ц и а л и за ц и я
о
И нициализация
И м е е т м есто о д и н р а з в н а­
ч ал е ц и к л а f o r .
©
О
П р о в е р ка условия
о
У сл о ви е п о к азы в ает, следует
л и п р о д о л ж а ть в ы п о л н е н и е
цикла.
Д е й с тв и е
С о б ств ен н о код, к о т о р ы й
п о в т о р я е т с я в п р о ц е сс е
р а б о т ы цикла.
О б н о в л ен и е
в э т о й ч ас ти о б н о в л я ю тся
зн а ч е н и я всех п е р е м е н н ы х
цикла.
■■■
■■■
■■■
■■■
■■■
'
— V ----- —
Ш ТУРМ
Один шаг цикла.
В т о р о й ш аг цикла.
Каким образом четыре стадии цикла f o r
помогут нам в поисках сокровищ?
далее >
217
цикл for: подсчитаем
Охота за сокровищами с циклом for
Ц и к л f o r по д х о ди т для р а б о т ы с к а р т о й , так как вкл ю ч ает в себя
и зв е с т н о е ко л и ч е с т в о ш агов. Его п р и м е н е н и е к п е р в о й ч асти п о и с­
ка будет в ы гл яд еть п р и м е р н о так:
О
О
О
for (var X = 0; X < 37; х-1-+)
Л
И нкрем ент X —
э т о т о ж е сам ое,
чт о U X = X +- І .
takeStep();
О
В и а у а З сп р Ь о т ­
сч ет раб от ы цикла
начинает ся с о ,
х о т я его мож но
н а ча т ь и с 1 .
В от а н ал и з ко д а ц и кл а f o r :
П е р е м е н н о й X п р и с в о и м н а ч а л ь н о е зн а ч е н и е 0.
П р о в е р и м , м ен ьш е л и х, чем 37. Если да, п е р ей д е м к ш агу 3
и п р о д о л ж и м ци кл. Е сли н ет, вы йд ем и з ци кла.
Запустим код ци кла. В д ан н о м случае эт о ф ун кц и я
ta k e S te p ().
У вел и ч и м зн а ч е н и е х н а 1 и в ер н е м с я ко втором у шагу.
П о сл е 37 ш агов х ст ан е т р а в е н 37, и ц и кл завер ш и тся . В от
каким о б р азо м в Jav aS crip t р еал и зу ю тся повторяю ш ;иеся
д ей ств и я.
И нициализация
Q
Ц и к л н а ч и н а е т с я п р и х,
р а в н о м 0.
var X = О
П р о в е р ка условия ©
С ледую щ ий ш аг ц и кл а
со в е р ш а ет ся то л ь к о
п р и условии, ч т о X
м ен ьш е 37.
X < 37
Д ействие
В ы зы вается ф ун кц и я
ta k e S te p {).
37 циклов
ta k e S te p О
Обновление ^
З н а ч е н и е сч е т ч и к а х уве^,
л и ч и в а е т с я н а 1.
Х++
218
глава 5
^
И н к р е м е н т X озн ачает
X = X + 1.
циклы
Составные части цикла for
К аж д ы й к о м п о н е н т ц и кл а f o r д о л ж ен н ах о д и ться н а п р е д н а зн а ч е н ­
ном ему м есте. В п р о ч ем , сущ ествует м н о ж ество в о зм о ж н о с те й н ап и ­
сать св о й с о б с т в е н н ы й ци кл f o r .
На эт олл э т а н е значение с ч е т ­
чика обычно увели ч и ва е т с я или
Цикл начинается
ум е н ь ш а е т с я на 1.
Здесь задает ся
с клю чевого слооа
начальное значение
for.
.
счет чика.
f
A c tio n
П роверка условия-,
оозвраицает ся р е з у л ь т а т tr u e или
fake.
)
П овт оряю ш ,иеся дей ст ви я
м о г у т бы т ь описаны как
единичи1?(М^ т а к и с о с т а в ­
ны м о п е р а т о р о м .
М
.
/
Инициализация, проверка
цсловия и изменение п о ­
казаний счетчика з а к л ю ­
ч а ю т с я в скобки.
Точка с за п я т о й
' ст а ви т с я после кода
инициализации и кода
п р о вер ки условия.
-------------------------------------Завершите код, который
сначала предлагает пользователю ввести число больше О,
а затем использует его в качестве начального значения счетчика цикла f o r , выполняю­
щего обратный отсчет до начала фильма (4, 3, 2, 1, Roll film!). Перед началом обратного
отсчета не забудьте удостовериться, что введенное значение действительно больше 0.
•У п р аж н ен и е
С о х р а н и т е ббеЭенное
число б п е р е м е н н о й -^
^р^Ш гТ т ся
—
.
^
var count ■= prompt("Enter а number greater than 0:", "10");
далее »
219
решение упражнения
Вот как выглядит код, который сначала предлагает пользователю ввести положительное
число, а затем использует его в качестве начального значения счетчика цикла f o r , вы­
полняющего обратный отсчет до начала фильма (4, 3, 2, 1, Roll film!).
нение
ение
Ч исло сохраняет ся
в п ер ем ен н о й count.
Пользователю
предлагается '
е с т и число.
обрат ны й
_от счет
Л
У б еди м ся. чт о
c o u n t = p r o m p t( " E n te r а number greater than О:",
!^ерем енная
.................................................
count больше о if (count > o) {
............. ............... Ф ..................................................................................................
w r (var X = count; x > О; у - - )
Г
П рисвоим
счет ч и ку
цикла (х)
значение
пер ем ен н о й
co u n t.
......чаг............................
a le r t(" S ta r tin g in..." + x
alertC'Roll F ilm !"^
,
Мй каждом
ш аге ц и к ­
ла значение
счет чика
ум е н ь ш а е т с я
на 1 .
'екуицее
значение
перем енно й
count.
}
else
alertC 'The n u m b e r wasn’t greater th a n o . No m o vie fo r you!");
Н екоррект ны е
■данные. ......................3
—
^ ..................................................................
The number wasn’t greater than 0. No movie for you!
RoUfilml
Специальные места для мачо
О б р ат н ы й о т с ч е т до нач ала сеанса — это н е ед и н ств ен н ы й
эп и зо д , в ко то р о м ц и кл ы могут б ы ть и сп о л ьзо в ан ы в ки н о ­
те ат р е . М ож ет бы ть, вы слы ш али, ч то м ачо требую т, ч то б ы
между н и м и б ы ло пустое кр есл о . П оэтом у С ет и Д ж ей со н
р еш и л и создать програм м у M an d an g o , осущ ествляю ш ую п о ­
и ск пусты х кр есел в к и н о театр е.
Д рузьям требую тся группы и з т р е х м ест, ч то б ы между ни м и
всегда оставал о сь свобо д н ое кресло. Н о п о ка о н и еш;е не
зн аю т, как п о д о й ти к р еш ен и ю д ан н о й проблем ы .
220
глава 5
Отсчет за ­
кончен!
циклы
проверка доступности м ест
П ар н я м нуж но п р о в е р я т ь каж ды й р я д н а н а л и ч и е р ас п о л о ж е н ­
н ы х п о д р яд т р е х сво б о д н ы х кресел.
Свободно всего
одно м ест о .
Все т р и hhicwKO.
свободны!
Все т р и м е с т а
занят ы .
J
Классно!
Плохо
Т р и свобод н ы х кресла,
сто ящ и х п од ряд, даю т н а­
стоящ ем у м ач о нуж ное п р о ­
стр ан ство .
Все в а р и а н т ы , о т л и ч н ы е от
т р е х сто ящ и х п о д р я д свобод ­
н ы х к р есел , н е п о зв о л я ю т п о ­
к а за т ь «мачизм».
5озьми1 в руку карандаш
_^Возьм
Взяв за о сно ву р и с у н о к снизу, п о к а ж и те , ка ки м о б р а з о м при
■
V
п о м о щ и ц и кл а f o r
вы будете и скать м еста для н а ш и х м ачо.
далее >
221
решение упражнения
Возьми в руку карандаш
Решение
И так, вот к а к и м о б р а зо м при п о м о щ и ц и кл а f o r м о ж н о найти
по д х о д я щ и е места для м ачо.
П редст авив д о с т у п н о с т ь м е с т а в виде логической п е р ем ен н о й ,
нужно н а й т и п р и п о м о щ и цикла м р и подряд значения tru e.
-луКонйц цикла.
false
tr u e
false
tr u e
tr u e
tr u e
false
tr u e
false
Н ачало
цикла.
М е с т о за ­
нят о.
Всего одно
м е с т о сво
бодно.
М есто
занят о.
Т ри подряд!
Циклы, HTML U свободные кресла
О с н о в н ая и д ея п р о гр ам м ы M a n d a n g o п о н ем н о гу ст ан о в и т ся п о ­
н я т н о й , но каким ж е о б р азо м за п и с ать ее в ви д е код а H TM L?
HTM L и гра­
фические
Фрагменты
для этого
прим ера м о ж ­
но скачать
по адресу
h ttp ://w w w .
headfirstlabs.
со м /b o o k s /
hfjs/.
222
глава 5
<img
<img
<img
<img
<img
<img
<img
<img
<img
id = "se a tl"
id = "seat2"
id= "seat3"
id = "se at4 "
id = "seat5"
id = "se at6 "
id = "seat7"
id = "se at8 "
id = "se at9 "
На ст р а н и ц е M andanqo
осе кр есла показаны
о оиде рисунков.
s r c = ' s e a t_ u n a v a i l . p n g " a l t - " U n a v a i l a b l e
s r c = ' 'se at_ a v a i l . p n g " a l t = " A v a i l a b l e " />
s r c = ' 'se at_ u n a v a i l . p n g " a l t = " U n a v a i l a b l e " />
sr c = ' 'se at_ 'avail.png" a l t = " A v a i l a b l e " />
s r c = 'se at_ "avail.png" a l t = " A v a i l a b l e " />
s r c = 'seat_ "avail.png" a l t = " A v a i l a b l e " />
s r c = ' s e a t ^ unavail.png" a l t = " U n a v a i l a b l e " />
s r c = ' s e a t a v a i l . p n g " a l t = " A v a i l a b l e " />
s r c = " s e a t "unavail.png" a l t = " U n a v a i l a b l e " />
Вам нуж но н е т о л ь к о п р о с м о т р е т ь п р и п ом о щ и ц и к л а гр а ф и ч е с к и е
ф р а гм е н т ы с и зо б р а ж е н и е м кр есел , н о и с о х р а н и т ь и н ф о р м а ц и ю
о д о сту п н о сти м ест в коде JavaS cript.
циклы
М еста, как переменные
П ер е д тем как п р и сту п и ть к в ы п о л н е н и ю ци кла, нуж но п р ед став и ть и н ф о р ­
м ацию о д о сту п н о сти каж дого кр есл а в ви д е кода JavaS cript. Д л я р я д а и з д евя ­
т и кр е с е л вам п о тр еб у ется д ев я т ь л о ги ч ес к и х п ер ем ен н ы х .
var seatl = false;
Информации 0 доступности
каждого м е с т а х р а н и т ­
ся в виде пер е м е н н о й т и п а
boolean.
var seat2 = true;
var seats = false;
var seat4 = true;
var seats = true; ^
_True о зн ачает , ч т о
м е с т о свободно.
var seat6 = true;
var seat? = false;
False о зн ачает ,
чт о м ест о з а ­
нят о.
var seats = false;
Получается, я дол­
жен просматривать
различные фрагменты
данных с помощью все­
го одной переменной?
var seat9 = false;
Т е п е р ь все го то в о д ля со зд ан и я ц и кл а f o r , к о т о р ы й будет
и ск ать т р и сво бо д н ы х м еста подряд.
о
о
for (var і = 0; і < 10; і++) {
if (seatl)
Вы не м ож ет е м е н я т ь
и м я п ер ем ен н о й при
каж дом прогоне цикла!
}
К аж ется, у нас п р о б л ем а. Ц и к л f o r д о л ж ен п р о в е р я т ь зн а ч е н и я
р а зл и ч н ы х п е р е м е н н ы х s e a t н а каж дом ш аге. Н о т а к как все
п е р е м е н н ы е и м ею т р а зн ы е и м ен а, эт о п о п р о сту н ево зм о ж н о .
U T V P M
Каким же образом сохранить информацию в том случае,
когда отдельные переменные не работают?
далее *
223
массив данных
Массивы
Jav aS crip t п о зв о л я е т с о х р а н я т ь н а б о р ы д ан н ы х в о д н о й п е р е м е н н о й
о с о б о го ти п а , н азы в а е м о й м ассивом . М ассив, как и о б ы ч н а я п е р е м е н ­
н ая, и м еет всего одно им я, за т о у н е го ц е л ы й н а б о р м ест для х р а н е ­
н и я. П р е д с та в ь те себе ш каф с п о л к ам и — это о д и н п р ед м ет м ебели,
н о с м ассой м ест для х р а н е н и я .
К аж д ы й эл ем ен т м асси ва с о с то и т и з двух ч астей : зн а ч е н и е и уни каль­
н ы й клю ч, по к о то р о м у осуш ;ествляется доступ к этом у зн ач ен и ю .
В р о л и кл ю чей о б ы ч н о вы ступ аю т ц и ф р ы , н а ч и н а я с нуля. Т ак и е
кл ю чи о б ы ч н о н азы в аю тся ин дексам и :
Э т о т массив
хранит пят ь
фрагментов
Индексы массива начинаются
с О и подсчит ывают коли чест во
Численный ключ или
индекс и с п о л ь з уе т с я для
дост упа к значению.
элементов.
Д л я с о зд ан и я м асси ва д о ст а т о ч н о д ать зн а т ь об это м JavaS cript.
П о больш ом у счету вы с о зд аете о б ъ ект.
var showTime = new Array();
_Новый о б ъ ект
т и п а A rra y .
^ м я массива.
Создание нового
объекта.
Не беспокойтесь о том, что
массив является объектом.
Д л я ваш и х текущ их ц ел ей эта
и н ф о р м а ц и я н е и м е ет осо б о го
зн ач ен и я . П о д р о б н о м ы п о го в о р и м об о б ъ ектах
в главах 9 и 10.
224
глава 5
циклы
Значения сохраняются с ключами
М ассив го то в, т е п е р ь в н его м о ж н о д о б а в л я ть д ан н ы е. Д л я до­
ступа к ни м будут и с п о л ь зо в ать с я ключи. К аж ды й клю ч ун и ка­
лен и св я зан со сво и м ф р а гм е н т о м дан ны х.
Сохраняем ое
в п ер ем ен н о й
И м я п ер ем ен н о й
т и п а arra y.
И ндекс эл е м е н т а
м ассива ука зы ва ет ся
в ква др а т н ы х скобках.
Э то т код зад ает п е р в ы й эл е м е н т м асси ва sh o w T im e, п р и с в аи ­
вая ему зн а ч е н и е в р ем ен и . В о зм о ж н а как ин ди ви дуальн ая, т а к
и груп п о вая и н и ц и а л и за ц и я эл е м е н то в м ассива.
Список всех значений
через за п я т у ю .
var ShowTime = [ "12:30", "2:45", "5:00"Г "7:15", "9:30" ];
,
—
и е р в а я чаете? п р о цедуры создания
м ассива о с т а е т с я
без изм енений.
V
^ д
о
Не заб удьт е
м очки с за п я м о й в конце.
Список э л е м е н т о в м а с с и л ж е н бы т ь заклю чен
д квадрат ны е скобки,
“
П о д о ж д и те, это н е п о х о ж е н а со зд ан и е о б ъ екта. Ч т о п рои сходи т?
В д ан н о м случае м ы заб егаем в п ер ед и создаем н е пустой о б ъ ект,
а сразу м ассив со всем и его зн а ч е н и я м и . И м е н н о о н и п е р е ч и с л е н ы
в к вад р атн ы х скобках. Т е п е р ь , когда м ассив за п о л н е н д ан н ы м и ,
мы го то в ы с ни м работать!
В о зь м и т е последний
э л е м е н т м ассива
alert("The late movie starts at " + showTime[4] +
Массивы сохраняют целые
наборы данных в одном
месте.
The late movie starts at 9:30.
далее ►
225
массив о себе
М Л Р С И В
О
(Й Й В Ё
И нтервью н ед ел и :
С екреты х р а н и те л я д а н н ы х
Head First: Р ады в и д еть вас, М ассив. С лы ш ал, ч то
вы ум еете с о х р а н я т ь н а б о р ы дан ны х.
Массив: Д а. Е сли вам нуж но с о х р а н и т ь 50 ст р о к
т е к с т а и л и 300 ч и сел , о б р ащ ай тесь.
Head First: З в у ч и т зам ан ч и в о . Н о ведь д ан н ы е
м ож но сохранить и в обы чной перем енной.
Массив: Р азум еется. А н а р або ту м о ж н о х о д и ть
б о си ко м . В идиш ь л и , н е к о т о р ы е в ещ и м о ж н о д е­
л а ть р а зн ы м и спо со б ам и . В д ан н о м случае б олее
у д о бн ы й сп о со б х р а н е н и я н а б о р о в д ан н ы х п р ед ­
ставл яю и м е н н о я.
Head First: Д а, я п р е д п о ч и т а ю х о д и ть н а р аботу
в б о ти н ках . Н о ч ем и м е н н о вы лучш е других?
Массив: П р ед став ь, ч т о т ы ведеш ь д н ев н и к . К аж ­
д ы й день. Ч т о со всем и эт и м и с т р ан и ц а м и ст ан е т
ч е р е з н еск о льк о лет?
Head First: А ч то с н и м и м о ж ет случиться?
Массив: Т ы сей ч ас п р ед став л яеш ь с т р ан и ц ы ,
каким -то сп о со б о м с о е д и н е н н ы е друг с другом.
А есл и п р е д с та в и ть о б ы ч н ы е л и с т ы бумаги,
склад ы ваем ы е в коробку? Р ан о и л и п о зд н о , теб е
с т ан е т сл о ж н о их с и с те м ати зи р о в а ть .
Head First: Т ы нам екаеш ь, ч т о с о х р а н е н и е д ан ­
н ы х в м асси ве — эт о то ж е сам ое, ч т о и со е д и н е­
н и е о тд ел ь н ы х л и с т о в в книгу?
Массив: И м ен н о . Ведь я си стем ати зи р у ю
д ан н ы е, о б ес п е ч и в а я к ни м л е гк и й доступ.
В д н е в н и к е т ы м ож еш ь н а й т и нужную зап и сь н а
о п р е д е л е н н о й ст р ан и ц е . В случае м асси ва вм есто
с т р а н и ц исп ользую тся клю чи.
Head First: Я слы ш ал п р о и н д ек сы м ассива. А ч то
т а к о е «клю чи»?
226
глава 5
Массив: К лю ч ом н а зы в ае т ся ф р а гм е н т и н ф о р м а ­
ц и и , п р и п ом о щ и к о т о р о г о л егк о н а й ти нуж ны е
д ан н ы е. И н д екс —э т о всего л и ш ь ч а с т н ы й случай
клю ча. Т аки м о б р азо м , н о м е р а с т р ан и ц в д н ев н и ­
ке я в л я ю т ся н е т о л ь к о клю чам и, н о ещ е и и н дек­
сам и.
Head First: Я п о н ял . А каким о б р азо м все это
с в я за н о с циклам и?
Массив: В п р и н ц и п е я могу с о х р а н я т ь д ан н ы е
и б ез уч асти я ц и кл ов. Н о их пом ощ ь уп рощ ает
доступ к м ои м эл ем ен там .
Head First: К аки м образом ?
Массив: П о м н и те, ч т о ц и кл ы и сп ользую т ч и с ­
л е н н ы й счетч и к? О н м о ж ет служ ить и в к ач естве
и н декса, в и т о ге о б л е гч а ется ц и к л и ч ес к и й п р о ­
см о тр х р а н и м ы х во м н е дан ны х.
Head First: Т о ес ть м ож н о и сп о л ьзо в ат ь сч е т ч и к
ц и кл а в кач естве и н д ек са м ассива?
Массив: И м е н н о так.
Head First: Э то п отрясаю щ е!
Массив: Я знаю . И м е н н о п оэтом у м ен я т ак л ю б ят
с ц е н а р и и , в к о т о р ы х н еоб ходи м ц и к л и ч е ск и й
п р о с м о т р д ан н ы х. Н ес к о л ьк о с т р о ч е к кода, и вы
л егко п р о с м а т р и в а е т е ц е л ы й м ассив.
Head First: М огу в о о б р ази т ь . С паси бо, ч то рас­
сказал и о себе и о ваш ей со в м ес тн о й р а б о т е
с ци клам и.
Массив: Н е за ч то. В сегда р ад пом очь!
циклы
Возьми в руку карандаш
Н а п и ш и те ко д со зд ан и я м ассива s e a t s для п р о гр ам м ы M a n d a n g o ,
а затем п р о с м о тр и те в ц и кл е е го элем енты , выводя для пользователя
и н ф о р м а ц и ю о д о с ту п н о с ти к а ж д о го из кр есел .
_
часвдо
чадаБаеМые
В опросы
Возможен ли бесконечный цикл
J y * Можно ли использовать в цикле
fo r?
f or составные операторы?
Q ; Страшный бесконечный цикл?
Конечно, вы можете запрограммировать
цикл, который не закончится, пока вы не
перезагрузите страницу. Но такие циклы
считаются вредной вещью, так как не
дают сценарию перейти к следующей
задаче, — их можно считать эквивалентом
заблокированного приложения.
Q ; Конечно! Более того, во всех случаях,
кроме самых простых сценариев, вам
придется их использовать.
хотя это и не совсем удобно. Поэтому
если у вас нет на то веской причины, не
начинайте нумерацию элементов массива
с чисел, отличных от нуля.
Сохраняемые в массивах данные
должны принадлежать к одному типу?
Когда результатом проверки
условия становится значение false,
выполняется ли цикл в последний раз?
Бесконечный цикл возникает или при
некорректном обновлении счетчика шагов,
или в случае, когда он не меняется и
результатом проверки условия всегда
является значение f a l s e . Поэтому
всегда следует тщательно проверять
Q l Нет. Операторы в цикле for
выполняются, только когда проверка
условия дает результат true.
В противном случае происходит
немедленный выход из цикла и никакой
код не запускается.
условие выхода из цикла f o r . Понять,
что у вас бесконечный цикл, можно по тем
признакам, что сценарий долгое время не
выполняет никаких действий.
3 * Первым индексом массива всегда
является О?
0 ; Вовсе нет. Все зависит от
предназначения массива. Например,
если вы хотите циклически просмотреть
массив оценок и вычислить среднюю, вы
не сможете этого сделать, если часть
значений будет принадлежать, например,
к логическому типу. Поэтому, несмотря
на наличие принципиальной возможности
сохранять в массив данные различных
типов, лучше этого не делать.
Q ; и да, и нет. По умолчанию нумерация
всех числовых массивов начинается с 0.
Но это можно переопределить, начав
нумерацию с любого другого числа,
далее >
227
решение упражнения
Возьми В руку карандаш
Решение
И так, вот код м ассива s e a t s для п р о гр ам м ы M a n d a n g o , которы й
при п о м о щ и ц и кл а п р о в е р я е т места в ки н о те а тр е и с о о б щ а е т об
их д о сту п н о с ти пользователю .
л
Так как индексы м ассива
на чи на ю т ся с О, начнем
с О и сч ет ч и к цикла.
Х о т я в данном случае
мож но было об ойт ись
ч и с ло м я, лу ч ш е и с п о л ь ­
зо в а т ь свойст во len g th
на случ а й , если длина
м а сси ва п о т о м и з м е - ^ ^
нит ся.
С чет чик цикла
и с п о ль зуе т с я в
ка чест ве и н д ек­
са м ассива и по
очереди д а ет до
с т у п ко всем его
элем ент ам .
Значения м ассива
у к а з и б й н .т с я через
за п я т у ю
ские значения.
I
единицу.
v a r sea ts - [ false, tr u e , false, tr u e , tr u e ,T r u e , false, tr u e , ft
fo r (v a r I = O; і < seats.length; ;V+) {
if (seats[ij)
■Щa lertC 'S ea t “ + і +
.............. k :
is available.");
else
a lertC 'S ea t " + і + " is n o t available.");
Seat 1 is twaiSable.
Seat Оis not avaitable.
A
Циклы for повторяют фрагменты кода JavaScript
228
ув е л и ч и в а е м
\
В за ви с и м о с т и о т т о го ,
д о ст уп н о м е с т о (tru e )
или н ед о ст уп но (raise),
б уд ут п о я вля т ь с я разны е
окна диалога.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
^
заданное число раз.
Массив хранит набор фрагментов данных, но при
этом имеет всего одно имя.
Операторы инкремента (++) и декремента (— ) по­
Доступ к элементам числового массива осуществля­
зволяют легко менять показания счетчика цикпа.
ется с помощью индексов.
Массив — это способ хранения наборов данных
в одном месте.
Счетчик цикла удобно использовать для доступа
к данным числового массива.
глава 5
циклы
О т JavaScript к HTML
Н а д ан н ы й м о м ен т д о сту п н о сть к р есел п р е д с тав л ен а в виде м асси в а л о ги ч еск и х
зн а ч е н и й . Т е п е р ь нам нуж но п р е о б р а зо в а т ь эт о т м асси в в н а б о р и зо б р а ж е н и й
H T M L (их м ож н о скач ать п о адресу http://www.headfirstbbs.com /books/hJjs/), к о т о ­
р ы е будут п о к азы в ать св о б о д н ы е к р е с л а н а веб -стр ан и ц е M an d an g o .
var seats = [ false, true, false, true, true, true, false, true, false ]
71
Mandartgo ~ Thg
Movie Ttcfeei Finder
______
В ы гл яд и т все п р е к р а сн о , н о п р о б л ем а в то м , ч т о у нас н е т кода, п ер ево д ящ его
м ассив л о ги ч ес к и х эл ем ен то в в визу ал ьн ы е эл ем ен ты н а веб-страни це.
Гы турм
Каким образом вы реализовали бы связь между массивом логи­
ческих элементов иауаЗспр! и картинками на веб-странице?
далее ►
229
я вижу... место!
Визуализация кресел
С в я зы в ая м ассив Jav aS crip t с к а р ти н к а м и , у бедитесь, ч то
г р а ф и ч е с к и е ф а й л ы п о л н о стью доступн ы , затем о п р е д е ­
л и т е д ля себя, как£1я к а р т и н к а будет со о т в ет с т в о в ать
каком у со сто я н и ю . Н ач н ем с р е ш е н и я п о сл ед н ей задачи.
I
по являет ся
Доступно
М е с т о уж е ,,
занят о.
Нв0ОСтупНО
■
1001 К
\llOiOl
Ш ои
101оіц
Э т о М ест о
дост упно!
5еаІ_ауаіІ.рпд
5еа1_8е1ес1.рпд
8еаІ_ипаУ8іІ.рпд
С оо тветству ю щ и е гр а ф и ч е с к и е ф а й л ы н а зн а ч е н ы атрибуту з г е
в Н Т М Ь -коде и зо б р а ж е н и й :
<ітд id»"seat8" згсв"зеаі_ипауаі1.рпд" alt="UnavailaЫe" />
П а р а м е т р IV о п р е д е л я ­
е т с о о т в е т с т в и е меж оу
э л е м е н т а м и м ассива ——
ы изображ ениями — он
должен начинат ься с О
и за ка н ч и ва т ься Я, как
и индексы м ассива.
Т е п е р ь вам нуж но в ц и к л е п р о с м о т р е т ь м ассив л о ги ч еск и х эл е­
м ен тов, со п о с та в и в и зо б р а ж е н и е с каж ды м Н Т М Ь -тегом < 1 тд >
н а с т р ан и ц е . Ф ак ти ч еск и вы будете и сп о л ьзо вать уже зн ак о м ы й
вам ци кл п р о с т о с другим н а б о р о м дей стви й :
О
О
\
230
глава 5
П р и с в о й т е счетч и ку ц и кл а 1 зн а ч е н и е 0.
У д о сто вер ь тесь, ч то 1 н е п р ев ы ш а ет 9. Если это так, п е р е й д и ­
т е к ш агу 3, в п р о т и в н о м случае в ы й д и те и з цикла.
О
З ап у сти те код, задающий изображение кресла.
^
У в ел и ч ьте зн а ч е н и е 1 н а 1 и в е р н и те с ь к ш агу 2.
циклы
IJoAj^ogHo про
И н и ц и а л и за ц и я м ест в п р о гр а м м е M a n d a n g o осущ ествл яется п р и
п ом о щ и ф у н кц и и i n i t S e a t s O , ц и к л и ч е с к и со п о ставл я ю щ ей
м асси в Jav aS crip t с и зо б р а ж е н и я м и кресел.
in it^ e a ts ()
С чет чик цикла
начинается с О,
поскольку именно
т аким являет­
ся первый индекс
массива.
Проверяет,, все
ли м ест а были
просм от рены .
4UU
о
function initSeats O' {
^
/ / Задаем вид-К ртсел
X
for (var i = 0; i < s eats.length; i++) {
if (seats[i]) {
// Вид доступных кресел
i).src
documdht.getElementByld("seat"
i).alt
docujjifent.getElementByld
("seat
iocuafent.(
elsзе/ {
11 Вид занятых кресел
document.getElementByld{"seat"
document.getElementByld("seat"
i ) .src
i) .alt
У величение
счет чика
цикла на 1 .
"seat_avail.png";
"Available seat";
"seat_unavail.png " ;
"Unavailable seat";
}
Если перемен,ная s e a t и м е е т
Л
значение tr u e ,
п о м е ч а е м кресло
В ка ч ест ве
п а р а м е т р а ID
к р есла в ы с т у п а е т сч ет ч и к
цикла.
как до ст уп н о е.
<body onl
<div St
<img
<img
<img
<img
<img
<img
<img
<img :
<img ;
</div>
</body>
=" in itS e a ts 0 ;" >
- " m a r g i n - t o p : 75px; t e x t - , a l i g n
s e a tO " s r c = " " a l t = "" />
" s e a t l " src=" " a l t =
" s e a t 2 " s r c = " " a l t = "" /> Am
и at
' s e a t 3 " s r c = " " a l t = "" />
ped:
' s e a t 4 " s r c = " ’" a l t = ....
Эля
’s e a t s " s r c = " ' " a l t = ....
’s e a t 6 " s r c = " ' ' a l t = '
---/>
' s e a t ? " s r c = " ' ' a l t = ' ...
s e a t s " s r c = " '' a l t = '
/ X b r />
se a t
и м е е т значение false
(
®
id эт о го
‘изображения
'seat&".
</html>
далее *
231
переменные поиска
Поиск любых свободных кресел
Т е п е р ь , когда и н и ц и а л и за ц и я зав ер ш ен а, м о ж н о п е р е й т и к поиску,
р а д и к о т о р о го , со б ств ен н о , и б ы ла задум ана п р о гр а м м а M an d an g o .
С ет и Д ж е й с о н реш и л и , ч т о сн ач ал а и м е е т см ы сл н а п и с ать ал го р и тм
п о и с к а о д н о го сво б о д н о го м еста. В и т о ге м ы п од ой д ем к р еш ен и ю
сл о ж н о й зад ач и п о с т е п е н н о , р еш ая б о л ее п р о с т ы е в ар и ан ты .
Д л я п о и ск а св о бо д н о го м еста нам п о тр еб у ется п ер е м е н н а я , отслеж иваюш,ая р езу л ьтат вы бора.
Если э т о глобальная п е р е іу м е н н а я , т о она б у д е т д о ­
с т у п н а для всего сценария.
П е р е м е н н а я , храняш ,ая и н ф о р м а ц и ю о в ы б р ан н о м кресл е,
будет нуж на нам н а п р о т я ж е н и и всей ж и зн и с ц е н а р и я , п о э т о ­
му о н а д о л ж н а б ы ть гл о бал ьн о й . П р и с в о и м е й и м я s e l S e a t .
И м е н н о в эту пер ем ен н у ю ф у н кц и я i n d S e a t () будет со х р ан я т ь
и н дек с в ы б р ан н о го кресла.
А какое значение указывает \
на невыбранные кресла?
J
С ет задал х о р о ш и й во п р о с. П е р е м е н н а я s e l S e a t х р а н и т и н ф о р м а ц и ю
о в ы б р ан н о м кр есл е, т о есть ч и сл о о т О до 8. А как б ы ть в т е х случаях,
когд а п о л ьзо в а т е л ь п о к а н е вы б р ал н и од н ого вар и а н т а. Д л я это го нам
п о тр еб у ется с п е ц и а л ь н о е зн ач е н и е. П усть эт о будет 1. И м е н н о тако е
н ач ал ь н о е зн а ч е н и е д о л ж н а и м еть п е р е м е н н а я s e l S e a t .
П ерем енной selS ea t присвоено
начальное значение - 1 . Ведь
сценарий на чи на ет работ у^
когда ни одного м е с т а ещ е не
выбрано.
'
■—
var selSeat = -1;
И так, р а б о т а над п е р е м е н н о й в ы б о р а м еста о к о н ч е н а, и все го то в о для
н а п и с а н и я ф у н кц и и £ i n d S e a t {). Э та ф у н кц и я будет п р о с м а т р и в а т ь все
м еста, н ах о д и ть н е за н я т ы е и сп р аш и в ать п о л ьзо в ат е л я, н е х о ч е т л и он
за б р о н и р о в а т ь и м е н н о эт о м есто. Р азум еется, для ц ел ей настояш ;их м ачо
эт а п р о гр а м м а п о к а н е п од ходи т, н о м ы д ви ж ем ся в нуж ном н ап р авл ен и и !
232
глава 5
циклы
Магниты JavaScript
Ф у н к ц и я £ i n d S e a t ( ) д о л ж н а и скать незан яты е кр есл а и п р е д ­
лагать их пол ьзователю , которы й м о ж е т к а к п о д тв ер д и ть бр о н ь ,
та к и вер нуть ся к д а л ь н е й ш е м у пои ску. В оспол ьзуйтесь м а гн и та м и ,
чтобы за в е р ш и ть код.
U a -o ,
if
>= 0)
(
=
-
„ р о „ = .е .„ .е п о „ о р и у .
{
1;
О;
}
//
п о и с к с в о б о д н о г о м е с т а с р е д и в с е х в о зм о ж н ы х
,0 .
.р е е л ,
^
//'в ы д е л я е т 'к р е с л о и обн овляет его вид
= І;
docu m e n t . q e t E l e m e n t B y l d C 's e a t "
+ i ) ■....................
s e a t ^ s e l e c t .р g
document.,etEle»„tById|-seat" t i) ........ '
/,
по л ь зо в ател ю „ р е д л .г а е .о я
= oo„£l»(-Seat
принять „реллож еннм й в а р и а н ,
- *
,1 t 11
* - 1=
ayailable.
Aoceptr',;
Vdi- ............
" " /)'п 'о л ь з о в 'а т е 1 1 Ь ^ о т к а з а л с я ,
............. =
-
продолжаем поиск
1;
г,
d o c u m e n t.g e tE le m e n tB y ld ( s e a t
+
„ -Г Л
d o c u m e n t.g e tE le m e n tB y ld ( s e a t
+ it
= "С вободное м е с т о " ;
+ i ) ....................
initSeats
±)
+ D •..................
accept
= "se a t a v a il.p n g " ;
IselSeat
seats[i]
далее ►
233
решение задачи с магнитами
Решение задачи с магнитами
И так, вот к а к д о л ж н а вы глядеть ф ункци я f i n d S e a t ( ) , ищ ущ ая
с в о б о д н о е м есто и п р е д л а га ю щ а я им воспользоваться.
fu n c tio n fin d S e a tO {
/ / Е с л и м е с т о уже в ы б р а н о ,
if
п р о и з в е д и т е повторную инициализацию
«ре««*“
(
Показываемые
п о л ь зо в а т е л ю
номера м е с т на
единицу больше
реальных., т а к каь
иск заново.
}
П о и с к с в о б о д н о г о м е с т а с р е д и в с е х в о зм о ж н ы х
кинот еат рах
f o r ( v a r ii = 00;
; ii < sseats.xengta;
e a t s . l e n g t h ; iхт-г;
+ + ) {x
/ / П р о в е р к а д о с т у п н о с т и р а с с м а т р и в а е м о г о в д а н н ы й м о м е н т к р е с л а ну м е р а ц и я начи
____ 1 ________ _
^
иается с 1 , а не
^ ------------- — --------------- -- ^ Если м ест о свободн
свободноJ с О.
s e a t s [х] 1
if
I5еаЬ$11] и м е е т значе
//
3
есло и обновляет его вид
selSeat
}
i;
+ i)
d o c u m e n t.g e tE le m e n tB y ld (" s e a t"
+ i) .
П ользователю п р е д л а г а е т с я принять пре
!accept~|j
Проверяем,,
согласился ли
пользователь
занять место. ■
( i + 1)
co n firm ("S eat
accept
234
■= " s e a t _ s e l e c t . p n g " ;
d o c u m e n t.g e tE le m e n tB y ld C 's e a t"
//
±гие.
;нный в а р и а н т
+ " is
a v a ila b le .
A cc e p t? ");
{
1ЛЬ о т к а з а л с я ,
=
= "Y our s e a t " ;
-
продолжаем п оиск
1;
document. g e t E l e m e n t B y l d ( " s e a t '
+ i) •
" s e a t_ a v a il.p n g " ;
document.g e t E l e m e n t B y l d ( " s e a t
+ i) •
"A v a ila b le
глава 5
se a t";
циклы
проверка
П е р в а я в е р с и я п р и л о ж е н и я M an d a n g o и сп о льзует ци кл
f o r и м ассив д ля п о и с к а о д и н о ч н ы х сво б о д н ы х м ест. И я в ­
л я е т с я в п о л н е ф у н к ц и о н ал ь н о й , х о т я и н е для м ачо.
Так как кресло но м ер 4
каж ет ся е м у подходящ им ,
п о л ь зо в а т е л ь щ е л к а е т на
кнопке ОК.
JasissiJ
Seat 4 is avaHable. Accept?
далее >
235
цикл за циклом...
Бесконечные циклы
П о и с к н е за н я т ы х о д и н о ч н ы х м ест с т е х н и ч е с к о й т о ч к и зр е н и я р а б о т а е т
х о р о ш о , в о т т о л ь к о ц и кл н е зн ает, когд а ему следует п р е к р а т и т ь свою р а б о ­
ту. Д аж е п о сл е т о го , как п о л ь зо в а т е л ь за б р о н и р о в а л себе м есто, щ елкнув н а
к н о п к е О К , п е р е б о р и п о и с к д ал ь н ей ш и х сво б о д н ы х м ест п р о д о л ж ается.
П о льзо ва т ель уж е вы
брал себе кр есло но м ер 4 ,а п р о гр а м м а все продол
ж ает поиск.
236
глава 5
'
м
т
я
я
циклы
Условие выхода из цикла
Т ак как п р и ч и н о й слиш ком б о льш о го у сер д и я п о и ск о в о й п р о гр ам м ы ,
судя п о всему, я в л я е т с я б ес к о н е ч н ы й ц и кл , Д ж е й с о н р е ш и л в н и м ател ь­
н е й п р и с м о т р е т ь с я к циклу f o r в ф у н кц и и f i n d S e a t ( ) .
co n firm Q п р е д л а га е т п о л ь з о ­
в а т е л ю о т в е т и т ь на вопрос д а /н е т ,
возвращ ая значение tr u e (да) или false
(нет ).
fo r
11
if
( v a r i = 0; i < s e a t s . l e n g t h ; i+ + ) {
П р о в е р к а д о с т у п н о с т и р а с с м а т р и в а е м о г о в_^5 ййны й м о м е н т к р е с л а
(se a ts [ i ] ) {
/ / В ы д е л я е м к р е с л о иу(!Гбновляем е г о в и д
s e l S e a t = 1;
d o c u m e n t.g e tE le m e n y fe y ld C se a t" + i ) . s r c
d o c u m e n t.g e tE le m e r* B y Id ("se a t" + i ) . a l t
= "s e a t_ se le c t.p n g " ;
= "Y our s e a t " ;
/ / П ользователю г ^ д л а г а е т с я п рин ять предложенный в а р и а н т
v a r a c c e p t = c o n f i r m ( " S e a t " + ( i + 1) + " i s a v a i l a b l e . A c c e p t ? " ) ;
-i-£. ( 'a r^ c e p t)
{ J
I I Пользователь отказался, продолжаем поиск
selSeat = -1;
document.getElementById("seat" + i).src = "seat_avail.png";
document.getElementByld("seat" + i).alt = "Available seat";
К огда п о л ь зо в а т е л ь б р о н и р у ­
е т свободное м е с т о , ничего не
п р о и схо д и т , и ц и кл продолж ает
р а б о т у.
Э т о т код за п у с к а е т с я , если
M 3 o 6 a m e A t> от казы вает ся
б ронироват ь свободное м ест о.
П р и щ ел ч ке н а к н о п к е C an cel п е р е м е н н о й s e l S e a t п р и с в аи в а е тс я зн а­
ч е н и е -1 (н и ч е го н е в ы б р ан о ), и ци кл п р о д о л ж ае т работу. О д н ако н ет
кода, к о т о р ы й в ы п о л н я л ся б ы п осле б р о н и р о в а н и я сво б о д н о го м еста.
С о д н о й с т о р о н ы , эт о х о р о ш о , т а к к ак п о зв о л я е т п е р е м е н н о й s e l S e a t
зап о м н и т ь в ы б р ан н о е зн а ч е н и е . А с другой — н и ч т о н е м еш ает циклу
п р о д о л ж и ть п о и с к сво б о д н ы х м ест.
Ш ТУРМ
Что должно происходить при щелчке на
кнопке ОК и бронировании места?
далее ►
237
перерыв
прерывание действия
П р о б л е м а с кодом п р и л о ж е н и я M an d a n g o в том , ч то вам нуж но
б ы ло вы х о д и ть и з ц и к л а сразу ж е п о сл е б р о н и р о в а н и я кресл а. Э того
м о ж н о д о б и ться, к пр и м ер у , путем п р и с в о е н и я счетч и ку ц и к л а f o r
зн а ч е н и я , п р ев ы ш аю щ его длину массива.
В э т о м случае, про вер ка
.у с л о в и я п р и в е д е т к п р е р ы в а ­
н и ю цикла... но е с т ь и долее
изящ ны е ва р и а н т ы реш ени я
проблем ы .
i = seats.length + 1;
Д а н н ы й код я в л я е т с я зам еч ател ьн ы м о б х о дн ы м м ан евром ,
н о е с ть и б о лее п р о с т о й путь вы хода и з цикла. Э то о п е р а т о р
b r e a k , со зд ан н ы й с п ец и ал ь н о для п о д о б н ы х случаев.
З а с т а в л я е т нем едленно
вы й т и из цикла.
З а в е р ш а е т все операции
на т е к у щ е м ш аге ци кла ,
п р и н у д и т е л ь н о переводя
на следую щ ий.
О б н ар у ж и в о п е р а т о р b r e a k , ц и кл н ем ед л ен н о зав ер ш а ет работу,
и гн о р и р у я п роц едуру п р о в е р к и условия. Т аки м о б р азо м , д ан н ы й
о п е р а т о р д ае т вам в о зм о ж н о сть в ы й т и и з ц и к л а в л ю б о й м ом ент.
С н и м б л и зк о свя зан о п е р а т о р c o n t i n u e , к о т о р ы й п р е к р ащ ае т
в ы п о л н е н и е текущ их о п е р а т о р о в б ез вы ход а и з цикла. Д ругим и
сл овам и, о п е р а т о р c o n t i n u e п ри н у д и тел ьн о п е р е в о д и т ц и кл на
следую щ ий шаг.
continue;
О п е р а т о р ы b r e a k и c o n t i n u e по­
зв о л я ю т н а с т р а и в а т ь р або ту ц и кл о в
нуж ны м вам о б р азо м . И и м е н н о
о п е р а т о р b r e a k р е ш а е т п роблем у
с б ес к о н е ч н ы м ц и кл о м в п р о гр ам м е
M an d an g o .
238
глава 5
циклы
Ч асщ о
^аД аБаеМ ы е
Б о Ц Р о С Ь!
Выполняется ли код, стоящий
в цикле f o r после оператора b r e a k ?
Чем плох вариант с увеличением
показаний счетчика для выхода из
цикла?
; Нет. Оператор b r e a k приводит
к немедленному прекращению работы
цикла, и все стоящие после него операто­
ры игнорируются.
0:^
^ j Вы заставляете счетчик работать
непредусмотренным образом, и это может
привести к проблемам. Он предназначен
для подсчета элементов массива, а вы
присваиваете ему значение, выходящее
за границы диапазона, провоцируя выход
из цикла. В общем случае показания счет­
чика должны обновляться только в одном
месте. Разумеется, бывают случаи, когда
допустимы различные обходные манев­
ры, но это — не один из них. в конце
концов, к вашим услугам всегда оператор
b r e a k , мгновенно прерывающий цикл
без принудительного изменения значения
счетчика.
Возьми в руку карандаш
Ц и кл f o r в ф ункци и f i n d S e a t ( ) д о л ж е н преры ваться после
то го , к а к пол ьзователь за б р о н и р о в а л кр е с л о . В пи ш ите н ед о стаю ­
щ и е с тр о ч ки кода и к о м м е н та р и и к ним .
//
поиск свободного м еста
с р е д и
в с е х в о зм о ж н ы х
.р е е .
If
и
(se a ts [i]) {
выделяем к ресло и обновляем е го вид
s e l S e a t = 1;
,
^ "seat
d o c u m e n t.g e tE le m e n tB y ld
seat
+ i -s
^
d o cu m en t. g e tE le m e n tB y ld ( " s e a t
+ 1)•a it
/ / П ользователю п р е д л а га е тс я
v ar accep t = co n firm ("S eat
+
П ользователь о тк азал ся,
selSeat = - 1 ;
se le c t.p n g " ;
;
A ccep t?")
(1 +
продолжаем поиск
.n„Tri("4eat" + i).src = "seat_avail . p n g " ;
d o c u m e n t.g e tE le m e n tB y ld
s e a t _
d o c u m e n t.g e tE le m e n tB y ld (
s e a t
^
+
- A v a il a b le
s e a t " ;
i ) - a
далее ►
239
решение упражнения
Возьми в руку карандаш
Решение
Ц икл f o r в ф ункци и f i n d S e a t { ) д о л ж е н преры ваться посл е
того, к а к пол ьзователь за б р о н и р о в а л кр е с л о . Вот к а к вы глядят
н е д о с та ю щ и е с тр о ч ки кода и к о м м е н та р и и к ним .
// Поиск свободного места среди возможных
f o r ( v a r i = 0; i < s e a t s . l e n g t h ; i+ + ) {
/ /
П р о в е р к а
if
д о с т у п н о с т и
(seats[i])
/ /
р а с с м а т р и в а е м о г о
в
д ан н ы й
м о м ен т
к р е с л а
{
В ы д ел яем
к р е с л о
и
о б н о в л я е м
е г о
ви д
se lS e a t = 1 ;
document.g
e tE le m e n tB y ld { " s e a t"
+
i ) . s r c
=
document.g
e tE le m e n tB y ld ( " s e a t"
+
i ) . a l t
- "Your
/ /
П о л ь зо в а т е л ю
п р е д л а г а е т с я
п р и н я т ь
" s e a t _ s e l e c t . p n g
п р ед л о ж ен н ы й
v a r a c c e p t = c o n f ir m ("S e a t " + (i + D
+ " is
;
s e a t " ;
в а р и а н т
a v a ila b le .
A c c e p t?
_(f_(a c c e p t),...............................................................................................................................
/ / К р ес л о заб ронировано, п о э т о м у
ц и кла з а в е р ш а е т с я ...........
break;
.............................................................................
■}......................... ..........................................................................................................................
e lse
/ /
{
П о л ь з о в а т е л ь
о т к а з а л с я ,
п р о д о л ж аем
п о и с к
s e lS e a t = -1;
.п
do c u ment.getElementById("seat " + D - s r c = "seat_avail.png ;
d o c u ment.getElementByld("seat" + i).alt - "Available seat ;
}
}
}
М еста для мачо
К ак вы п о м н и те, и зн а ч а л ь н о нлани ровгш ось со зд ать п рограм м у
к о т о р а я будет и с к а ть группы и з т р е х п о д р я д сво б о д н ы х м ест.
В а р и а н т для п о и ск а о д н о го сво б о д н о го м еста уж е го то в, и н аш и
друзья С ет и Д ж е й с о н го то в ы н а ч а ть р або ту над н о в о й в е р с и е й
св о ей п р о гр ам м ы .
Три свободных кр есла п о д ­
ряд... сколько м е с т а !
240
глава 5
циклы
- Г
'
Думаю, что несколько вложенных
операторов if без проблем помогут найти
три свободных места подряд. Да, именно так
я и сделаю!
К од Б д еталях
--------------------------------
П о сл еЭ о б ател ь н о сть из
п р о б е р я е т с я п р и у^омощи вложенных
о п ер а т о р о в iffor
(v a r i =
0;
i < s e a t s . lengflh; i++)
Пры обнаруж ении
т р е х м е с т подряд
вы деляем первое из
них.
{
М еняем изображение
всех т р е х кресел на
« за н я т ы е » , чтобы
п о ль зо ва т е ль видел,
какие м е с т а о с т а ­
ли сь свободными.
// Проверяем, свободно л и т к у щ е е место и два места за
if
( s e a t s [ х ]) (
i f ( s e a t s [ i + 1]) {
i f ( s e a t s [ i + 2]) {
/ / Выделяем кресла и обновляй1й их вид
selS eat = i ; - ^
document.getElementByldC'seat"
document.getElementByld("seat"
document.getElementByld("seat"
document.getElementById("seat"
document.getElementByld("seat"
document.getElementById("seat"
+
+
+
+
+
+
i) .src = "seat_
i).alt = "Your
(i + l)).src =
(i + l)).alt =
(i + 2)).src =
(i + 2)).alt =
select.png";
seat";
"seat__select .png
"Your seat";
"seat_select.png
"Your seat";
// Пользователю предлагается принять предложенный вариант
v a r a c c e p t = c o n f i r m (" S e a t s " + ( i +
i f (accept) {
1)
+ " through " + (i +
3)
J
+ " a r e a v a i l a b l e . A c c e p t? " ) ;
// Кресла забронированы, поэтому работа цикла закончена
break;
}
else {
// Пользователь отказался, продолжаем поиск
s e l S e a t = - 1;
document.getElementByld("seat"
document.getElementByld("seat"
document.getElementByld("seat"
document.getElementByld("seat"
document.getElementByld("seat"
document.getElementByld("seat"
}
+
+
+
+
+
+
i).src = "seat_avail.png";
i).alt = "Available seat";
(i + l)).src = "seat_avail.png";
(i + l)).alt = "Available seat";
(i + 2)).src = "seat_avail.png";
(i + 2)).alt = "Available seat";
* Н апом инаем : код п р о гр а м м ы M andango
и все с о п у т с т в у ю щ и е изображ ения можно
ска ча т ь по адресу h ttp ://w w w .k e a d fir s tla h s .
с о т / b o o k s/h fjs/.
Если п о ль зо в а т е ль
не б ро н и р ует М е­
ст а возвращ аем им
изображ ение « неза пят ы е».
далее *
241
с надеждой на изящество
А здорово было бы, если бы
все эти вложенные операторы if
заменил какой-нибудь более из­
ящный вариант?
242
глава 5
циклы
Логичное
U
элегантное решение
П р о в е р к у д о сту п н о сти т р е х м ест п о д р яд в п р о гр ам м е M an d an g o
м ож н о в ы п о л н и ть и б о л ее п р о с т ы м и средствам и . В л о ж ен н ы е
о п е р а т о р ы i f в п о л н е сп р ав л яю тся со с в о е й зад ач ей , н о код м ож н о
улучш ить, сделав его б о лее изяш ,ным.
Изящный?! Вы из­
деваетесь? Все ведь
и так работает!
Q
Н е с м о т р я н а в о зр а ж е н и я С ета, ст о и т
вн е с ти в код и зм е н ен и я , сделав его б о лее
«изящ ны м », то есть б о лее э ф ф ек т и в н ы м ,
л егк и м д ля п о н и м а н и я и р е д а к ти р о в а н и я .
Р азве н е зд о р о в о б ы ло бы п р е в р а т и т ь вл о ­
ж ен н ы е о п е р а т о р ы 1 £ в о д и н о п ер ато р ?
Л огически й о п е р а т о р
И (&&) про вер я ет , все
ли п ар а м ет р ы и м е ю т
значение true.
if (seats[i] && seats[i + 1] && seats[i + 2 ] )
tr u e
tr u e
{
tr u e
Л о г и ч е с к и й о п е р а т о р И (&&) п р о в е р я е т , все ли
п а р а м е т р ы и м ею т од н о и т о ж е зн а ч ен и е . В д ан ном
случае два о п е р а т о р а И исп ользую тся для п р о в е р к и
д о сту п н о сти т р е х м ест п од ряд. Если все т р и р аза
мы наблю даем зн а ч е н и е t r u e , зн ач и т , м ы наш ли
т о , ч то нуж но. П р о б л е м а реш ен а... и как изящ но!
далее *
243
исследуем
булеву логику
Логические операторы
Вы уж е зн ак о м ы с так и м и о п е р а т о р а м и с р а в н е н и я , как ==
и <■ О н и с о п о став л я ю т два зн а ч е н и я и получаю т резу л ьтат
в ф о р м е t r u e / f a l s e . А н ал о ги ч н ы й р езу л ьтат д аю т л о ги ­
ч ес к и е о п е р а т о р ы , к о т о р ы е м ы р а с с м о тр и м ни ж е.
Э т о т операт ор
вы уже видели!
OR
а II Ь
В о звр а щ а ет значение
tr u e , если а И Ь и м е ­
ю т значение tru e.
В о звр а щ а е т значение
tr u e , если а И Л И Ь и м е ­
е т значение tru e .
В о звр а щ а е т значение false,
если а и м е е т значение tru e ,
и значение tr u e в п р о т и в ­
ном случае.
Л о ги ч е с к и е о п е р а т о р ы п о зв о л я ю т с о е д и н я ть друг с дру­
гом н еск о льк о услови й , д авая в о зм о ж н о с ти п р и н и м а т ь
р е ш е н и я с собл ю ден и ем д о ст а т о ч н о сл о ж н ы х условий.
Л огические выражения
гр у п п и р у ю т с я п р и п о м о щ и
скобок.
г
if ((largeDrink && largePopcorn)
freeCandyO ;
В д ан н о м п р и м е р е о п е р а т о р И п р о в е р я е т , сделал л и
кл и ен т к о м б и н и р о в а н н ы й заказ, купив б о льш ой стакан
н а п и т к а и б о льш о е в ед р о п о п ко р н а! В это м случае он
пол у ч ает в награду кон ф ету. С ущ ествует и другой способ
п ол у ч ен и я б ес п л атн о й к о н ф е т ы , как п о к а зы в а ет о п е р а ­
т о р И Л И , —н а л и ч и е купона. Т о есть вам даю т кон ф ету,
если вы зака зы в а е те б о льш о й н а п и т о к И б о льш ой п о п ­
ко р н И Л И п р е д ъ я в л я е т е купон. Б е з л о ги ч е с к и х о п е р а т о ­
р о в за п р о гр а м м и р о в а т ь т а к о е условие б ы ло бы к р ай н е
слож но.
244
глава 5
/
|| coupon)
П о луч и т ь б ес п л а т н у ю ■
к о н ф е т у (free ca ndy) можно
п у т е м ком бинированного
заказа И Л И п р и наличии
купона.
Комбинируя логические
операторы, мы создаем
сложные условия.
циклы
Часщо
Задаваем ы е
Б о Ц Р о Сь !
Ti-»
J» в чем разница между операторами
сравнения и логическими операторами.
Q ; Начнем с того, что все они являются
логическими операторами в том
смысле, что результатом их работы
является выражение t r u e или f a l
s e .
Различаются они типами обрабатываемых
данных. Операторы сравнения могут
работать с любыми данными, для
которых имеют смысл выражения
«равно», «не равно», «больше чем» и т. п.
Логические операторы работают только
с логическими данными, объединяя их
друг с другом.
гч.
3 * То есть оператор НЕ является
логическим?
верно вообще для всех операторов, а не
только для логических. Первым делом
! Именно так. Ведь он работает
с логическими данными. Кроме того,
определяется значение выражения
в скобках. Поэтому в показанном на
предыдущей странице примере сначала
это унарны й оператор, так как для него
требуется всего один операнд.
l a r g e P o p c o r n , а только потом | | .
выполняется часть l a r g e D r i n k
&&
3 * Какую функцию в логических
операторах выполняют скобки?
! Скобки позволяют менять заданный
по умолчанию порядок выполнения
операторов. Причем это утверждение
^Возьми в руку карандаш
Это шестой п р о го н цикла f o r в пр огра м м е M an da ngo ( i = 5).
О пределите д оступн ость рассматриваемы х мест и укажите,
подходят ли о н и для настоящ их мачо.
for (var i = 0; i < seats.length; i++) {
// Проверяем, свободно ли текущее место и два места за ним
if (seats[i] && seats[i + 1] && seatsti + 2 ] )
{
далее >
245
решение упражнения
Возьми В руку карандаш
X
Решение
Вот каким образом распределились д оступны е места на шестом
пр о го н е цикла f o r в програ м м е M an da ngo ( i = 5). К сожалению,
рассматриваемы е на этом шаге места не подойд ут наш им мачо.
tr u e
г =
false
tr u e
S'
/ +2 = 7
for (var i = 0; i < seats.length; i++) {
// Проверяем, свободно ли текущее и следующие два места
if (seatsli] && seats[i + 11 && seats[i + 2 ] )
■f.'T“ ?....
&&
{
false
&&
Наконец поиск заработал
Т е п е р ь п р о гр ам м а M an d a n g o к о р р е к т н о и щ ет п о с л ед о в ател ьн о с ти
и з т р е х п о д р я д н е за н я т ы х м ест, п о д н я в се р в и с р е зе р в и р о в а н и я б и ­
л е т о в н а такую вы соту, ч т о о ц е н и т ь его м огут даж е н аш и м ачо.
.......
■П»MachoMow
......
Теперь пользоват елю
предлагаю т выбрать
1лоследоват елш ост ь
из т р е х мест .
I
Seats 4 through 6 are avaitable. Accept’
[andseaVii
('"C^cel j f
J
246
глава 5
OK
циклы
U сноВа карта сокровищ
Раз п р о гр а м м а M a n d a n g o п р е к р а сн о р а б о т а е т , м о ж н о в ерн уть­
ся к пои ску со кр о ви щ . П о м н и те эту карту?
37 шагов.
О И д и те, п о к а н е увидите
скалу в ф о р м е п оч атка.
А
^
Ч У С н ач ал а 37 ша-
Цикл fo r ув ер ен но проводит в а с ___ У
по первой части
м арш рут а!
О К р ес т указы вает место!
....
Д л я п р о х о ж д е н и я п е р в о й ч ас ти м арш рута вам д о стато ч н о
ц и к л а f o r . Н о во т п р е о д о л е ть следую щ ий уч асток о н вам н е
п о м о ж ет. В едь н е в о зм о ж н о со зд ать ци кл f o r , н е зн ая т о ч н о ­
го к о л и ч ес т в а его ш агов.
Сокровищ е
ждет...
Ш ТУРМ
в чем разница между двумя частями карты? Каким
образом вы бы создали цикл для прохождения второй
части?
далее ►
247
сколько? некоторое время...
Цикл while
Х отя т е о р е т и ч е с к и ци кл f o r м о ж н о со зд ать и д ля в т о р о й
ч аст и к ар ты , сущ ествует лучш ий в ар и ан т. О с н о в о й ц и кл а
f o r я в л я е т с я сч етч и к , а в о т ц и кл w h i l e р а б о т ае т , пока
н е будет в ы п о л н е н о зад ан н о е условие. И эт о услови е
м о ж ет б ы ть н и к а к н е с в я за н о с ч и сл о м и т е р а ц и й (п о в то ­
р е н и й ).
Ц и к л w h i l e с о с т о и т и з двух частей:
Проверка условия
Цикл №Ы1е повторяет
код, пока результатом
проверки условия пе
станет значение true.
Проверка условия
П р о в е р я е т с я , д о л ж ен л и
п р о д о л ж а т ься цикл.
Ш аги 1 U Я
п о л н я ю т с я нд
каждой и т е р а ­
ции цикла.
О
Действие
О ператоры , которы е
следует в ы п о л н я т ь н а
каж дом п р о г о н е цикла.
\
.
•••
Действие
...
...
.
О дин илаг
цикла.
Проверка
условия
О
П р и м е н е н н ы й ко в т о р о й ч асти к а р т ы ци кл w h i l e д ае т т ак о й
ж е н е о ж и д ан н о п р о с т о й код, как и ци кл f o r в п е р в о й части:
О
С ледую щ ий ш аг вы ­
п о л н я е т с я , то л ь ко
есл и скалы все ещ е н е
видно.
while (!rockVisible)
takeStepО ;
О
?госкУ ± з± Ы е
В от как ф у н кц и о н и р у ю т р а зл и ч н ы е ч ас ти ц и к л а w h i l e :
Действие ^
^
П р о в е р я е м , ви д н а л и скала. Если да, п ер ех о д и м
к ш агу 2, если н ет, вы ход им и з цикла.
О
Запускаем код ци кла. В д ан н ом случае вы зы ваем
ф ункц ию t a k e S t e p ( ) .
В ы зов ф у н кц и и t a k e S t e p ( ) .
takeStep О
248
глава 5
циклы
Анализ цикла while
Б о л е е п р о с т о й по структуре, ч ем ци кл f o r , ци кл w h i l e
т о ч н о т а к ж е о п и с ы в а е т с я о п р е д е л е н н о й ф орм улой :
П роверка ус ло ви я , к о т о ­
р а я должна во звр а щ а т ь
значение tr u e или false.
i
Проверка
while
|Д к ш е
I
осш орож ны !
Действие
П овт орянущ иеся дейст вия
зада ю т ся как п р о с т ы м ^
т й к и со ст а вны м опера
тороМ-
Будьте аккуратны
с условием выхода
из цикла.
Цикл while не имеет
встроенного кода
обновления, поэт ому его внутрен­
ний код должен быть написан
таким образом, чтобы влиять на
условие выхода. Иначе цикл может
оказаться бесконечным.
Перепишите код уже знакомого вам упражнения, в котором пользова­
телю предлагалось ввести число больше О и который использовался
для обратного отсчета перед началом фильма (4, 3, 2, 1, Roll film!).
Замените цикл f o r циклом w h i l e .
var count = prompt{"Enter a number greater than 0:", "10");
if (count > 0) {
}
else
alert{"The number wasn't greater than 0. No movie for you!");
далее *
249
решение упражнения
Вот как после замены цикла f o r циклом w h i l e выглядит код уже знакомого
вам упражнения, в котором пользователю предлагалось ввести число больше О
и которое использовалось для обратного отсчета перед началом фильма (4, 3,
2,1, Rollfilm!).
^пражнеше
реш ение
С охраним число
в п ер ем енно й
count.
Пользователю
предлагается в
сти число.
а
var count = prompt("Enter a number greater than 0:", "10");
Убедим­
ся, что
•леременная count
больше о.
if (count > 0) {
___
обрат ны й
от счет
до О.
v a r X = count;
................
I
В данном
случае
счетчик
создается
вне цикла
while.
while (x > O) {
................................................................................................................................................
a le r t( " S ta r tin g in..." + x);
Значение
........................................................................................................................................ п ер ем ен н о й X
уменьшается
на 1 вн у т р и
цикла.
Внутри
цикла с о ­
ст а вно й
оператор.
alert("The number wasn't greater than 0. No movie for you!");
Некорректные
данные.
The number wasn't greater than 0. Ho movie for you!
Обратный отсчет
закончен!
Roil film!
C__0 k'" )
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
250
Оператор b r e a k немедленно завершает цикл,
пропуская оставшийся код.
Цикл w h i l e выполняет указанный код, пока вы­
полняется заданное условие.
Логические операторы позволяют создавать слож­
ные условия.
Код в теле цикла w h i l e должен влиять на условие
выхода.
глава 5
циклы
Выбор подходящего цикла
П реды дущ ее у п р аж н ен и е п о к азало , ч т о и н о гд а одну и ту ж е
проб л ем у м о ж н о р е ш и т ь как п р и п о м о щ и ц и кл а f o r , т а к и п р и
п ом о щ и ц и к л а w h i l e . Б о л е е то го , п р е в р а щ е н и е ц и к л а f o r
в ц и кл w h i l e осу щ ествл яется по следую щ ей ф орм уле:
Циклы while и цикл
’
Р
ЯП Н аШ Ф О а
Л о Л Л Ш 1 1//1
взаимозаменяемыми.
Иниц.
while
1
^ □
О бно влени е
с
Действш
И нициализация
вы п о лн яет ся вне
цикла.
□
И так , вы убедились, ч то т е х н и ч е с к и одну и ту ж е задачу м ож н о
р е ш и ть с пом ощ ью лю б о го и з ци кл о в. Н о в б о л ьш и н стве слу­
ч аев следует и с п о л ьзо в ат ь с т р о го о п р е д е л ен н ы й ци кл. М ож ет
б ы ть, все д ел о в изящ естве?
/
\
for (var i = 0; i < Ю ;
О бновление
вы полняет ся
в т е л е цикла.
var i = 0;
while (i < 10)
(
alert(i);
i++)
i++;
alert (i);
}
Э т и циклы Kopomcf
подходят для р еш е ния п о ст а влен н о й
задачи.
Н е т обновления.
Н ет и ни ц и а ли за ц и и ^
while (!finished)
dolt О ;
___________ с
for (; !finished; )
dolt О ;
\
В ы б о р между ц и кл ам и f o r n w h i l e п од обен вы б ору н аи б о л ее
под х о дящ его д ля р аб о т ы ин струм ен та. Д ругим и словам и, «ме­
хани ка» ц и к л а до л ж н а со о т в ет ст в о в а ть п о с т а в л ен н о й задаче.
далее *
251
цикл fo r против цикла while
Беседа у камина
Циклам For и While сложно не повториться.
Цикл For:
В от и м ы , п а р а п о в то р я ю щ и х с я п а р н ей , ко­
т о р ы е д ер ж а тс я вм есте.
Я во все н е сл о ж н ы й , п р о с т о ко м не д о б ав л е­
н а о п р е д е л ен н а я структура. Е сли нуж ен цикл
с ч и сл ен н ы м сч етч и ко м , я л е гк о п о зво л яю
и н и ц и а л и зи р о в а т ь и р е д а к ти р о в а ть д ан н ы й
п ар а м е тр .
З ву ч и т слиш ком н е о п р е д е л е н н о , х о т я я ду­
маю , ч то это д о л ж н о р аб о тать. Н о м н е по
душе б о льш ая то ч н о ст ь . И м е н н о п оэтом у
я п р е д п о ч и т а ю и н и ц и а л и зи р о в а т ь с я до н а­
ч ал а р а б о т ы и о б н о в л я тьс я в п р о ц е сс е и т е ­
р а ц и й , п р о с т о ч то б ы б ы ть у вер ен н ы м , ч то
все р а б о т а е т так, как нуж но. Я м ан и ак ал ьн о
слеж у за тем , ч то б ы р а б о т а т ь к ак часы .
Цикл While;
Д а. Х о тя д о л ж ен сказать, ч т о к о л и ч е ств о ш а­
гов, п р и п ом о щ и к о т о р ы х т е б я заставл яю т
р аб о та ть, п р е д ста в л я е тс я м не и зб ы то ч н ы м .
Э то так, но, как т ы пом н и ш ь, дал еко н е все
ц и к л и ч е ск и е п о в т о р е н и я св я зан ы со счетом .
Е сть п о т р я са ю щ и е ц и кл ы , вооб щ е н и к ак
н е св я за н н ы е с ц и ф р а м и . К огда тр еб у ется
т о л ь к о сказать «Эй, д ел ай в о т эт о н е к о т о р о е
врем я!», я незам ен и м .
В осхищ ен тв о и м п од ходом к р аб о те. Н о
п о н и м аеш ь л и ты , ч то ц и к л и ч е ск о е п о в т о р е ­
н и е д ей ств и й в п о л н е осущ ествим о и б ез всех
эт и х ф о р м ал ь н о с те й вр о д е п р ед в ар и т ел ь ­
н о й и н и ц и а л и за ц и и и о б н о вл ен и я ? К ром е
т о го , я ч асто п о в т о р я ю код, для к о т о р о г о
н е тр еб у ется и н и ц и ал и за ц и и . А о б н о в л ен и е
п р о и сх о д и т п р я м о внутри м еня, и то ге
я могу сф о к у си р о в аться н а н е п о ср ед с тв е н ­
н о й р аб о т е , то есть н а и т ер а ц и я х .
в
Я знаю , ч т о в о зм о ж н ы ц и к л ы р а з н о й струк­
туры . Н о л и ч н о я п р е д п о ч и т а ю над еж н о сть.
252
глава 5
циклы
Цикл While;
Цикл For:
Н а в е р н о е , все д ел о в том , ч то каж ды й ци кл
и м е ет свой сти л ь р аб о ты . Т е б е н р ав и тс я
и м е т ь под рукой все эл ем ен ты у п р ав л ен и я,
в т о вр ем я как я со с р е д о т о ч е н н а п р о ц ессе.
Д а, эт о так. Г лавное, ч то м ы о б а делаем свою
работу. И я даж е и н о гд а виж у, где м о й под ­
ход я в л я е т с я изли ш н и м .
П о л н о стью с т о б о й согласен! Г лавное, ч то
р аб о т ы х в а т и т нам обоим .
Я го то в слуш ать эт о сн о ва и снова!
Г л авн ое, ч т о раб о ты ... о й , к аж ется, м н е п о р а
п р е р ы в а т ь работу. П рош у п р о щ е н и я .
Н и ч е г о с тр аш н о го . С п аси бо за беседу!
Часто
'^ а Д а Б а е М ы е
Б о 1 1 |э о с ь 1
3 * Цикл w h i l e кажется очень про­
стым. Я чего-то не понимаю?
; Да... и даже слишком усердно. Ведь
вы создали бесконечный цикл, потому что
результат проверки условия всегда будет
Может ли случиться так, что тело
цикла никогда не будет выполнено?
S Вовсе нет. Простота не является
синонимом слабости или ограниченности.
иметь значение t r u e . А цикл w h i l e
продолжает работу, пока условие не пере­
станет выполняться, то есть результатом
^ ; Да. Для перехода к операторам
в теле цикла нужно, чтобы результатом
Более того, вы удивитесь, обнаружив, на­
сколько мощным инструментом является
цикл w h i l e . Разумеется, он состоит
только из условия и выполняемого кода,
но в некоторых случаях большего и не
требуется. Особенно в тех случаях, когда
условие выхода из цикла является до­
статочно сложным. Кроме того, в тело
цикла можно поместить любое количество
кода, ведь вы можете воспользоваться
составным оператором.
Будет ли работать цикл вида
w h i l e ( t r u e ) ...?
его проверки не станет значение f a l s e .
Страшно подумать, сколько бесконечных
циклов вынуждены работать, работать
и работать... эй, прекратите немедленно!
проверки условия было значение t r u e .
Поэтому если условие не проходит про­
верку, перехода к телу цикла не происхо­
дит. Вы выходите из него еще до начала
его работы.
Б
>Допустимы ли вложенные циклы?
! Конечно! Вложенные циклы по­
зволяют создавать различные уровни
повторений. На данном этапе это может
звучать для вас странно, но это — правда.
Вы познакомитесь с вложенными цикпами
позже, когда программа Mandango от ряда
перейдет к целому кинотеатру!
далее *
253
успех цикла
Сокровище В награду
В о сп о л ьзо вавш и сь ц и кл о м f o r , за к о т о р ы м следует
ц и кл w h i l e , вы см о ж ете п р о й т и ук азан н ы й н а к ар те
м арш рут и п р и б ы т ь в точку, пом еч ен н у ю кр естом .
3 7 шагов.
И д и те, п о к а н е увидите
скалу в ф о р м е поч атк а.
while (!rockVisible)
С н ач ал а 37 ш а­
гов н а восток.
takeStep ();
for (var X = 0; X < 37; х++
При пом ощ и цикла
while вы без задер­
жек преодолеете
вт орую часть!
takeStep();
Ц и к л f o r уверенФ
НО проводит вас _J
по первой части
м арш рут а!
К р е с т указы вае т место!
Сундук открывает­
ся, и вы находите..
...билеты в кино!
Р азве эт о н е зн ак судьбы? Вы п о зн а к о м и л и сь с ц и кл ом w h i l e
и о б н аруж и л и б и л еты в ки н о, зн ач и т , нам п о р а вернуться...
к р а б о т е над п р и л о ж е н и ем M andango!
254
глава 5
циклы
далее >
255
решение упражнения
Возьми в руку карандаш
Решение
Вот как выглядит функция f i n d S e a t s () после замены цик­
ла f o r циклом w h i l e и ввода новой переменной f i n i s h e d ,
которая вместо оператора b r e a k будет отвечать за выход из
цикла.
Э т о т ц и кл в к а к о м -т о см ы сле я в л я ­
ет с я гидридом т о го , чт о м ы видели
раньш е. Ведь выход из цикла за ви си т
как о т показаний сч ет чика, т а к и о т
логического выражения. В т а к и х с л у ч а ЯК лу ч ш е испол(узов^иль цикл while.
J
Ц и кл р а б о т а е т , пока
значение сч ет ч и ка м ен ьш е
числа сидений И п е р е м е н ­
ная "finished" не п р и н и м а ­
е т значение tru e.
Инициализация
счетчика цикла
и переменной
"finished".
L
.ШК.!.л.??Л
г..
.
w hile ((i < seats.len0 th ) §£& lfm ^ ^
11
п р о в е р я е м
i f
( s e a t s [ i ]
т е к у щ е е
&&
м е с т о
s e a t s [ i
к р е с л а
и
+
и
1]
...........
д в а
м е с т а
&&
s e a t s [ i
о б н о в л я е м
+
ним
2 ])
{
/ /
В ы д ел я ем
„
„ о л ь ,о . а , е л . „ р е „ а ™ . , с , _ „ р » я , ь „ р е л л о ж ,.™
var accept = confirm( Seats
"
a r e
a v a i l a b l e .
и х
з а
+ u
в и д
^
^
+
A c c e p t ? " ) ;
if_(acce0 ) , l ....................................................................................................... .........................
.....................
/ / К р ес л а забронированы ^ п о э т о м у р а б о ^
finished - tru e;
.......................................................................................................
// Пользователь отказался7''п?10ДОЛжаем поиск
И нкремент счет чика
цикла.
256
глава 5
П рисвоение п ер ем ен н о й "finished"
значения tr u e п р и во д и т к в ы ­
ходу из цикла. И м енно п о э т о м у
в данном м е с т е вам больш е не
т р е б у е т с я о п е р а т о р break.
циклы
Приложение Mandango выглядит здоро­
во, вот только я не знаю ни одного кино­
театра со всего одним рядом кресел. Надо
бы его отредактировать...
Кинотеатр — место моделирования данных
Д ж е й с о н прав. Ч т о б ы п р о гр а м м а M an d a n g o стал а ф у н к ц и о н ал ьн о й
ее нуж но п е р е п и с а т ь с у ч етом р е а л ь н ы х условий. П р и м е р с од ним
ряд о м кр е с е л о ч е н ь пом ог, т а к как п о зв о л и л п р я м о св я зать м ассив
л о ги ч ес к и х д ан н ы х с и зо б р а ж е н и я м и . Т е п е р ь нам нуж но д о б ави ть
к м ассиву в т о р о е и зм е р е н и е . Д а, да, м ы го в о р и м и м е н н о о двум ер­
ном массиве!
в эт ом к ш т е а п р
т
т
т
Каждый э л е м е н т
двум ерного м ассива
о т н о си т с я к л о г и ­
ческом у т и п у .
Н ам п о тр еб у ется м ассив р а зм е р о м 9 x 4 , к о т о р ы й будет с о о т в ет ­
ство в ать ч ет ы р е м рядам и з д е в я т и кресел.
Э т о еще. одно и зм ерени е
индексов м ассива.
далее
►
257
больш е, чем одно изм ер ени е
двумерные массивы
Д л я со зд ан и я д вум ерн ого м асси ва вам н е п о тр еб у ется н и к ак и х н овы х
свед ен и й . Вы всего ли ш ь сф о р м и р у е те м ассив, эл ем ен там и к о т о р о го
будет другой м ассив. И м е н н о эт о д о б а в и т в т о р о е и зм е р е н и е . В р е ­
зультате вы п о л у ч аете таблицу д ан н ы х , р а с п р е д ел е н н ы х п о стр о кам
и столбцам .
Н ачнем с м а сси ва , к о т о р ш
— .с т а н е т основой для д о п о л н и т е л ш ы к м ассивов. Э т о
п ервое изм ерение!
Создадим д ополнит ельны е
м ассивы , кот оры е с т а н у т
эл е м е н т а м и первого м а с с и ­
ва. Э т о вт о р о е изм ерение!
var seats = new Array(new Array(9), new Array(9), new Array(9), new Array(9));
V
_____
Ч ет ы ре влож енных м ассива дадут
на м чет ы р е ряда.
Р аб о та я с п р о гр а м м о й M an d a n g o , м ы зн аем н ач а л ь н ы е зн а ч е ­
н и я эл ем ен то в , по это м у д ля со зд ан и я д ву м ерн ого м асси ва вос­
п ользуем ся м ассивом ко н стан т. Д р у ги м и сл овам и, м ы о д н о в р е ­
м е н н о создадим и и н и ц и ал и зи р у ем массив!
/двойны е скобки
указы ваю т , на д в у ­
м ер ны й массив.
var seats = [[ false, true, false, true, true, true, false, true, false ],
[ false, true, false, false, true, false, true, true, true ],
[ true, true, true, true, true, true, false, true, false ],
[ true, true, true, false, true, false, false, true, false ]];
Первый перечень логических
значений с о о т в е т с т в у е т
п е р во м у ряду д вум ерного
м ассива.
Каждый влож енный
м а с с и в и м е е т свои
собст венны е и н д ек­
сы. в данном случае
False — м е с т о
уже занят о.
258
глава 5
T rue - - м е ~сто свободно.
циклы
Двумерные массивы
позволяют сохранять
строки и столбцы
таблиц.
ДВа ключа доступа
Д оступ к д ан н ы м д вум ерн ого м асси ва о т л и ч а е т с я о т уж е п р и ­
в ы ч н о й вам п р о ц ед у р ы указан и ем д о п о л н и т е л ь н о го ин декса.
Д ругим и сл овам и, вам п р и х о д и тс я как б ы указы вать н о м е р
с т р о к и и сто лб ц а, о п р е д е л я я м е с то п о л о ж е н и е м ассива. В от
как будет в ы гл яд еть код доступа к элем енту, ч етв е р то м у во
второ
ряду.
В т о р о м у ряду с о о т в е т с т в у е т
индекс X (н у м е р а ц и я начинает ся
с О).
Д бд изм ер ени я
/
alert(зеа18[1][3]);
V
Одно изм ерение.
___ 1^ е т в е р т о м у э л е м е н т у
в ряду с о о т в е т с т в у е т
индекс 3.
Д л я п р о с м о т р а эл ем ен то в д вум ерн ы х м асси во в н ам п о тр еб у ю т­
ся в л о ж е н н ы е ц и кл ы . В н еш н и й ци кл будет у п р авл я ть п е р е х о ­
дом о т о д н о го р я д а к другому, в т о в р ем я как в н у т р ен н и й — п р о ­
см а тр и в а ть м еста.
Влож енные ц и ­
клы д а ю т д о с т у п
к данны м д в у м е р ­
ных м ассивов.
далее >
259
решение упражнения
Возьми В руку карандаш
Решение
Вот код просм отра элементов д вум е р н о го массива s e a t s ,
извещ аю щ ий пользователя о состоянии ка ж д о го места.
В н у т р е н н и й ц и кл
просм ат ривает
м е с т а в вы бранном
р я д у, м еняя значение
сч ет ч ика J.
В неш ний ц икл п е р е х о д и т
о т одного ряда к д р у го м у ,
м еняя показания сч ет чи ка /.
П р о с м о т р данных
двум ер но го м ассива
осуш ,ест вляет ся
>лри п о м о щ и двух
влож енных циклов.
Э т о длина
влож енно­
го м ассива
в ряду I.
fo r (v a r i - О; i < sea ts.len ^th ; ('++)
^
fo r (v a r j = O; J < seatsp'].length; J++) (
Д л я д о ст уп а к каж
д ом у кр е с лу нужн
у к а з а т ь , в каком
ряду ( 1) и в ка ко м
ст о лб ц е ( j ) оно
располож ено.
if (seats[i][j])
r t(" S e a t " + i -h " in ro w " + j + " is available.'');
alertC 'S ea t “ + i + " in ro w " +J +■ " is n o t available.");
В за ви с и м о с т и о т т о го ,
свободно м е с т о (tru e ) или
за н ят о (false), б уд у т п о ­
я вля т ь с я окна с р а зн ы м и
сообщ ениям и.
В сообщ ении о свободном
м е с т е ука зы вает ся его
н о м ер и в ка ко м ряду оно
располож ено.
Часто
'^адаБаеМые
БоИ роС Ь!
Существуют ли массивы большей
размерности?
0 ; Да, хотя визуализировать их сложнее.
Трехмерные массивы обычно соответству­
ют х-у-1-координатам точки в простран­
стве. Массивы еще большей размерности
применяются в редких случаях. Чтобы '
добавить очередное измерение, достаточ­
но сделать элементы внешнего массива
в свою очередь массивами.
Если инициализация элементов
массива происходит в момент его
создания, можно ли добавлять в него
элементы постфактум?
; Вы в любой момент можете назна­
чить данные неиспользуемому элементу
массива. Например, в нашем примере
можно создать еще один ряд (с индексом 4).
Достаточно назначить массив элементу
s e a t s [ 4 ] . Можно также воспользовать­
ся функцией p u s h () и добавить новый
элемент в конец массива.
260
глава 5
3 * Двумерные массивы должны
содержать одно и то же количество
рядов?
! Не обязательно. Но помните, что
в этом случае могут возникнуть пробле­
мы с циклами, так как вложенные циклы
обычно работают с массивами одинако­
вой длины. Так что, несмотря на принци­
пиальную возможность варьировать длину
рядов двумерного массива, лучше этого
избегать.
циклы
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
■
Двумерные массивы позволяют сохранять строки
и столбцы таблиц.
Для просмотра элементов двумерных массивов ис­
пользуются вложенные циклы.
в
Для доступа к элементам двумерного массива ука­
зывайте индексы строки и столбца.
Как и в обычном случае, двумерные массивы могут
быть инициализированы набором констант в момент
их создания.
двумерная Версия Mandango
Вы уже р а б о т а л и с о тд ел ьн ы м и ч ас тя м и ко д а M an d an g o , но
п е р ех о д о т е д и н ств ен н о го р я д а к целом у к и н о т еа тр у тр еб у ет
с е р ь е зн о го р е д а к ти р о в а н и я . П о это м у будьте в н и м ател ьн ы .
Д ля просм от ра
д вум ер но го м ассива
кр есел ва м п о т р е ­
б ую т с я два с ч е т ­
чика.
П ереход о т
одном ерной
к двум ер­
ной версии
Мапе1апдо
т ребует
внесения
серьезны х
и зм енений
в код.
Ш ТУРМ
Каким образом нужно поменять код программы Mandango, чтобы она начала работать
с целым кинотеатром? Как бы вы это визуализировали?
д алее >
261
для этого кода вам не нужны стереоочки
<htm l>
<head>
< title> M a n d a n g o - поиск билетов для Ma4o</title>
В о т полны й код для
Щ т е р н о й версии
M andango!
< sc rip t ty p e = "te x t/ja v a sc rip t">
v a r s e a t s = [[ f a l s e , t r u e , f a l s e , t r u e , t r u e , t r u e , f a l s e , t r u e , f a l s e ],
[ f a l s e , t r u e , f a l s e , f a l s e , t r u e , f a l s e , t r u e , t r u e , t r u e ],
[ t r u e , t r u e , t r u e , t r u e , t r u e , t r u e , f a l s e , t r u e , f a l s e ],
[ tru e , tru e , tru e , fa ls e , tru e , fa ls e , fa ls e , tru e , fa ls e ]];
v a r s e lS e a t = -1;
mandango.html
fu n ctio n i n i t S e a t s 0 {
Создан двум ерны й м ассив
/ / З а д а єм вид в с е х к р е с е л
логических конст ант , co~
сг
f o r ( v a r і = 0; і < s e a t s . l e n g t h ; i+ + ) {
f o r ( v a r j = 0; j < s e a t s [ 1 ] . l e n g t h ; j + + ) {
держ ащий и н ф о р м ац и ю
if (se a ts[i][j]) {
о дост упност и кресел.
/ / Задаем свободные м е с та
d ocum ent. g etE le m e n tB y ld (" s e a t " + (І * s e a t s [ І ] . l e n g t h + j ) ) . s r c
"se a t_ a v a il.p n g "
d ocum ent. g e tE le m e n tB y ld (" s e a t" + (і * s e a t s [ і ] . l e n g t h + j ) ) . a l t
"A v ailab le s ea t"
)
e lse {
/ / Задаем заняты е места
d o c u m e n t. g e tE l e m e n t B y l d (" s e a t " + ( i * s e a t s [ i ] . l e n g t h + j ) ) . s r c = " s e a t _ u n a v a i l . p n g "
d o c u m e n t.g e tE le m e n tB y ld ("se at" + ( i * s e a t s [ i l . l e n g t h + j ) ) . a l t = "U n a v ailab le s e a t"
)
}
fu n ctio n fin d S ea tsO {
/ / Е с л и м е с т а уже вы бр аны , п р о и з в е 1&1т е п о в т о р н у ю и н и ц и а л и за ц и ю
i f ( s e l S e a t >= 0) {
s e lS e a t = -1;
i n i t S e a t s () ;
}
/ / П оиск с в о б о д н ы х м е с т с р е д и в с е х во змож ных
v a r i = о, f i n i s h e d = f a l s e ;
w h i l e ( i < s e a t s . l e n g t h && I f i n i s h e d ) { ^
f o r (v a r j = 0; j < s e a t s [ i ] . l e n g t h ; j++) {
/ / П р о в е р я е м , с в о б о д н о л и т е к у щ е е м е с т о и д в а м е с т а з а ним
i f ( s e a t s [ i ] [ j ] && s e a t s [ i ] [ j + 1] && s e a t s [ i ] [ j + 2 ]) {
/ / Выд еляем к р е с л а и о б н о в л я е м и х в и д
selS eat = i * s e a ts [ i] .le n g th + j;
docu m en t.g etE le]T ien tB y Id ("seat" + (i * s e a t s [i] . l e n g t h +
d o c u m e n t.g e tE le m e n tB y ld C 's e a t" + (i
s e a t s [ і ] . le n g th
d ocum ent. g e tE le m e n tB y ld (" s e a t
(і * s e a t s [ і ] .le n g th +
d ocum ent. g e tE le m e n tB y ld (" s e a t
(і * s e a t s [ і ] .len g th +
d o cu m en t. g e tE le m e n tB y ld (" s e a t
s e a t s [ і ] . len g th + j
(і
d o cu m en t. g e tE le m e n tB y ld (" s e a t
s e a t s [ i l . len g th + j
(і
Если п о ль зо ва т е ль
— ______ на ч и на ет новый поиск
щ елч ко м на кнопке
Find S e a ts, п о вт о р н о
(инициализируем э л е ­
м е н т ы м ассива.
Д л я п р о с м о т р а рядов
и с п о л ь зуе т с я ц и кл w hile,
в т о вр ем я как ц и к л fo r
о с у щ е ст в л я е т п р о с м о т р
от д ельн ы х кресел.
) ) .s r c = "seat_ select.p n g ";
) ) . a l t = "Your s e a t " ;
+ l) } .s r c = "seat_ select.p n g ";
+ 1 ) ) . a l t = "Your s e a t " ;
+ 2) ) . s r c = " s e a t _ s e l e c t .p n g " ;
+ 2 ) ) . a l t = "Your s e a t " ;
/ / П о л ь з о в а т е л ю п р е д л а г а е т с я п р и н я т ь предл ож е нн ы й в а р и а н т
v a r a c c e p t = c o n f i r m ( " S e a t s " + ( j + 1) + " t h r o u g h " + (j + 3) +
" i n Row " + ' ( i + 1) + " a r e a v a i l a b l e . A c c e p t ? " ) ;
i f (accept) {
/ / К р е с л а з а б р о н и р о в а н ы , п о э т о м у р а б о т а в н е ш н е го ц и к л а з а к о н ч е н а
fin ish ed = true;
b reak;
)
e lse
262
глава 5
{
циклы
fI
П ользователь
отказался,
п родолж аем
s e lS e a t = -1;
d o c u m e n t.g e tE le m e n tB y ld C 's e a t"
d o c u m e n t. g e tE l e m e n t B y l d (" s e a t "
d o c u m e n t.g e tE le m e n tB y Id (" s e a t'‘
d o c u m e n t.g e tE le m e n tB y Id { "se a t"
d o c u m e n t . g e t E l e m e n t B y l d C ’s e a t "
d o c u m e n t.g e tE le m e n tB y Id (" se at"
//
У величиваем
счетчик
вн еш н его
+
+
+
+
+
+
цикла
(
(
(
(i
{i
(i
на
поиск
sea ts[i].le n g th
s e a t s [ i ] . len g th
s e a t s [ i ] . le n g th
s e a t s [ i ] •le n g th
sea ts[i].le n g th
s e a t s [ i ] . le n g th
един ицу
i++;
< /scrip t>
< /head>
vT
Ф у н к ц и я in itSeatsQ
вы зы вает ся п р и
п е рвой за гр у зке
ст раницы .
j ) ) . s r c = • 's e a t _ a v a i l .p n g " ;
j ) ) . a l t = "A v ailab le s e a t" ;
j + l ) ) . s r c = " s e a t_ a v a il.p n g "
j + l ) ) . a l t = "A v ailab le s ea t"
j + 2) ) . s r c = " s e a t _ a v a i l . p n g "
2 ) ) , a l t = "A v ailab le s e a t"
с
Именно благодаря
счетчиКйМ м е н я ю т ­
ся изображения к р е ­
сел и всплывающии
т екст .
<body o n l o a d = " i n i t S e a t s { ) ;" >
« d i v sty le= "m argin -to p:2 5 px ;
<i m g i d = " s e a t O " s r c = " " a l t =
Н е п у га й ­
<im g i d = " s e a t l " s r c = "
<im g i d = " s e a t 2 " s r c = "
тесь
<im g i d = " s e a t 3 " s r c = "
разм еров
<img i d = " s e a t 4 " src=="
<img i d = " s e a t 5 " s r c = "
это го кода.
<im g i d = " s e a t 6" s r c = "
<img i d = ' ' s e a t ? " s r c = " " a l t = " " / >
З д е сь и сп ользуется уж е зн ак о м ая вам
<img i d = ' ■ s e a t 8" s r c = " " a l t = " " / X b r / >
т
е х н и к а р а б о т ы с двум ерн ы м и м асси­
<img i d = ' ' s e a t 9 " s r c = " " a l t = " " / >
<img i d = ' ’s e a t l O " s r c = " " a l t = " ' " / >
вам и, ад а п ти р о в а н н а я д ля п р и л о ж е н и я
<img i d = ' ' s e a t l l " s r c = " " a l t = " ' " / >
M a n d a n g o , с е г о H T M L -кодом и и зо ­
<img i d = ' " s e a t l 2" s r c = " " a l t = " ' " / >
б р аж е н и я м и (все эт и м а тер и ал ы м ож н о
<im g i d = ' " s e a t l 3 " s r c = " " a l t = " ' " / >
<im g i d = ' " s e a t l 4 " s r c = " a l t = " " / >
с к ач ать здесь: http://xmvw.headfirstlabs.com/
V Д ля
<im g i d = ' " s e a t l S " s r c = " " a l t = " " / >
books/hfjs/).
^
^
ч
г
т
ш
е
к
"
a
l
t
=
"
/>
<img i d = ' " s e a t l G " s r c = "
<img i d = ' " s e a t l ? " s r c = " " a l t = " " / x b r / >
f рядов по
<img i d = ’" s e a t l S " s r c = " " a l t = " " / >
девят ь
<img id = '" s e a t l 9 " s r c = " " a l t = " ’■ / >
сидений
<img id = '" s e a t 20" s r c = " " a l t = " " / >
пот ре­
<im g i d = " s e a t 21" s r c = " " a l t = " " / >
бует ­
<im g i d = " s e a t 22" s r c = " " a l t = " " / >
ся 36
<img i d = " s e a t 2 3 " s r c = " " a l t = " " / >
<img i d = " s e a t 2 4 " s r c = " " a l t = " " / >
изобра­
<img i d = " s e a t 2 5 " s r c = " " a l t = " " / >
жений...
"
/
x
b
r
"
a
l
t
=
"
/
>
<img i d = " s e a t 2 6 " s r c = "
кошмар!
<img i d = " s e a t 2? " s r c = " " a l t = " " / >
Ф у н к ц и я FindSeatsQ
<img i d = " s e a t 2 8 " s r c = " " a l t = " " / >
вы зы вает ся ш ,елч<im g i d = " s e a t 2 9 " s r c = " " a l t = " " / >
к о м на к н о п ке Find
<img i d = " s e a t 3 0 " s r c = " " a l t = " " / >
Seats.
<img i d = " s e a t 3 1 " ' s r c = " " a l t = " " / >
<img i d = " s e a t 3 2 " ' s r c = " " a l t = " " / >
<im g i d = " s e a t 3 3 " ' s r c = " " a l t = " " / >
<im g i d = " s e a t 3 4 " ' s r c = " " a l t = " " / >
<img i d = " s e a t 3 5 " 1 s r c = " " a l t = " " / x b r / >
< i n p u t t y p e = " b u t t o n ' l d = " f i n d s e a t s " v a l u e = " F i n d S e a t s " o n c l l c k = " f i n d S e a t s ()
< /div>
< /body>
</htm l>
J
далее >
263
вне себя от радости
Целый кинотеатр мест для мачо
Т е п е р ь , когда п р о гр а м м а M a n d a n g o стал а двум ерн ой , С ет
и Д ж е й с о н могут и ск ать м еста по всем у ки н отеатру... и со с в о и ­
м и к р и т е р и я м и поиска! П а р н и в в о с то р ге .
Мы больше никог­
да не будем сидеть
рядом!
Класс!
Т еп ер ь M a n d a n g o м ож ет
и с к а т ь наборы из т р е х
свободных м е с т подряд
по всем у к и н о т е а т р у .
М^ап§^
пев
т
Ticlusi Findef
л
J
Seats 2 through 4 in Row 3 are
(
■ iiip e
264
глава 5
Cancel
available. Accept?
(
OK
циклы
В к л а д к а
Согните страницу
по вертикали, ч т о б ы
совместить два мозга
и р е ш и т ь задачу.
Что общего у ЦИКЛОВ с фильмами?
\ } Д х.у роШ о. а д В а лу'ІЯіе!
Некоторые фильмы имеют сюжет,
за которым сложно уследить.
Другае фильмы привлекают зрителя
постоянным движением.
Но любой фильм — это только фильм.
с :>ункДии
Многократное использование
Начни JavaScript выступать за экологию, это выступление
возглавили бы функции. Ведь именно они увеличивают эффективность
кода и позволяют использовать его многократно. Они ориентированы на ре­
шение задач и позволяют все систематизировать. Функции дают возможность
упростить любой сценарий, ну кроме разве что и так простых. Их значение не­
возможно оценить, поэтому просто скажем, что именно функции делают сце­
нарии такими экологичными.
анализ большой проблемы
источник Всех проблем
П о больш ом у счету н а п и с а н и е с ц е н а р и е в д ля веб-стран и ц
я в л я е т с я р е ш е н и е м задач. В дум чивы й подход и п л а н и р о в а н и е
всегда п о зв о л я ю т н а й ти в е р н о е р еш ен и е. Н о как б ы ть с о ч е н ь
б о л ь ш и м и за д ач а м и ?
Мир во всем мире
В о т наш а
больш ая
задача!
Б о л ьш и е зад ач и и м е е т см ы сл р еш ать путем р а зд е л е н и я и х н а б олее
м ел ки е. Е сли даж е п о сл е эт о го зад ач и о с таю тся слиш ком б ольш и м и , п о ­
д ел и те их еш;е раз.
бо льш а я
задача.
Вш,е м еньш ая
задача.
/
Выращ ивание
\
|1
Продажа
Право на
С т ройка
1
зем л ю
Свобода
слова
Право г о ­
лоса
1
Э ту проц едуру м о ж н о п р о д о л ж и т ь снова, и снова, и снова...
268
глава 6
функции
Решение задач снизу
Р азд ел я я в о п р о с о м и р е во всем м и р е н а б о л ее м ел ки е, м ы р а н о
и л и п о зд н о п р и д ем к задачам , р е ш и ть к о т о р ы е м о ж н о п р и п ом ощ и
Д ауа8спр.
Кров
\
чая
П р ед став и м п р о б л ем у у п р ав л ен и я кл и м ато м в т е р м и н а х JavaS cript.
Вам п о тр еб у ется эк в и в а л е н т т е р м о с т а т а , к о т о р ы й о б ы ч н о и сп о л ь­
зуется д ля к о н т р о л я те м п е р а ту р ы о круж аю щ ей среды . С ам ы й п р о ­
с т о й т е р м о с т а т с о с т о и т и з е д и н с т в е н н о й к н о п к и «H eat».
Л роет ейилий т е р
/л о с т л т — н й Ж М ите кн о п к у,
и он за р а б о т а ет .
HEAT FIRST
В ам не и н т е р е с ­
но, ка ки м образом
работ ает т е р м о ­
с т а т , дост ат очно
т о го , ч т о вы у м е ­
е т е его вклю ч а т ь.
П о д о б н а я м одель т е р м о с т а т а н е д аст вам п р е д с тав л е н и я о том , как
осущ ествл яется н агр ев. В ы н аж и м аете кн опку H e a t, и ст ан о в и т ся
теп л о . П р о б л е м а у п р ав л ен и я кл и м ато м реш ена!
далее *
269
методы как решение маленьких задач
Функции как способ решения
Функции превращают
большие задачи
в маленькие.
К н о п к а H e a t н а т е р м о с т а т е э к в и в а л е н т н а ф у н к ц и и в JavaS cript.
И д ея п р о с т а я — ч ел о в е к п р о с и т сдел ать п о т е п л е е, и ф ун кц и я
осу щ ествл яет н агр ев. Д е та л и р е а л и за ц и и ск р ы т ы вн утри и для
кода, к о т о р ы й его в ы зы в ает, н е важ н ы . Ф ункцию м о ж н о п р ед ­
с т ав и ть в виде « ч ер н о го ящ ика» — и н ф о р м а ц и я н а входе и и н ­
ф о р м а ц и я н а вы х о д е, а за то , ч т о п р о и с х о д и т вн утри , о т в е ч а е т
сам ящ и к.
Просьба
сделать тепло
Нагрев
Н а я з ы к е Jav aS crip t н а ж ат и е к н о п к и H e a t эк в и в ал ен т н о вы зову
ф у н к ц и и h e a t ( ) ...
Просьба оде
лать тепло
heat О ;
function heat о
{
// Увеличим температуру
^
Нагрев
Т о м у , к т о хо ~
чет увеличит ь
т ем п ер а т ур у, до­
ст а т о ч н о вы зват ь
ф у н к ц и ю heat().
shovelCoalО ;
lightFire О ;
За нагрев о т в е ч а ю т
т р и другие ф ункции.
harnessSun();
}
В олноват ь­
ся о т о м , как
им енно о с у щ е с т ­
в л я е т с я нагрев,
должен т о ль к о человек, ко т о р ы й
пиш ет ф ункцию
кеа±().
270
глава 6
Н е и м е е т зн а ч е н и я , к аким образом ф ун кц и я h e a t () осущ ест­
в л я е т н агрев. В аж н о т о л ь к о то , ч т о о н р е ш а ет наш у проблем у.
Х о т и т е с о гр еть с я , в ы зо в и т е эту ф ункц ию . Э то все, ч т о вам
тр еб у ется зн ать.
функции
(1з чего состоит функция
Р еш и в со зд ать ф у нкц ию , вы б е р е т е н а себ я о т в е тс т в е н н о с т ь
за р е ш е н и е о п р е д е л е н н о й задачи. Вы д о лж н ы и сп о л ьзо в ат ь
о п р е д е л ен н ы й си н так си с, связы ваю ш ,ий и м я ф у н кц и и с запу­
скаем ы м ею кодом . В от как о н в ы гл яд и т в общ ем виде;
В начале и д ет
клю чевое слово
fu n ctio n .
З а т ем — идент иф икат ор,
■написанны й с п р и м е н е н и е м
ст и ляВ ерблю д а.
К од 6 т е л е ф ункции п р е д ­
с т а в л я е т собой обычный
сост авной о п е р а т о р ,
п о э т о м у он начинает ся
с ^>игурной скобки.
function \ +
V
И м енно в т е л е
ф ун кц и и р еш а ет ся
непосредст венная
задача.
в конце ф ункц и и не
за б уд ьт е п о с т а в и т ь
за к р ы ва ю щ у ю ф и ­
г у р н у ю скобку.
Скобки у к а зы ва ю т
на т о , ч т о перед
н ам и ф ункция.
Е щ е р аз в н и м ател ьн о п о см о тр и м н а код ф у н кц и и h e a t ( ) , ч т о ­
б ы з а к р е п и т ь п о л у ч ен н ы е зн а н и я о си н такси се:
function heat () {
II
Увеличим температуру
shovelCoal();
Н агревание о с у ­
щ е с т вля е т ся
в т е л е ф ункции.
lightFireО ;
harnessSunО ;
Тело ф ун кц и и заклю чено
в ф и гурны е скобки и я в ­
л я е т с я обычным с о с т а в ­
ны м о п ер а т о р о м .
Ш ТУРМ
Какие еще функции вы можете вспомнить?
далее >
271
мет оды m andango
У)ке знакомые Вам функции
Н е т а к д авн о м ы п р е к р а с н о с п р а в и л и сь с п р о б л ем о й . П о м н и те
про гр ам м у M a n d a n g o д ля п о и ск а м ест в к и н о т еа тр е? Вам т р е б о ­
вал о сь и н и ц и а л и зи р о в а т ь д ан н ы е о м естах. В от каки м о б р азо м
мы п о д ел и л и глобальную задачу н а б о л ее м елкие:
больш ая
задача.
Поиск м е с т
Зля Майо
А в е м еньш и е
задачи.
Поиск
м ест
И ни ц и а ли за ц и я
м ест
М с-
И н и ц и а л и за ц и я к р е сел это м ал ен ькяя задача, к о т о р а я м ож ет
б ы ть р е ш е н а п р и п ом о щ и ф у н кц и и i n i t S e a t s ( ) :
function initSeatsо {
// Задаем вид всех кресел
for {var i = 0; i < seats.length; i++) {
for (var j = 0; j < seats[i].length; j++)
if (seats [i] [j ]) {
// Задаем свободные места
(i
document.getElementByld("seat"
(i
document.getElementByld("seat”
seats[i].length
seats[i].length
j)).src
j)).alt
"seat^avail.png";
"Available seat";
}
else {
// задаем занятые места
document.getElementByld("seat"
document.getElementByld("seat"
seats[i].length + j)).src = "seat_unavail.png"
seats[i].length + j)).alt = "Unavailable seat"
}
Ф ункция i n i t S e a t s {) я в л я е т с я частью в еб -стр ан и ц ы M a n d an g o
Д ля е е в ы зо в а н ам п о тр еб у ется св я за ть е е с о б р аб о т ч и к о м со б ы т и я
o n l o a d . В р езу л ьтате ф у н кц и я будет запускаться п о сл е загрузки
стр ан и ц ы .
А.А ч
iriitSeatsQ не ед и н ст вен н а я ф ункция
О M andanqo.
andango.
/
<body
onload="initSeats(); ">
<div style="height:2 5 p x "x/div>
<div style="text--align: center">
<img id="seatO" src="" alt="" />
<img id="seat35" src="" alt="" / x b r />
<input type="button" id="findseats" value="Find Seats" onclick- 'findSeats0 ;" />
</div>
</body>
</html>
272
глава 6
функции
Часзи»
^аД аБаеМ ы е
Б о 1 ]|э о С Ь 1
Каким образом составляются
имена функций?
0 ; Первое слово пишется прописными
буквами, в то время как все остальные
Точно так же людей назначают на
различные должности, чтобы каждый мог
сфокусироваться на своих обязанностях.
В таких ситуациях функции улучшают
структуру сценария, делая его более
начинаются со строчных. Поэтому
функцию оценки фильмов мы назовем
читаемым.
r a t e M o v i e ( ) , а функцию вывода
из зала мужчины, который хочет во
^ Как определить, какой фрагмент
кода может быть помещен внутрь
функции?
время сеанса говорить по телефону —
логических частей.
r e m o v e In a p p r o p r ia te G u y ( ) .
Всегда ли функции превращают
большие задачи в набор более мелких?
0=
! Не всегда. В некоторых ситуациях
санкции используются сами по себе, как
набор кода. То есть одна задача может
решаться целым набором функций.
В этом случае каждая из них имеет свое
собственное назначение.
приходится в несколько мест сценария
одновременно. Поэтому дублирующиеся
фрагменты желательно соединить
в функцию. Вторым признаком является
слишком большой фрагмент кода,
который можно поделить на несколько
0 ; к сожалению, алгоритма,
позволяющего однозначно определить,
что вот этот фрагмент кода будет уместен
в виде функции, не существует. Но
существует ряд признаков, на которые
имеет смысл обратить внимание.
Одним из таких признаков является
дублирование кода. В этом случае вы
попадаете в ситуацию, когда, например,
вносить одинаковые исправления
В книге упоминалось, что
( >ункциям можно передавать
аргументы и получать от них данные.
Это действительно так?
! Вы правы. Функции действительно
берут и возвращают данные. И скоро
вы увидите эту процедуру на примере
функции h e a t ( ) .
Значимое имя позволяет сразу понять назначение функции. Присвойте этим функ­
циям названия, не забывая про СтильВерблюда.
Request aisle s e a t.
Ask for refund
Throw popcorn
Receive tic k e t for aisle seat
G et refund
Popcorn is hurled a t others
далее *
273
решение упражнения
Вот какие имена можно присвоить описанным ниже функциям.
пражнш е
решение
Request aisle s eat — . >
Receive tic k e t for aisle seat
requestAisleSeatQ
A sk for refund
G et refund
g e tR e fu n d Q
T h ro w popcorn
Popcorn is hurled a t others
th ro w P o p co rn Q
НЫК при помощи ст иляіерблюда
Меня просто поджарили!
Неужели это Эффект локаль­
ного потепления?
Слишком )карко
П о к а ч то п о п ы тк и у стан о в и ть м и р во всем
м и р е путем у п р ав л ен и я кл и м атом т е р п я т
неудачу. К аж ется, н аш а к н о п к а H e a t р а б о т а е т
слиш ком х о р о ш о . А м о ж ет б ы ть, п р о б л е м а
в н е д о с та тк е д ан н ы х д ля ф у н кц и и h e a t () .
К ак бы т о н и б ы ло , ситуацию нуж но
и сп р ав л ять.
274
глава 6
функции
Улучшаем наш терм остат
Т е р м о с т а т н е зн а е т , когд а следует о с т ан о в и т ь н агр ев, т ак как
нужную н ам тем п ер ату р у м ы н е указали. П о л у чается, ч т о для
э ф ф е к т и в н о г о р е ш е н и я п р о б л ем ы н е д о с та т о ч н о д ан ны х. И п о ­
сле н а ж ат и я к н о п к и H e a t т е м п е р а ту р а будет р а с ти бескон еч н о!
Э т о т регулят о р помож ет задать
ж елаемую т ем п ер а т ур у.
HEAT FIRST
Н о в а я в е р с и я т е р м о с т а т а п о зв о л я е т указы вать ж ел ае­
мую тем п ературу. И б лагод аря этом у лучш е сп р ав л я е тся
с зад ач ей «нагрева».
Просьба сделать
теплее
Желаемая
температура
Ж елаем ая т е м п е р а т у р а
СГе
ГІраЖН€НУ12
ЛлГфак“кц»,
Нагрев
^
heat (targetren*.) ;
Напишите код функции h e a t ( ) . Функция должна использовать в качестве
параметра указанную пользователем температуру и осуществлять нагрев только
до ее достижения. Подсказка: температуру в данный момент определяет функция
g e t T e m p ().
fu n c tio n h e a t(ta rg e tT e m p ){
Первая с т р о ч к а .......................................................................................................................................
уж е написана.
далее *■
275
решение упражнения
іажнение
У гш гн м
Вот как выглядит новый код функции h e a t ( ) , написанный с учетом
перечисленных на предыдущей странице пожеланий:
fu n c tio n k e a t(ta r g e tT e m p )l
...................
Ж ела ем а я т е м п е р а т у ­
р а п ер ед а ет ся ф ункц и и
в ка ч ест ве а р гу м е н т а .
Н агрев н а ч и н а е т ­
ся т о ль к о в случае,
когда окруж аю щ ая
‘т е м п е р а т у р а м е н ь ­
ш е желаемоіл.
w hile (g e tT e m p O < ta rg e tT e m p ) {
■/ / Н агрев
..................................................................... Ж ёлШ М -ая-т е-м пер-ат т .
skovelCoalQ;
иказы вает ся в услооии
.....;........................................................ Ш б -д а -us-цикла-.while ........
lightFireQ;
harnessSunQ ;
}
Передача информации функциям
Д ан н ы е п ер ед аю тся ф у н кц и ям Jav aS crip t п р и п ом ощ и аргументов. С н о в а в н и м ател ь н о р а с с м о тр и м си н такси с; о б р а т и т е вним ан и е н а то , ч то аргум ен ты ф у н кц и и зак л ю ч ен ы в скоб ки .
ß
^
указан о
бы т ь
число а р г у м Т н т о Т ^ ^
_^
Аргументы
Т е ло м ф ун кц и и а р гу м е н т ы
во с п р и н и м а ю т с я как и н и ­
ц иализированны е локальны е
перем енны е.
Т е о р е т и ч е с к и вы м о ж ете п е р ед ать ф у н кц и и п р о и зв о л ь н о е
к о л и ч е с т в о аргум ен тов, н о с п р а к т и ч е с к о й т о ч к и зр е н и я
ж е л а т е л ь н о о г р а н и ч и т ь с я двумя-трем я. В ка ч е ств е аргум ента
м о ж е т вы ступ ать л ю б о й ф р а гм е н т и н ф о р м ац и и : к о н стан та
( M a th . P I), п е р е м е н н ая (tem p) и л и п о с т о я н н о е зн а ч е н и е (72).
276
глава 6
функции
Аргументы как данные
Д а н н ы е , п е р ед ав аем ы е ф у н кц и и в к а ч е с тв е аргум ента, п од об ­
н ы и н и ц и а л и зи р о в а н н ы м л о кал ьн ы м п ер ем ен н ы м . В к ач естве
п р и м е р а р а с с м о тр и м ф ункц ию h e a t ( ) , к о т о р о й п е р ед ает с я
ж ел аем ая тем п ер ату р а:
heat (72) ;
ігГ------Ж ела ем а я т е м п е р а т у р а
функции 6 биЭе иислобом к о н с т а н т ы .
ф у н к ц и я h e a t () в о с п р и н и м а е т ар гу м ен т t a r g e t T e m p как локальную п е р е м е н ­
ную, к о т о р о й б ы л о п р и с в о е н о н а ч а л ь н о е зн а ч е н и е 72. П о ст ав и м в т е л о э т о й
ф у н кц и и код, в ы зы в аю щ и й о к н о д и а л о га со зн а ч е н и е м аргум ента.
72
function heat(targetTemp)
{
В т е л е ф ун кц и и heatQ
а р г у м е н т вы глядит как
ло к а ль н а я перем енная.
alert (targetTeii5>) ;
}
После за вер ш ени я р а б о т ы
ф ун кц и и п ер ем ен н а я
ta r g e tT e m p уда ляет ся.
С1Ж Э
Х о тя ар гу м ен т и н а п о м и н а е т локальную пер ем ен н ую , р е д а к ти р о в а н и е
его в н у т р и ф у н кц и и н и н а ч т о н е в л и я е т . Э то п р а в и л о н е о т н о си т ся
к п ер ед ав аем ы м в к ач еств е аргу м ен то в о б ъ ектам , н о о н и х м ы п о го во ­
р и м в главах 9 и 10.
var ten^j = 80;
coollt (ten^)) ;
alert (teir^)) ;
Н есм о т р я на и з ­
м енени е т е м п е ­
рат уры внут ри
ф ункции, внеш ­
няя п ер ем енна я
о ст а ла с ь н е и з­
м енной.
П ерем енная te m p
была передана
ф ун кц и и в качест ве
а р гу м е н т а .
У м ен ьш и т е значение
т е м п е р а т у р ы на і-
function coollt(temperature)
temperature— ;
С
далее >
277
удаляем дубли при помощи мет одов
избавляемся о т дублирующегося кода
Ф ун кци и н е т о л ь к о п о зв о л я ю т р а зд ел и ть больш ую задачу н а н еск о л ьк о б о ­
л ее м елких, н о и даю т в о зм о ж н о с ть и зб а в и т ьс я о т дублирую ш;егося кода.
И м е н н о т а к н азы в аю тся о д н и и т е ж е ф р а гм е н т ы , появляю ш ;иеся в р а з­
н ы х м естах с ц е н а р и я. К од м о ж ет н е б ы ть п о л н о стью и д ен ти ч н ы м , н о во
м н о ги х случаях все р а в н о и м е е т см ы сл п р е в р а т и т ь его в ф у н к ц и ю .
В р езу л ьтате, есл и вам н ео б х о д и м о о т р е д а к т и р о в а т ь какой-то ф р а гм е н т ,
уже н е п о тр еб у ется и ск ать все его в х о ж д ен и я в с ц е н а р и й , д о ст а т о ч н о
будет в н е с ти и зм е н ен и я в т е л о ф ункции:
// В и л е т на д н е в н о й сеанс,
м е н ь ш е на 1C
m a tin e e T ic k e t = a d u ltT ic .e t
/ /
*
Детский
(i
f/
_ о . 10, ;
В ы числение скидки
п р е д с т а в л я е т собой
п р и м е р ненуж ного
дублирования кода.
Б и л е т д ля
U n io rT ic k et
}
= a d u ltT ic k e t
(1 - 0.15) ;
билет
c h ild T ic k e t
=
a d u ltT ic k e t
Г
П о к а за н н ы е вы ш е зад ач и сво д ятся к в ы ч и сл ен и ю ц ен ы б и л ето в
с у ч ето м р а зл и ч н ы х скидок. Н о н а сам ом дел е м о ж н о о г р а н и ч и т ь ­
ся за д ач е й п о в ы ч и сл ен и ю ц ен ы н а о с н о в е зад ан н о го п р о ц е н т а
скидки:
fu n c tio n
r e tu r n
d is c o u n tP r ic e (p ric e ,
(p ric e
*
(1
-
p e rc e n ta g e )
(p erc e n ta g e
/
{
1 0 0 )));
Функции воз
вращ аю т
данные.
B ut как будут выглядеть указанны е выше ф рагм енты кода после
создания функции d i s c o u n t P r i c e :
// Б и л е т на
д н е в н о й сеанс,
m a tin e e T ic k e t
меньше на К
// Б и л е т
= d isc o u n tP ric e (a d u ltT ick e t,
/ /
Детский
билет,
10) ;
меньше
Г ® " ^ ° ^ Т 1с к е Г
на
глава 6
м е н ь ш е на 15%
= d iisco u n tP ric e (a d u ltT ic k e t,
20-s
childTicket = discountPrice(adultTicket,
278
пенсионеров,
20);
15);
функции
^ щ а н ь
эК сяер ш о М
П о
Э‘
Циж е Показан к°Д «рункЦии fmJ^eatsO
us программы ]\|EnJango. ЦсЛоЛьЗуя
Полученные знания, оёБедшюе
'рраГМеашы Кода, к°іворьіЄ
М оїуш Тіосяужитоь осЯоБой
ДЛЯ ноБьіх <|>ункЦий.
function f i n d S e a t s о {
// Е с л и м е с т а у ж е выбраны,
if
(selSeat >= 0)
s e l S e a t = -1;
initSeats О ;
произведите повторную инициализацию
{
// П о и с к с в о б о д н ы х м е с т с р е д и в с е х в о з м о ж н ы х
v a r i = О, f i n i s h e d = false;
w h i l e (i < s e a t s . l e n g t h && Ifinished) {
for (var j = 0; j < s e a t s [ i ] .length; j++) {
// П р о веряем, с в о б о д н о л и в ы д е л е н н о е м е с т о и д в а м е с т а за
if (seats[i][j] && s e ats[i][j + 1] &s seats[i][j + 2]) {
// В ы д е л я е м к р е с л а и о б н о в л я е м и х вид
s e l S e a t = i * s e a t s [ i ] .l e n g t h + j;
s e a t s [ i ] .l e n g t h +
d o c u m e n t . g e t E l e m e n t B y l d ( " s e a t " + (i
s e a t s [ i ] .l e ngth +
d o c u m e n t . g e t E l e m e n t B y I d ( " s e a t " + (i
s e a t s [ i ] .l e n g t h +
d o c u m e n t . g e t E l e m e n t B y I d ( " s e a t " + (i
s e a t s [ i ] .l e n g t h +
d o c u m e n t .g e t E l e m e n t B y l d ( " s e a t " + (i
s e a t s [ i ] .length +
d o c u m e n t .g e t E l e m e n t B y l d ("seat" +
s e a t s [ i ] .length +
d o c u m e n t . g e t E l e m e n t B y l d ("seat" + (i
ним
j) ) . s r c = " s e at_select.png";
j )).alt = "Your seat";
j + l) ) . s r c = " s e at_select.png";
j + l) ) . a l t = "Your s e a t ” ;
j + 2 ) ) . src = " s e a t _ s e l e c t . p n g " ;
j + 2 ) ) . alt = "Your seat";
// П о л ь з о в а т е л ю п р е д л а г а е т с я п р и н я т ь п р е д л о ж е н н ы й ва р и а н т
v a r a c c e p t = c o n f i r m ("Sea t s " + (j + 1) + " t h r o u g h " + (j + 3) +
" in R o w " + (i + 1) + " are ava i l a ble. Accept?");
if (accept) {
// К р е с л а з а б р о н и р о в а н ы , п о э т о м у р а б о т а в н е ш н е г о ц и к л а з а к о н ч е н а
f i n i s h e d = true;
break;
}
еІЕ
,олжаем п о и с к
s e l S e a t = -1;
d o c u m e n t .g e t E l e m e n t B y l d ("seat" +
document.getElementByld("seat" +
d o c u m e n t .g e t E l e m e n t B y l d ("seat" +
d o c u m e n t .g e t E l e m e n t B y l d ("seat" +
d o c u m e n t .g e t E l e m e n t B y l d ("seat" +
d o c u m e n t .g e t E l e m e n t B y l d ("seat" +
(І
(І
(І
(І
(i
(І
(І
*
*
*
*
*
*
s e a t s [i]
s e a t s [i]
s e a t s [i]
s e a t s [i]
s e a t s [i]
s e a t s [i]
.l ength
.l ength
.l e n g t h
.l e n g t h
.l e ngth
.l e ngth
+
+
+
+
+
+
j)) .src
j) ) .alt
j + D ) .src
j + 1) ) .alt
j + 2) ) .src
j + 2) ) .alt
// У в е л и ч и в а е м с ч е т ч и к в н е ш н е г о ц и к л а на е д и н и ц у
i++;
далее >
279
помогите с реш ением
еШ ение З а д а ч и
какие '^аШ енгры «^ункДии
GnJ^eatsQ из г^оХ^аММы ]^апс14Ю£о
Мо1^ , Б cBojo оЧе]=>еДь,
служииаь осноБой для
других •функций.
function f i n d S e a t s о
{
// Е с л и м е с т а у ж е выбраны,
if (selSeat >= 0) {
se l S e a t = -1;
in i t S e a t s ();
произведите повторную инициализацию
}
// П о и с к с в о б о д н ы х м е с т с р е д и в с е х в о з м о ж н ы х
va r 1 = 0 ,
f i n i s h e d = false;
w h i l e (i < s e a t s . l e n g t h && Ifinished) {
for (var j = 0; j < s e a t s [ i ] .length; j++) {
// П р о веряем, с в о б о д н о л и в ы д е л е н н о е м е с т о и д в а м е с т а за н им
if (seats[i][j] &s sea t s [ i ] [ j + 1] && seats[i][j + 2]) {
// В ь щ е л я е м к р е с л а и о б н о в л я е м и х вид
s e l S e a t = i * s e a t s [ i ] .l e n g t h + j;
- d o c u m e n t .g e t E l e m e n t B y l d (" s e a t ’'.+ (1 ~ ~ ^ ^ ~ з ё а ^ Т Г 7 Т Ш д Г Т Г Т - 1 Т Г Г з г с ~ ^ ~ ^ ^
^ o c u m e n t . g e t E l e m e n t B y I d (V
" s e a t " -r
+ v
(i
s e a t s [[ Ji.J].l
eu
ng
tn
h -+I- j ) ) . a l t = ”" iYoouu r
seat";
-L * atiduto
. j.e
yc
r s
eat";
—^
d o c u m e n t .g e t E l e m e n t B y l d ("seat " ' ■ T i r ‘‘^‘‘'^^StiTi77TSrgt!rT°l + 77')';sTc
^ o c u m e n t . a e t ^ l e m e n t B v I d ( " s e at" + (i * seats [i 1 .l e n g t h + i + l ) l . a ] t = "Your seat":
d o c u m e n t . g e t E l e m e n t B y I d ( " s e a t " + (i * s’
^ i t i T T T T l e ^ f ^ i t t ' T T ^ 2 ) ) " . src = " seat .select.
^-■^Jtoc.ument.getElementBvId.(.".s.e.at" + (i * seats Til ,l e n g t h + -j + 2 n . a l t = "Your- ___________
// П о л ь з о в а т е л ю п р е д л а г а е т с я п р и н я т ь п р е д л о ж е н н ы й в а р и а н т
v a r a c c e p t = c o n f i r m ( " S e a t s " + (j + 1) + " t h r o u g h " + (j + 3)
in R o w " + (i + 1) + " a r e ava i l able. A c cept?");
if (accept) {
// К р е с л а з а б р о н и р о в а н ы ,
f i n i s h e d = true;
break;
else (
// П о л ь з о в а т е л ь
s e l S e a t = -1;
поэтому работа внешнего цикла закончена
отказался,
продолжаем поиск
^ - T l o c u m e n t .g e t E l e m e n f B y T a
d o c u m e n t .g e t E l e m e n t B y l d (" s e a t " + (i
d o c u m e n t .g e t E l e m e n t B y rai'"seat'"'"‘T
—
П
D o c u m e n t . g e t E l e m e n t B y l d ( " s e a t " + (i
■aocument.g e t E l e m e n t B y l d ("seat" + 7 Г
d o c u m e n t ■g e t E l e m e n t B y l d ("s eat" + (i
}
Так как э т и ш ест ь
ф р а гм е н т о в кода
в ы п о л н я ю т одну
и т у ж е задачу, их
Можно п р е в р а т и т ь
о ф ункцию .
"^■етг^ахгэтгтрнд*
seats [i] .length +
.length 4seats[i .l e n g t h +
seats [i)'"iengETr+
seats[i].length +
j ) ) . a l t = "Ava i l a b l e s e a t ' T ^
-I- i)).gf'e' = "Sei r ^ a V a i i . p n l "
j
1 ) ) .alt = "__________
A v a i l a b l e _______
seat _
j'
^ "seat _ a v a i l . p n g ^
j + 2 ) ) . alt = "Ava i l a b l e seat";
N
// У в е л и ч и в а е м с ч е т ч и к в н е ш н е г о ц и к л а на е д и н и ц у
i++;
280
глава 6
С войст во len g th
о п р е д е ля е т число
э л е м е н т о в влож ен­
ного м ассива.
^ 3 Зублирующ ^егося
кода мож но извлечь
некот оры е а т р и б ут ы :
функции
функция, задаюи^ая места
Т е п е р ь , когда н аш и п р и ятел и -м ач о о с о зн а л и всю п ользу о т у в е л и ч ен и я э ф ­
ф е к т и в н о с т и , о н и х о т я т с о к р а т и т ь код п р о гр а м м ы M a n d a n g o , д обави в в н ее
ф ун кц и и . Н о п р еж д е, ч ем м ы п р и сту п и м к н а п и сан и ю ф у н кц и и s e t S e a t ( ) ,
т р еб у ется п о н ять, как и е аргум ен ты е й нуж ны . Д л я эт о го поиш;ем в дублирую ­
щ ем ся ко д е т е ф р а гм е н т ы и н ф о р м а ц и и , к о т о р ы е о т л и ч аю тс я друг о т друга.
В от к ак и е аргум ен ты будуш;ей ф у н кц и и f i n d S e a t s () мы обнаруж им :
Номер места
в д ан н о м случае эт о н е и н декс
м ассива, а н о м е р , к о т о р ы й бы л
бы п р и с в о е н месту п р и сч ете
- сл ева н а п р а в о и сверху в н и з, н а­
Чувак, нам нужно
больше функций!
ч и н а я с 0.
Знаю,
но я тебе перезвоню...
У меня звонок на другой
линии.
Статуе
А т р и б у т ы ф ункц и и
fin d S ea tsO г\олучены
исследованием д у б л и ­
рую щ его с я кода.
М есто м о ж ет б ы ть свободны м ,
за н я т ы м и л и в ы б р ан н ы м . О т
эт о го зав и си т, каки м и зо б р а ­
ж е н и е м о н о будет п р ед став ­
л ен о .
Описание
С татус м ест м о ж е т и м е т ь о д н о и з
т р е х о п и с ан и й «Available seat»,
« U navailable seat« и «Y our seat». О н номеш,ается в атр и б у т a l t и зо б р аж е н и и .
Возьми в руку карандаш
Напишите функцию s e t S e a t () для программы Mandango.
далее *
281
повт орное использование кода в m andango
Возьми в руку карандаш_ _ _ _
'ешение
Вот как выглядит функция s e t S e a t {) в программе Mandango.
Три а р гу м е н т а перечислены
'ч е р е з за п я т у ю .
И ндивидуальны е
данные из исходно­
го кода з а м е н е ны обобщ енны ми
лргум & нщ ам и.
v
v
statusJ descrip tio n ) {
<^^Cj^_^^_>^i.g_etElementByld('’seat'' + sea tN u m ).src ~ " s e a tj + s ta tu s + ".png";
d o c u m e n t.g e tE le m en tB yld C 'sea t" +- se a tN u m ).a (t = d escription;
......................... ...................................................................... z
z
..........................
Редактируем код Mandango
П р е в р а щ е н и е дублирую щ егося ко д а в ф у н кц и ю s e t S e a t {) зн ач и тел ьн о у п р о сти л о код ф у н кц и и f i n d S e a t s ( ) .
function findSeatsO
п е р ед а ю т с я 6 качест ве
а р гу м е н т о в п р и каждом
вызове ф ункции setSeatQ .
{
// Поиск свободных мест среди всех возможных
var 1 = 0 , finished = false;
while (i < seats.length s& Ifinished) {
for (var j = 0; j < seats[i].length; j++) {
// Проверяем, свободно ли выделенное место и два места за ним
if (seats[i][jl &S seats[i][j + 1] ss seats[i][j + 2]) {
// Выделяем кресла и обновляем их вид
selSeat = i * seats[i].length + j;
'
f s e ts e a td * seats [il.len g th + j , "select", ™
>'
* seats [i] .length + j + 1, "select". Your seat ,
T s e ts e a td * seats [il.len g th + j + 2, "select" ,^ ^ Y o u rje a tJ^
J se tS e a td
/ / п о л ь з о в а т е л ю п р е д л а г а е т с я п р и н я т ь предл о ж е нн ы й в а р и а н т
v a r a c c e p t = c o n f i r m ( " S e a t s " + (j + 1) + " t h r o u g h
+ (3 + 3)
" i n Row " + ( i + 1) + " a r e a v a i l a b l e . A c c e p t ? " ) ;
Новая ф ункц и я
se tS e a tQ вы зы ва­
е т с я ш ест ь раз.
^ ^ //^ К р е с л а забронированы,
+
поэтому р а б о т а внешнего цикла за к о н ч е н а
fin ish e d = tru e;
break;
}
else {
// Пользователь отказался, продолжаем поиск
S s S e a t ( i * seats [il.len g th + j, "avail", "Available seat");
( setSeat(i * seats [il.len g th + j + 1, "avail", Ava^.lable seat ,
L se tS e a t(i * seats[i] .length + j + 2, "avail". Available seat ),
1
)
)
// Увеличиваем счетчик внешнего цикла на единицу
І++;
282
глава 6
функции
Усовершенствование Mandango
Ф ункция s e t S e a t () вы го д н а н е т о л ь к о с т о ч к и зр е н и я со к р ащ ен и я
кода ф у н кц и и f i n d S e a t s ( ) . У в е л и ч и в а е тс я такж е э ф ф е к т и в н о с т ь
ф у н кц и и i n i t S e a t s ( ) , в к о т о р о й п р и сутствует п о х о ж и й код.
function initSeatsо {
// задаем вид всех кресел
for (var i = 0; i < seats.length; i++)
for (var j = 0; j < seats[ll-length,
if (seats[i][jl) (
// Задаем свободные места
docvment.getElementById("seat" ^ (i
document. getElementBy Id ("seat" H (i
seats[i].length + j))-src
seats[i].length + j))-alt
"seat_avaxl.png
"Available seat
кода
)
else {
// Задаем занятые места
document. getElementByld ("seat" ■ (i
(i
document.getElementByld (' seat
}
)
fu n ctio n i n i t S e a t s о {
/ / З а д аем вид в с е х к р е с е л
f o r ( v a r i = 0; i < s e a t s . l e n g t h ; i+ + )
f o r ( v a r j = 0; j < s e a t s [ i ] . l e n g t h ;
if (se ats[il[j]) {
/ / Задаем свободные м еста
setSeat(i * seats[i].length + j
Если обобщ ит ь пр о ц едур у
задания вида кр есла , ф ункция
setS eд tO хорош о р а б о т а е т
и в э т о м случае.
e lse {
/ / Задаем заняты е места
setSeat(i * seats[i].length + j
seat");
'Available seat");
"unavail", "Unavailable
}
И та к , в с ц е н а р и и п р о гр а м м ы M a n d a n g o т е п е р ь восем ь р а з в ы зы в ае тся н е­
сл о ж н ая ф у н кц и я, со с то я щ а я и з п а р ы с т р о к кода. Э то н е т о л ь к о у п р о щ ае т код
сц е н а р и я , н о и о б л е гч а ет его р е д а к ти р о в а н и е . В едь для и зм е н е н и я сп особ а
зад ан и я м ест д о ст а т о ч н о в н е с т и и с п р ав л е н и я в ф ункц ию s e t S e a t ( ) . Э то
нам н о го уд обн ей р е д а к т и р о в а н и я в о сьм и р а зб р о с а н н ы х по всем у сц ен ар и ю
ф р а гм е н т о в кода.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
■
Функции позволяют разбить большую задачу на
ряд более мелких и более простых для решения.
■
функции предоставляют механизм разделения задач
и превращения их в код многократного использо­
вания.
Функции позволяют избавиться от дублирующе­
гося кода, ведь их можно вызывать произвольное
количество раз.
Передача данных функциям осуществляется при
помощи аргументов.
далее >
283
не бойся спросить
_
Часщо
^аД аБаеМ ы е
- Э
Ограничено ли количество
передаваемых функции аргументов?
Б
о
Ц ^ э о С Ь !
) • Мы узнали, что функции
позволяют делить крупные задачи
на более мелкие, разделяют
процесс написания сценария
и устраняют дублирующийся код.
Они действительно настолько
универсальны?
0 ; И да, и нет. Если не брать в расчет
ограниченность памяти компьютера, то
формальных ограничений на количество
передаваемых аргументов нет. Впрочем,
если вы передали функции столько
аргументов, что возникли проблемы
с оперативной памятью, вам явно нужно
сделать паузу и подумать над своими
действиями. С практической точки зрения
количество аргументов желательно
выбирать таким образом, чтобы вызов
функции не превратился в несуразно
сложную задачу.
! Да, действительно. Часто функция
помогает решить несколько проблем
одновременно. Впрочем, если попытаться
указать главное достоинство функций,
наверное, это будет разделение процесса
написания сценария на фрагменты.
Напомните, где именно должны
появляться функции, в заголовке или
в теле веб-страницы?
0 1 Функции могут располагаться, как
внугри тега < s c r i p t > в заголовке
страницы, так и во внешнем файле,
импортированном в заголовок.
Как сделать, чтобы функция
меняла значения аргументов?
О
; Напрямую изменить аргументы
функции нельзя, точнее говоря, эти
изменения никак не отразятся на
сценарии за пределами функции. Так
что для изменения фрагмента данных,
который передается в качестве аргумента,
нужно получить от функции измененное
значение. О том, как это сделать, вы
узнаете чуть позже!
С термостатом что-то
не так. Я замерзаю!
Зима 8 июле
с пом ощ ью ф у н к ц и й м ы улучш или програм м у M a n d a n g o , а в о т в об­
л а с ти к л и м ат-ко н тр о л я так и м и резу л ьтатам и п о х вастаться п о к а н е
п олучается. К аж ется, т е р м о с т а т все р а в н о р а б о т а е т н е к о р р е к т н о .
Т о л ьк о п о с м о т р и т е н а д р о ж ащ его п о л ьзо в а т ел я, скучаю щ его п о н е­
п р е р ы в н о м у н агреву п осл е н аж ати я к н о п к и H eat.
284
глава 6
функции
Обратная связь
Б л а го д а р я ф у н кц и и наш т е р м о с т а т п о зв о л я е т зад ать нужную тем п ературу,
но о н н е сообш ,ает о то м , н аск о льк о т е п л о в пом еш ,ении в д ан н ы й м ом ент.
А эт о о ч е н ь в аж н ы й п а р а м е т р , т а к как и м е н н о о н я в л я е т с я о с н о в о й для
д о с т и ж е н и я ж ел аем о й тем п ер ату р ы . К р о м е т о го , в о д н и х и т е х ж е усло­
в и я х р а зн ы е т е р м о с т а т ы м огут и м еть р а зн ы е п о к азан и я . С о о т в етст в ен н о ,
для к о р р е к т н о й р а б о т ы си стем ы нам нуж на о б р ат н а я связь.
О кно « т е/Л і^ер лт ур а
° м н ш й м ом е««»
инф орм ации} о т о м . на
“ а“ »
в л я т ь нагрей.
В к ач е с тв е о б р а т н о й св я зи т е р м о с т а т т е п е р ь п е р и о д и ч е с к и п о ­
ка зы в а е т тем п ер ату р у Б п о м е щ е н и и в д ан н ы й м ом ент.
Возвращ енное
Ж елаем ая
зн а ч ен и е теку-
температура
Температура
^
щей температуры
в данны й мо­
ф ункция д е Ш т р О п о зв о ­
ляет определит ь т е к у ­
щ ую т ем перат уру-
мент^
д е Ъ Т е т р ()
Функция возвращ ает
значение т ем перат уры
о данный м ом ент .
И так , нуж но, ч то б ы ф у н кц и я в о зв р ащ ал а и н ф о р м а ц и ю
вы звавш ем у ее коду.
ГШ ТУРМ
Каким образом можно получить данные от функции?
далее >
285
ответ на за п р о с
Возврат данных
Ч т о б ы за с т ав и ть ф ункц ию вер н у ть д ан н ы е, и сп ользуется клю ­
ч ев о е сл ово r e t u r n . П о сл е н его у казы вается, к ак и е и м е н н о
д ан н ы е вы х о т и т е получить.
Оператор return позволяет
получить данные от функции.
re tu rn
К лю чевое слово r e tu r n у к а в п .й Т
ф ункц и я
во звр а щ а ет з н а ч е н и !
К акое им енно значение
б уд ет возвращ ено, за ви с и т
о т ваш его выбора.
П о л о ж е н и е к л ю чево го сл о в а r e t u r n в т е л е ф у н кц и и т е о р е т и ч е с к и
м о ж ет б ы ть лю бы м ; но следует уч и ты в ать, ч то п о сл е в ы п о л н е н и я
это го о п е р а т о р а ф у н кц и я п р е к р а щ а е т свою работу. Д ругим и слова­
м и, д ан н ы й о п е р а т о р н е т о л ь к о в о зв р а щ ае т д ан н ы е, н о и п р е р ы в а е т
р або ту ф ун кц и и . Н а п р и м е р , ф у н кц и я g e tT e m p () за в е р ш ает с я после
в о зв р а щ ен и я п р о ч и т а н н о й с д и сп л ея текущ ей тем п ер ату р ы ,
function getTen^) () {
// Считывание и преобразование текущей температуры
var rawTemp = readSensor() ;
var actualTeir^j = convertTen^ (rawTenp) ;
return actualTea^;
V
}
благодаря о п е р а т о р у
r e tu r n ф ункция во зВ р а -^
щ а е т значение т е к ущ е й
т ем перат уры .
На дисплее д а н ­
ные от ображ аю т ся
V
ф ор­
м а т е , ц их т р е д у преоб р а зо ва т ь
о градусы.
Если п о м н и те, ф у н кц и я g e tT e m p () уже и сп о л ьзо вал ась в сц е н а­
р и и р а б о т ы н аш его тер м о стата:
function heat(targetTemp)
{
while (getTen^sO < targetTemp)
// Начинаем нагрев'
{
функция y e tT e m p Q
предост авляет зн а ­
чение, и сп о ль зуем о е
. п р и п р о вер ке условия
работ ы ц и кла w hite
в ф ун кц и и heatQ .
}
}
З н а ч е н и е , в о зв р ащ аем о е ф у н к ц и ей g e tT e m p ( ) , п о я в л я е т с я в м е с т о
в ы зо в а э т о й ф у н кц и и и с т ан о в и т с я ч астью п р о в е р к и усл ови я в ц и к л е
w h ile .
286
глава 6
Возвращаемое значение
появляется на месте
вызова функции,
функции
возвращаемые значения
Т ак как о п е р а т о р r e t u r n п р и в о д и т к за в е р ш е н и ю ф у н кц и и , его м ож ­
но и с п о л ьзо в ат ь для у п р ав л ен и я п р о ц ессо м р аб о ты . В общ ем случае
резул ьтато м п р и м е н е н и я ф у н кц и и с ч и та е т с я и м е н н о в о зв р ащ ен н о е
е й зн а ч е н и е . Р ассм о тр и м ф ункц ию h e a t ( ) :
function heat(targetTen^)
if (getTempO >
П о м ни т е п е р е м е н н у ю
a c tu a lT em p ? И м енно благо даря ей ф ункций g etT e m p O
во звр а щ а ет значение.
{
targetTemp)"^
Е сли на гр ев не т р е б у е т СЯ,, во звращ аем значение false
и за ве р ш а е м р а б о т у ф ун кц ми.
return false;
while (getTen^O < targetTen^)
Э т о т код вы п о л н яет нагрев,
влияя, т е м с а м ы м , на т е м п е р а >муру и на значение, возвращ аем ое
ф ун кц и ей g e tT e m p ().
// Осуществляется нагрев
_ Нагрев за вер ш ен , п о э т о м у
во звр а щ а ет ся значение tru e.
}
Т о есть п р и по м о щ и в о зв р ащ аем о го л о ги ч ес к о го зн а ч е н и я м о ж н о уп рав­
л я т ь р а б о т о й ф у н кц и и и указы вать как н а успеш ное за в ер ш е н и е н ек и х
о п е р а ц и й , так и н а неудачу. Д л я вы х о д а и з ф у н кц и и о б ы ч н о и сп ользуется
о п е р а т о р r e t u r n , п р и это м н и к а к и х зн а ч е н и й н е в о звр ащ ается . П о см о ­
т р и т е н а ещ е одну вер си ю ф у н кц и и h e a t ( ) , р а б о т а к о т о р о й п р е р ы в а е т с я
о п е р а т о р о м r e t u r n , если н а гр е в н е тр ебу ется.
function heat(targetTemp)
{
О п е р а т о р r e tu r n за ве р ш а ет
р а б о т у ф ункции на э т о м э т а п е ,
т а к как на гр ев в э т о м случ ае не
т р еб ует ся .
if (getTempO >= targetTemp)
return;
----- '
while (getTen^O < targetTemp)
{
// Осуществляется нагрев
ф ункция за ве р ш а е т
р а б о т у без п о м о щ и
о п е р а т о р а re tu rn .
Оператор return может
использоваться для за­
вершения работы
функции.
далее *■
287
оператор return о себе
^ ^ О Т Т Ё Р А Т О Р
/Т
О' С Ё Б Б
Интервью недели:
С екреты м а с те р а преры вания ф у н кц и й
Head First: Я слы ш ал, ч то вы сп о со б н ы н а й ти вы ­
ход и з л ю б о й ситуации.
л и ч и и эт о го зн а ч ен и я . Если ф ун кц и я н и ч е г о не
в о звр ащ ает, т о и за б о ти ть ся н е о чем.
Return: И м е н н о так. П о м е с ти те м е н я в те л о
л ю б о й ф у н кц и и , и я н ем ед л ен н о оттуда выйду.
И заб ер у с с о б о й дан н ы е.
Head First: П о н я т н о . Т огда д ав ай те п о го в о р и м
о ваш и х с п о со б н о стях . З ач ем вооб щ е нуж но п р е ­
р ы в а ть ф ункц ии? П оч ем у н е д ать им завер ш аться
ес теств ен н ы м путем?
Head First: И куда вы п о сл е эт о го н ап р ави тесь?
Return: Н е за б ы в ай те, ч т о ф у н кц и я в ы зы в а е т ­
ся каким -то кодом . Т ак ч т о вы ход и з ф у н кц и и
о зн а ч а е т п р о с т о в о зв р а щ ен и е в э т о т код. Т ам ж е
о к азы в аю тся и в о зв р а щ ен н ы е ф у н к ц и ей дан н ы е.
Head First: И как ж е эт о все рабо тает?
Return: П р ед став ьте, ч т о в ы зо в ф у н к ц и и —эт о
в ы р а ж е н и е , и м ею щ ее н е к и й р езультат. Если
ф у н кц и я не в о зв р а щ ае т д ан н ы х , р езу л ь тат о к азы ­
в ается нулевы м.
Head First: Если ф ункц ию м о ж н о п р е д с та в и ть
в ви д е в ы р а ж е н и я , зн а ч и т, м о ж н о н а зн а ч и т ь
в о зв р а щ ен н о е ей зн а ч е н и е какой-нибудь п е р е м е н ­
н ой . Я прав?
Return: И н ет, и да. В ы р аж ен и ем я в л я е т с я не
сам а по себе ф у н кц и я, а е е вы зов. И и м е н н о вы ­
зо в ф у н кц и и м о ж н о п о м е с т и т ь в код та к и м о б р а­
зом , ч т о в о зв р а щ ен н о е зн а ч е н и е будет н а зн ач ен о
п ер е м е н н о й .
Head First: А ч т о п р о и с х о д и т с в ы р а ж е н и е м , если
ф у н кц и я н е в о зв р а щ ае т зн ач ен и я?
Return: Если для вы х о д а и з ф у н кц и и исп ользую сь
я, о н а н е в о зв р а щ ае т д ан ны х, и в ы р а ж е н и е не
и м е е т н и како го зн ач ен и я .
Head First: А эт о н е п р и в о д и т к проблем ам ?
Return: Н ет. З а б о ти ть с я о то м , ч то д ел ать с во з­
вращ аем ы м зн а ч е н и е м , следует т о л ь к о п р и н а­
288
глава 6
Return: Т о т ф акт, ч т о в т е л е ф у н кц и и и м еется
н а б о р с т р о к кода, н е о зн ач ае т, ч то все о н и д олж ­
н ы б ы ть вы п о л н ен ы . О ф у н кц и ях в п р и н ц и п е
н е и м е е т см ы сла думать как о чем-то, им ею щ ем
н ач ал о и кон ец . «Е стественны й » к о н ец м о ж ет
расп о л ага тьс я в с е р ед и н е п о м ещ ен н о го в ее тел о
кода. В от тут-то н а п ом ощ ь п р и хож у я.
Head First: Т о есть вы у тверж даете, ч т о н о р м ал ь­
н о и м еть в т ел е ф ун кц и и код, к о т о р ы й , м о ж ет
б ы ть, н и к о гд а н е будет запущ ен?
Return: Я б ы сказал, ч то сущ ествует б о л ее од н о­
го сп о с о б а созд ать т е л о ф у н кц и и , и и м е н н о это
я пом огаю сделать. Если п р о и с х о д и т н еч то ,
указы ваю щ ее н а н е в о зм о ж н о с ть п р о д о л ж ен и я
р аб о т ы ф у н кц и и , я н ем ед л ен н о е е заверш аю . В то
ж е сам ое в р е м я д о ст а т о ч н о случаев, когд а тело
ф у н кц и и в ы п о л н я ет с я о т п е р в о й до п о сл ед н ей
с т р о ч к и , и я там п о я вл я ю сь в лучш ем случае, ч то ­
бы верн уть дан н ы е.
Head First: Д ругим и сл овам и, вы п о зв о л я е т е как
во зв р ащ ат ь дан н ы е, т ак и у п р авл я ть в ы п о л н е н и ­
ем ф ункций?
Return: Д а, и м е н н о так!
Head First: П о тр ясаю щ е. С паси бо, ч т о согл аси ­
л и сь с н ам и поб еседовать.
Return: Всегда пож алуй ста. А т е п е р ь м н е нуж но
о тсю д а вы йти!
функции
пражнение
Кажется, иауаЗспр! попал в эпицентр скандала вокруг климатических изменений.
Люди, выступающие за прохладную атмосферу, создали сценарий, распространяю­
щий воззвание против потепления. Но их оппоненты, уставшие от холодов, внесли
в код свою лепту, и сообщение перестало появляться. Вам нужно вернуть сценарию
первоначальный вид и узнать, что же хотели сказать противники нагрева.
function
showClimateMsgO
{
return;
a l e r t ( c o n s t r u c t M e s s a g e ());
}
function
constructClimateMsgO
{
var msg =
msg +=
"Глобальное
//
"Локальное
if (getTempO > 80)
msg += " п о т е п л е н и е ";
else
msg += "похолодание ";
if (true)
msg += "не
else
msg += "это ";
if (getTempO <= "/0)
return msg + "обман!";
else
return msg + "правда!";
return "Я в это не верю.";
function g e t T e m p O
{
// О п р е д е л я е т т е к у щ у ю
температуру
var actualTemp = readSensorO;
return 64;
далее >
289
решение упражнения
ажнение
)'"ешение
Вот какие исправления внесли в код сторонники локального нагрева, чтобы
не дать появиться сообщению от группы, выступающей против потепления.
О перат ор retu rn не
дает появит ься всплы ­
ваю щ ем у окну.
function
showClimateMsgO
{
a l e r t ( c o n s t r u c t M e s s a g e О );
}
function
С э т и м кодом все
'^‘^Рядке, т а к как
^появляющееся сооб­
щ ение б удет з а в и ­
сет ь от т екущ ей
^т ем перат уры .
И з-за о п ер а т о ­
ра if-else эт а
ст рочка никогда _
не будет вы пол­
няться, п о э т о ­
м у писат ь ее не
и м еет смысла.
Спасибо,
Java5cripti^
constructClimateMsgO
{
var msg =
nisg += -1ЧЗяв&ада«®«-^; // "Локальное
\.
^
if
(getTemp 0
>
80)
msg += "потепление ";
else
msg += "похолодание
Подобное условие
не им еет смысла.
if (getTempO <= 70)
return msg + "обман!";
else
return msg + "правда!";
function getTempO
/ /
О п р е д е л я е т
{
текущ ую
т е м п е р а т у р у
var actualTemp = readSensor ();
return 44^ actualTemp; ^ _____ _
Локальное потепление —
это правда!
290
глава 6
Исходный
т е к с т был
п р евр а щ ен
в ком м ент а р и й , а вм е с т о
него вписан
другой в а р и ­
ант .
функции
информация о статусе места
С ета и Д ж е й с о н а уж е т о ш н и т о т р а зг о в о р о в об окруж аю щ ей т е м п е ­
р ату р е, п оэтом у в е р н е м с я к п р о гр ам м е M an d a n g o . Ч а с т ь п о л ь зо в ат е­
л е й ж алуется, ч то по цвету к а р т и н к и с л о ж н о о п р е д е л и т ь с о с т о я н и е
м еста. П о это м у им х о т е л о с ь б ы и м еть в о зм о ж н о сть п олучать данную
и н ф о р м а ц и ю , н а п р и м е р , по щ елчку. С ловом , п р о гр ам м е наш их
м ач о тр еб у ется ещ е о д н а ф ункц ия.
М ест а п р о н ум ер о ва н ы
слева н а п р а во , сверху
вниз, начиная с О.
Как можно
думать о температуре,
когда надо работать над
Mandango!
«Г а
Возвращен
Запрос
статуса
^ статус места
Статус
места
getSeatStatus(seatWum);
С т ат ус м е с т а —
эт о ст р о ка
вида "available",
"unavailable" или
"yours".
__
Функция getSeatStatus ()
Функции g e t S e a t S t a t u s () не хватает кода, позволяющего определить статус выделенного
места. Функция сначала проверяет, относится ли указанное место к набору из трех, выбранных
пользователем. В случае отрицательного результата проверяется, свободно это место или занято.
Расставьте магниты, чтобы получить недостающие фрагменты.
М
g e tS e a tS ta tu s ( s e a tN u m )
f u n c t i o n
i f
........... i =
(
-1
____________
{
“
+ 1)11
( .................r e t u r n
..................N .................. -
‘
" y o u r s " ;
[ 0 ] . l e n g t h ] )
[ 0 ] . l e n g t h ) ] [
e l s e
i f
r e t u r n
{ .................. [ M a t h , f l o o r
( .............................../
" a v a i l a b l e " ;
e l s e
return
"unavailable";
}
далее >
291
решение задачи с магнитами
Решение задачи с магнитами
Вот как стал выглядеть код функции g e t S e a t S t a t u s I
-...ли м е с т о уже вы б р а ­
но, глобальная п ер ем ен н а я
se lS e a t и м е е т значение —1 .
Чт обы о п р е д е л и т ь н о м ер ряда,
р а з с е л и м н о м ер м е с м й на число
м е с т в ряду и о к р у гл и м р е з у л ь ­
т а т до целого.
после подстановки магнитов.
Т ак как м е с т а вы б ираю т ся по т р и ,
м ы п р о вер я е м не т о ль к о выбранное
м е с т о , но и два след ую щ и х за ним .
Ч т обы у з н а т ь вт о р о й индекс
м а сси ва , п о д ели т е ном ер
к р есла на ко ли ч ест во м е с т
в ряду.
Здесь мож но было п о ­
с т а в и т ь ц и ф р у <?, но
если в б удущ ем вы р е ­
ш и т е п о м е н я т ь число
м е с т в р яд у, п р о гр а м м а
перест анет коррект но
р(^оот ат ь.
Отобра}кение статуса
Н уж но, ч то б ы п о щ елчку п о л ь зо в а т е л я н а и зо б р а ж е н и и к р е сл а п о я в л я л ась
и н ф о р м а ц и я о статусе эт о го кр есл а. Д л я эт о го нам п о тр еб у ется ф ун кц и я
s h o w S e a t S t a t u s ( ) . В п р о ч ем , вся о с н о в н а я р а б о т а будет в ы п о л н е н а т о л ь ­
ко ч т о н а п и с а н н о й ф у н к ц и ей g e t S e a t S t a t u s ( ) .
function showSeatStatus(seatNum)
{
alert("This seat is " + getSeatStatus(seatNum) + ".");
}
292
глава 6
Чт обы у зн а т ь
ст ат ус м ест а,
п е р ед а й т е его
н о м е р ф ункции
g e tS e a tS ta tu sQ .
Сообщение 0 сост оянии
м ест а ф о р м и р ует ­
ся п чут
т еМ
СЯ
ем соединения
ст рок.
функции
связь функции с изобра)кением
С вязав новую ф у н кц и ю с и зо б р а ж е н и я м и м ест н а веб -стр ан и ц е M an d a n g o ,
вы д ад и те п о л ьзо в ател ям в о зм о ж н о сть п олучать и н ф о р м а ц и ю о состоян ии^____В данном случ ае ф ункция
м ест, щ елкнув н а и зо б р а ж е н и и в ы б р ан н о го кресла. С о б ы ти е o n c l i c k к а з ^
^ o w 5 e a tS ta tu s() Вызвана
д ого и з и зо б р а ж е н и й д о лж н о в ы зы в а ть ф ункц ию s h o w S e a t S t a t u s ( ) : /
‘изображении
<img id="seat23" src="" alt="" onclick="showSeatStatus(23);" />
oee ■
О "
. . . . .
Т аки м о б р азо м , п о сл е щ ел ч ка н а и зо б р а ж е н и и к р е сл а п о я в л я е тс я о кн о
д и ал о га с и н ф о р м а ц и е й о статусе это го кресла. Д а н н ы й в а р и а н т п од ход и т
для п о л ь зо в а т е л е й , к о т о р ы е н е х о т я т о р и е н т и р о в а т ь с я п о ц ветам и зо б р а ­
ж е н и й , п р е д п о ч и т а я п р о ч и т а ть , за н я т о м есто и л и свободно.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
^
■
Оператор r e t u r n заставляет функцию вернуть
данные в вызвавший ее код.
Функция может вернуть только один фрагмент
данных.
■
Возвращенные данные подставляются вместо кода,
вызвавшего функцию.
Оператор r e t u r n используется также для преры­
вания работы функций.
далее *
293
структурное улучшение кода
Дублирующийся код
С ц е н а р и й M a n d a n g o р а б о т а е т в п о л н е к о р р е к т н о , н о п ар н и
стал и задум ы ваться о д о л го с р о ч н ы х п е р с п е к ти в ах . В ч аст­
н о с т и , Д ж е й с о н н ач ал и ссл ед о в ан и е и о б н аруж и л , ч то
в с о в р е м е н н ы х в е б -п р и л о ж ен и я х в ы го д н о р а зд ел я т ь код
H T M L , Jav aS crip t и CSS.
<html>
^^Jtitle>Mandango - The Macho Movie Ticket Finder</title>
<script type=”text/javascript">
function initSeats0
{
}
function getSeatStatus(seatNum)
{
)
function showSeatStatus (seatNum) (
alertC'This seat is " + getSeatStatus (seatNum) +
^
- );
}
function setSeat (seatNum, status, description) {
status + ".png";
document.getElementById("seaf + seatNum). src d o c u m e n t . getElementByldC’seat" + seatNum).alt - descrapti
function findSeatsO
С м есь J a v a S c r ip t и H T M L
м о ж е т б ы т ь и зо л и р о в а ­
на б о б р а б о т ч и ка х с о б ы H T M L -а т р и б у т о в .
{
J ^ d y onload*"initSeats() ;">
<div style-'matgin-top:25px; text-align;center >
<img
<img
<img
<img
<img
<img
<img
<img
<img
<lmq
<i„g
На ве б ­
ст р а н и ц е
M andango
перемеш аны
меж ду собой
J a v a S c r ip t
и HTML.
.ЛШ _ 111
4
.. ..
_I alt
.howSea
id="seatO"
src=""
onclic)c="showSeatStatus (1); "
id="seatl" src="" alt="
o n c l i c k . = " showSeatStatus (2);"
id="seat2" src=”" alt="
onclick="showSeatStatus(3);"
id="seat3" src-"" alt="
o n c l i c k = " s h o w S e a t S t a t u s (4);
id="seat4" src="" alt="
onclick="showSeatStatus(5);
id="seat5" src="" alt="
o n c l i c k = " s h o w S e a t S t a t u s (6);
id="seat6" src="" alt="
o n c l i c k = " s h o w S e a t S t a t u s (7);
id="seat7" src="" alt="
ol
n
i'
c
t S t a t u s (8);
O
H.ciJl.J.
-lk'-= " s h o w S e a—--id="seat8" src="" alt
id-"seat9" stc-"" a l t - - onolick="sbo«SeatStatus (9);
id-"seatlO” stc--' a l t - - onclick-showSeatStatus 10
d-"seatll" src-”" alt-"" onclick."sbo»SeatStatus 11
o n c l i c k = " s h o w S e a t S t a t u s ( 0 ) />
<img
alt=""
<img id="seatl2
alt=""
<img id*"seatl3' ' src="
alt=""
<img id="seatl4 ' src="
al t = " "
<img id="seatl5" src="'
<img id="seatl6" src=’" alt»"'
<img id="seatl7” src=‘" alt="
<img id="seatl8" src="' alt="
<img id="seatl9" src='" alt»"
<img id="seat20" src=" ' alt=”
<img id="seat21" src=" ' alt="
<img id="seat22" src=" ' alt="
<img id="seat23" src=" ■ alt="
<img id="seat24" src=" ' alt="
<img id="seat25" src=" • alt=""
<img id="seat26" src=" ■ alt=’’"
ait=""
<img id="seat27" src="
<img id="seat28" src="
<img id=”seat29" src=" ■' alt=""
<img id="seat30" src=" " alt=""
<img id="seat31" src=" " alt=""
/>
/>
/>
/>
/>
/>
/>
/xbr />
/>
1 />
, />
/>
o n c l i c k = " s h o w S e a t S t a t u s (12),
/>
o n c l i c k - " s h o w S e a t S t a t u s (13);
/>
onclick="showSeatStatus(14);
/>
o n c l i c k = " s h o w S e a t S t a t u s (15);
o n c l i c k = " s h o w S e a t S t a t u s (16)
/>
o n c l i c k = " s h o w S e a t S t a t u s (17);"
o n c l i c k = ” s h o w S e a t S t a t u s (18); ’'
o n c l i c k = " s h o w S e a t S t a t u s (19);' '
o n c l i c k = " s h o w S e a t S t a t u s (20);' ’
/ X b r />
/>
/>
/>
■/>
o n c l i c k = " s h o w S e a t S t a t u s (21); ’
o n c l i c k = " s h o w S e a t S t a t u s (22);' ’ />
o n c l i c k - " s h o w S e a t S t a t u s (23);' ' />
o n c l i c k = " s h o w S e a t S t a t u s ( 2 4 ) ; ’ />
o n c l i c k = " s h o w S e a t S t a t u s (25); " />
o n c l i c k = " s h o w S e a t S t a t u s (26); " / X b r
o n c l i c k = " s h o w S e a t S t a t u s ( 2 7 ) ; '• />
/>
" />
o n c l i c k * " s h o w S e a t S t a t u s (30); " />
o n c l i c k = " s h o w S e a t S t a t u s (31); " />
o n c l i c k = " s h o w S e a t S t a t u s ( 3 2 ) ; " />
o n c l i c k = " s h o w S e a t S t a t u s (33); " />
o n c l i c k = " s h o w S e a t S t a t u s (34); " />
o n c l i c k = " s h o w S e a t S t a t u s (28);
on c l ick='’s h c w S e a t S t a t u s (29) ; " />
ait=""
<img id="seat32'" src="
<img id="seat33" src=’^^"^ alt=""
<img id="seat34" src="" alt^
/--x b r -/>
o n c l i c k = " s h oi
wws
Se
eaa
ti
aitw
u-»
s (\3 5 ) ;
i-toSuc
<img id="seat35" src="" alt
'Find Seats" onclick="findSeats0 ; "
<input type="button" id="findseats value»
294
глава 6
/>
функции
Отделите функциональность о т содер)кимого
Ч ем ж е т а к п л о х с м еш ан н ы й код? В к о н ц е к о н ц о в , о н ведь р аб о т а ет . П р о б л ем ы н а ч и н а ю т
в ы р и с о в ы в а т ь с я п р и п о п ы тк е п о с м о т р е т ь н а веб-стран и ц ы с Jav aS crip t н е как н а ст р а­
н и ц ы , а как н а приложения. Д л я д о л го в р е м е н н о й р а б о т ы л ю б о го п р и л о ж е н и я важ н ы
акк у р атн о е п л а н и р о в а н и е и структура. Р азд ели в в н е ш н и й вид, со д ер ж и м о е и ф ун кц и о­
н а л ьн о с ть с т р ан и ц ы , вы и зб е ж и те м н о ж ес т в а о ш и б о к и п ол уч и те б о л ее уд обны й для
р е д а к т и р о в а н и я код. П р о в е р и м сп р а в е д л и в о с ть эт о го у тв ер ж д ен и я н а п р и м е р е п р о гр а м ­
мы M an d an g o .
Соде|»кимое
H T M L -код о п р е д е л я е т структуру д ан н ы х н а с т р ан и ц е и
н ап о л н е н и е
Р азделяя содерж имое
ст р а н и ц ы , ее внеш ний вид
и ф у н к ц и о н а л ь н о ст ь , м ы
п р е в р а щ а е м б ольш ую за дачу в набор более м елки х.
<style>
Внешний Bug
</style>
С88-код зад ает в н еш н и й вид
с т р ан и ц ы , н а п р и м е р ш р и ф ­
ты , ц в е т а и даж е ком п он овку
дан ны х.
J
<script>
</script>
функциональность
JavaS cript-кoд д ел ает стр ан и ц у
и н т е р а к т и в н о й . И м е н н о эта
ч асть о т в е ч а е т за выполнение
различных задач.
П одум ай те, как р е а л и зо в а т ь р а зд е л е н и е кода. П р ед стави м ,
ч то С ет и Д ж е й с о н н аш л и уд ачны й а л го р и т м п о и с к а м ест,
к о т о р ы й о н и п р е д п о ч л и бы и с п о л ь зо в ат ь в м есто с т ар о й
в е р си и . З н а ч и т , тр еб у ется о т р е д а к т и р о в а т ь п р и л о ж е н и е
M a n d a n g o , но, т а к к ак код Jav aS crip t п е р е п л е т е н с кодом
H T M L , в п р о ц е сс е и с п р а в л е н и й м о ж н о п о в р е д и т ь структу­
ру ст р ан и ц ы . Н а ск о л ьк о уд обн ее б ы ло бы , если бы H T M L код бы л и зо л и р о в а н и его с в я зь с Jav aS crip t осущ ествлялась
бы и с к л ю ч и те л ьн о ср ед ств ам и по сл ед н его .
Отделение функционально­
сти от содержимого облегча­
ет последующее редактиро­
вание веб-нриложений.
Ш ТУРМ
Каким образом функции могут помочь нам отделить со­
держимое от функциональности в случае Mandango?
далее >
295
данные = функции
Функции — это то)ке данные
Д л я э ф ф е к т и в н о г о р а зд ел е н и я ко д а нуж но п о н я т ь , каким о б р а ­
зо м ф у н кц и и с в я зан ы с со б ы ти ям и ; п о к а ч то м ы осущ ествляли
эту св язь п р и п о м о щ и Н Т М Ь -атрибутов. Н о сущ ествует и дру­
го й сп о со б , к о т о р ы й б о л е е п р е д п о ч т и т е л е н с т о ч к и зр е н и я за­
д ач и р а зд ел е н и я кодов Jav aS crip t и Н Т М Ь . Д а в ай т е п о см о тр и м
н а ф у н кц и и с д ругой т о ч к и зр е н и я.
Как ни удивительно, но функция — это не более чем пере­
менная. Ее т е л о п р е д с та в л я е т с о б о й зн а ч е н и е , а и м я —и м я
п е р е м е н н о й . В от как м ы п р и в ы к л и в о с п р и н и м а т ь ф ункц ии:
ф ункция, созданная
'о ш ч н ы м способом .
function showSeatStatus(seatNum)
{
alertC'This seat is " + getSeatStatus (seatNxm) +
А в о т т а ж е сам ая ф у н кц и я, со зд ан н ая другим
сп о со б о м .
Б качсст бс и м е н и
ф ункции в ы с т у п а е м
и м я п ерем енной.
var showSeatStatus = function(seatNum) {
alertC'This seat is " + getSeatStatus(seatNtam) +
b-
Э то т код п о к а зы в а ет п р о ц е сс со зд ан и я ф у н кц и и н а п р и м ер е
си н так си са, исп о льзу ем о го для со зд ан и я п е р ем е н н о й . П р о ц е ­
дура с о с то и т и з о д н и х и т е х ж е ч астей : у н и кал ьн ы й и д е н т и ф и ­
к а т о р (им я ф у н кц и и ) плю с его зн а ч е н и е (тел о ф у н к ц и и ). Т ел о
ф у н кц и и , ф и гурирую щ ее сам о по себе, б ез и м ен и , н а зы в а ет ся
литералом функции.
Д ру ги м и словам и, ф у н кц и ям и м о ж н о у п р ав л я ть т а к ж е, как
и п е р е м е н н ы м и . К ак вы дум аете, ч т о д ел а е т следую щ ий код?
var myShowSeatStatus = showSeatStatus;
296
глава 6
8 р о ли значения п ер ем енной
'в ы с т у п а е т т е л о ф ункции.
В подобных к о н ст р у к ц и я х
оно назы вает ся л и т е р а л о м
ф ункции.
функции
Вызов функции и ссылка на нее
Н а зн а ч и в и м я ф у н к ц и и д ругой п е р е м е н н о й , вы д аете э т о й п е р е м е н н о й
доступ к телу ф ун кц и и . Т о е с ть вы м о ж ете н а п и са ть следую щ ий код:
Вы зов т ой же самой функции через
alert(myShowSeatStatus(23));
перем енную m ySh o w S ea tS ta tu s.
Р езультат в ы зо в а п е р е м е н н о й m y S h o w S e a tS ta tu s ( ) и ф у н кц и и
s h o w S e a t S t a t u s ( ) и д е н т и ч е н , так как в о б о и х случаях п р о и с ­
х о д и т ссылка н а о д и н и т о т ж е код. С о о т в е тс т в е н н о , ссы л ко й н а
ф ун кц и ю я в л я е т с я ее имя.
showSeatStatus ---^
^
myShowSeatStatus
function() {
};
В ч ем ж е р а зн и ц а между ссы л к о й н а ф ункц ию и ее вы зовом ? Ссыл­
ка на функцию ф и гу р и р у ет сам а по себе, в т о в р е м я как п осл е в ы ­
зова функции ст ав я т с я ско б ки , ч асто с н а б о р о м аргум ентов.
Функция это
такая переменная,
значение которой
является ссылкой
на ее тело.
var myShowSeatStatus = showSeatStatus;
Вызовем функцию
yShow SeatStatusQ j
чт о эквивалент но вы ­
зову show SeatStatusQ .
myShowSeatStatus(23);
С делаем п е ­
рем енную
m y S h o w S e a tS ta tu s
ссы лкой на ф у н к ­
цию.
П роанализируйте данный ниже код и определите, какое число появится в окне.
неиие
function doThis(num)
return num++;
{
}
function doThat(num)
return num— ;
{
}
var X = doThis(11);
var Y = doThat;
var z = doThat(x);
X = у (z);
у = x;
alert(doThat(z - y));
OK
У
далее >
297
решение упражнения
іажненке
Вот как работает данный код и к какому результату он приводит.
решение
function doThis(num)
return num++;
{
}
function doThat(num)
return num— ;
{
var X = doThis(11);
var у = doThat;
var z = doThat (x) ;
X = у (z);
У = x;
alert(doThat(z - y));
X = 12.
'
\
у = doThat
z - d o T h a t(lZ ) = 11
X = doThat(Xl-) = l O
у = XO
a(eirt(doThat(XX - 1C))
Часщо
_^аДаБаеМые
Б о І їр о с Г ь і
Неужели разделение программы
на части настолько важно?
не боясь случайно внести изменения в код
иауаЗспр!, которого они не понимают.
в памяти, функции сохраняют ссыпку на
свой код. То есть значение функции — это
не сам по себе код, а ссылка на место
( ^ ; И да, и нет. Для простых приложений
это не обязательно. Почувствовать
• А чем функция отличается
от обычной переменной?
в памяти, где этот код хранится. Точно
так же, как почтовый адрес на конверте
является только ссылкой на ваш дом, а не
вашим домом.
преимущества от разделения HTML,
CSS и JavaScript-кодэ можно только
в сложных, многострочных приложениях.
Чем длиннее программа, тем сложнее ею
управлять и тем проще допустить ошибку
в процессе редактирования, особенно
в случае использования разнородного
кода. Разделение позволяет вносить
функциональные изменения без риска
повредить структуру или внешний вид
страницы. Кроме того, данный подход
позволяет веб-дизайнерам редактировать
структуру и внешний вид страницы,
298
глава 6
п
Разница заключается в том, каким
образом вы можете поступить с данными.
Данные, связанные с функцией, можно
запустить на выполнение. Вы указываете
это, ставя за именем функции скобки
с набором аргументов, если таковые
требуются.
В чем смысл ссылки иа функцию?
0 ; в отличие от обычной переменной,
которая хранит данные в виде значения
Ссылки на функции используются в целях
эффективности. Ведь проще хранить
ссылку, чем набор копий одного и того
же кода. Поэтому, назначая функцию
обработчику событий (именно этим вы
займетесь через пару секунд), вы на
самом деле назначаете только ссылку на
код функции.
функции
Ссылки на функции — это прекрасно,
но какое отношение они имеют к раз­
делению кода?
Обратный Вызов функций
С сы л ки н а ф у н к ц и и т е сн о св я зан ы с о соб ы м сп о со б о м вы зо ва
ф у н кц и й , к о т о р ы й п р и го д и т с я нам п р и р а зд ел е н и и р азл и ч н ы х
т и п о в кода. В п р о гр ам м е M a n d an g o вам уж е п р и х о д и л о с ь в с т р е ­
ч ат ь с я с в о т та к и м и кон струкц и ям и .
setSeat(i * seats [i] .length ■¥ j, "select", "Your seat");
Н о эт о н е е д и н с т в е н н ы й сп о со б в ы зо в а ф ун кц и й . Сущ ествует
ещ е и т а к н азы в а ем а я п р о ц ед у р а обратного вызова, н е требую ­
щ ая ваш его н е п о ср е д с тв е н н о го участия.
Ш ТУРМ
Каким образом вы можете использовать обратный
вызов функции в Mandango?
далее >
299
ф ункция против функции обратного вызова
Беседа у камина
Обычная функция против функции обратного вызова.
Обычная функция:
я м н о го слы ш ала о том , ч т о т ы н е п р и е м ­
л еш ь л о к а л ьн ы х вы зо во в. И н т е р е с н о , п о ­
чему?
Т ы и м ееш ь в виду б раузеры ? Т о ж е м не эк зо ­
ти ка. М не к аж ется, т ы п р о с т о зад и р аеш ь нос
п ер е д тем и , к то обш;ается с кодом с ц е н а р и я
о б ы ч н ы м способом .
Функция обратного вызова:
Д а потом у, ч то у м ен я другая цель. М не
н р а в и тся , когд а м ен я вы зы ваю т и з эк зо т и ч е ­
ски х мест.
П ослуш ай, м ы ж е н е го в о р и м о том , кто
лучш е, а кто хуже. М ы все яв л яе м ся ч астью
сц е н а р и я , п р о с т о я п р ед о ставл я ю доступ
к коду снаруж и. Б е з м е н я н ев о зм о ж н о узнать,
ч то п р о и с х о д и т за п р ед ел ам и сц ен ар и я.
Д а ч то т ы говориш ь! Д а ко го волнует происходяш ;ее за п р ед ел ам и сц ен ар и я?
В озм ож н о, т ы и п рава. М не н р а в и тс я узна­
вать о том , ч т о с т р ан и ц а уже загрузилась,
ч т о п о л ьзо в а т е л ь щ елкнул к н о п к о й м ы ш и
и л и ввел текст. Т а к т ы го в о р и ш ь, ч т о м ы н е
зн ал и бы об это м , если бы н е ты?
В сех и каж дого. Н е заб ы вай , ч т о сц ен ар и и
созд аю тся д ля уд обства п о л ьзо в а тел ей . Н е
и м ея в о зм о ж н о сти о тсл ед и ть п р о и сх о д я щ ее
снаруж и , п р а к ти ч е с к и н ев о зм о ж н о улучш ить
п о л ьзо в ат ел ьск и й и н те р ф е й с .
И м е н н о так. Б р ау зер вы зы в ае т м ен я, и во
м н о ги х случаях уже я вы зы ваю теб я. Ведь
о т в е т н а в н еш н и е с о б ы т и я ч асто тр еб у ет
вк л ю ч ен и я н еск о л ьк и х ф ункц ий.
Б ы л о п р и я т н о узнать, ч т о м ы н е т а к уж р а з­
л и ч а ем с я , как эт о сн ач ал а казалось.
Д а. Т ы см о тр и ш ь в корен ь.
Н е о б р ащ а й с я ко м не, я сам а т е б я вы зову.
Н у поп робуй .
300
глава 6
функции
События, обратный ВызоВ и атрибуты HTML
Вам уж е п р и х о д и л о с ь в с т р еч а т ь с я с ф у н кц и ям и , к о т о р ы е в ы зы ваю тся н е ваш им
кодом , а браузером . С ам ы м р а с п р о с т р а н е н н ы м п р и м ер о м т а к о й ф у н к ц и и я в л яе т с я
о б р а б о т ч и к со б ы ти й . И м е н н о с его помош,ью р а б о т а е т п р о гр ам м а M an d an g o . Б о л ее
то го , о б р а б о т ч и к и с о б ы т и й и м ею т сам ое н е п о ср е д с тв е н н о е о т н о ш е н и е к п р о б л ем е
После загрузкы
р а зд ел е н и я H T M L и Jav aS crip t-кода
ст раницы браузер
вы зы вает ф ун кц и ю
initSeatsQ тг»
on/oadJ
Ш
^ ^ 1 S ii
m
m
u
showSeatStatus(26);
Д а н н ы е ф у н кц и и о б р а т н о г о в ы зо в а с в я за н ы с с о б ы т и я ­
м и в H T M L -коде с т р а н и ц ы M an d an g o .
H T M L -a m p u S y m onload
связы вает ф у н к ц и ю
, ^
. ..„
._
initS ea tsQ с собы т ием
< body o n lo a d = " 3 .n itS e a ts ( ) ;" >
onload.
<img id="seat26" src="" alt="" onclick="showSeatStatus(26);" />
H TM L- а т р и б у т onclick
связы вает ф у н к ц и ю
sh o w S e a tS ta tu sQ с с о ­
б ы т и ем onclick.
К со ж ал ен и ю , п р е к р а с н о р а б о таю щ ее с в я зы в ан и е о б р аб о т ч и к о в
с о б ы т и й с со б ы т и я м и п р и п о м о щ и H T M L -aтpи бyтoв н ев о зм о ж н о
без в за и м о п р о н и к н о в е н и я JavaScгipt- и H T M L-кoдa. П о л о ж е н и е
м о ж н о сп асти п р и п о м о щ и ссы л о к н а ф ун кц и и .
далее ►
301
ссылки на функции
Ссылки на функции
Д л я с в я зы в а н и я ф у н кц и и о б р а т н о г о в ы зо в а с с о б ы ти е м м ож н о
н е и с п о л ь зо в ат ь H T M L -атрибуты , а н а зн а ч и т ь ссы лку н а ф унк­
ц и ю н е п о ср е д с тв е н н о KOÄyJavaScript. В р езул ьтате вам во о б щ е
После и
йп
не п р и д е т с я и м е т ь дел а с Н Т М Ь-кодом - п р о с т о в о сп ол ьзуй тесь ско б о к! fe d b м ы ^нТс^б
ссы л ко й н а ф ункц ию .
запускат ь, мы Ы г о т ш ь
. ,
,
.
.
—
ссы лаем ся на нее
window.onload = initSeats;
Ссылка на ф ункцию
initSeatsQ назначена
свойст ву события
onload.
C fb s m m onload являет ся
свойст вом объект а window.
Ч т о б ы с в я зать о б р а б о т ч и к со б ы т и й и с к л ю ч и тел ьн о с Jav aS crip tкодом , нуж но н а зн а ч и т ь ссы лку н а ф ункц ию свойству со б ы т и я
о б ъ екта. В случае с н аш им со б ы ти е м o n l o a d эт о п р и в о д и т к вы ­
зову ф у н кц и и i n i t S e a t s () п о сл е загрузки ст р ан и ц ы . В от как
эт о м о ж н о п р е д с та в и ть сх ем ати чн о :
onload!
window.onload();
Событие onload запускает
обработчик посредст вом
свойства window.onload...
initSeats О ;
...и т ак как эт о м у свойст ву назначе­
на ссылка на ф ункцию initSeats(), эт а
функция вызывается для обработки
события.
И м е н н о эта т е х н и к а п о зв о л я е т ч е т к о р а зд ел и ть JavaScriptи Н Т М Ь-код — ведь вам уже н е тр еб у ется н а зн а ч а т ь JavaS criptкод Н Т М Ь-атрибутам .
<body>
Т е п е р ь < b o d y > н е с о д е р ж и т н и ч е го ли ш н его . О стал о сь т о л ь ­
ко за с т ав и ть код о б р аб о т к и с о б ы т и я зап у скаться как м ож н о
ран ьш е, и м е н н о п оэтом у о н о б ы ч н о п о м ещ ается в за го л о во к
стр ан и ц ы .
Н о как ж е б ы ть в ситуации , когд а о б р аб о тч и к у с о б ы т и я нуж но
п е р е д а ть аргум ент? Д л я с о б ы т и я o n l o a d в M a n d a n g o т а к о й п р о ­
блем ы н е сущ ествует, а в о т со б ы ти ю o n c l i c k нуж но п ер ед ать
н о м е р кр есл а, к о т о р о е в ы б р ал п о л ьзо в ател ь. С сы л ки н а ф унк­
ц и и н е п о зв о л я ю т р е ш и т ь данную задачу...
302
глава 6
Ссылки на функции
позволяют легко
связать обработчик
события с самим
событием.
функции
Литерал функции
»WMwM'ISteltlxölr
С о б ы ти е o n l i c k , с в я за н н о е с и зо б р а ж е н и я м и кр есел ,
д олж н о в ы зы в ать ф ункц ию s h o w S e a t S t a t u s () с н о м ер о м
кр е сл а в кач еств е аргум ента. П р о с т о н а зн а ч и в ему ссы лку
н а ф ункц ию , м ы н е см ож ем п е р е д а ть аргум ент. П оэтом у
ссы л аться в д ан н о м случае следует н а л и т е р а л ф у н кц и и , из
к о т о р о г о и будет осущ ествлен вы зов.
Я Й Й Г1Й
Так M&I получаем д о ст уп к с в о й с т в у onclick о б ъ ект а с изображе
нмем сид&нья. ^
л
d o c u m e n t . g e t E l e m e n t B y l d ("seat26").onclick = function(evt)
{
showSeatStatus(26)
};
Л и т е р а л ф ункц и и служ и т как бы
« к о н т е й н е р о м » для вызова ф у н к
цыы s k o w S e a tS ta tu s (), позволяя
п ер е д а ва т ь в нее а р гум ен т :
Л и т е р а л ф ун кц и и н а значен с во й ст ву собы т ия
onclick как ссы лка на
ф ункцию .
Л и т е р а л используется в кач естве «оболочки» для вы зо ва ф ункции
s h o w S e a t S t a t u s {), и и м ен н о о н п о зв о л я ет п ер ед ать н ом ер
кресла. Его м ож н о п р ед стави ть в виде б езы м я н н о й ф ункции,
о б раб аты ваю щ ей собы тия. И м ен н о по э т о й п р и ч и н е л и тер ал ы
ин огд а назы ваю т анонимными функциями.
К од п о к а зы в а ет, каким о б р азо м в Jav aS crip t п р ед ставл ен о б ъ ект,
п ер е д а в ае м ы й о б р аб о тч и ку , в д ан н о м случае п о ср ед ство м аргу­
м ен та e v t . Э то т о б ъ е к т с о д е р ж и т и н ф о р м а ц и ю о собы ти и .
ажнше
О б ъ е к т e v e n t а вт о м а т и ч еск и
п ер ед а ет ся об работ чику со
бы т ия ка к первы й а р гу м е н т ,
Литералы функции
позволяют создавать
анонимные
обработчики событий.
Свяжите функцию i n i t S e a t s () с событием o n l o a d , используя вместо ссылки
литерал.
далее >
303
реш ение упражнения
Вот каким образом функция initSeats {) связывается с событием onload при
помощи литерала.
;НСНИ2
гш гнпг
Function(evt)_ {
initSeatsQ;
Ь..................................
Ф у н к ц и я in itS e a ts Q в ы зы ва е м ся
у т р и о д р а д о т ч и ка собы т ия
^ ^
А р г у м е н т e vt игнорирует ся,
т а к к а к о б р а б о т ч и ку собы т ия
o n lo a d не т р е б у е т с я о б ъ е кт
event.
А где )ке связывание?
По-прежнему остался нерешенным вопрос о связи событий
с литералами функций. М ы увидели, что назначение обработ­
чика события onload может осуш;ествляться в заголовке стра­
ницы внутри тега <script>. В результате связанный с этим со­
бытием код не запускается до загрузки страницы. Точно такой
же результат м ы получали, назначая функцию initSeats ()
H T M L -атрибуту onload в теге <body>. Н о в каком месте связы­
ваются со своими обработчиками остальные события?
Это может происходить в функции обратного вызова обработ­
чика события onload.
window.onload
//
Свяжем
=
f u n c t i o n ()
остальные
события
-------------- //
Задаем
вид
i n i t S e a t s ();
{
з
Все ост а льн ы е собы т ия
с т р а н и ц ы м о г у т бы т ь
связаны в н у т р и о б р а б о т ­
ч и ка собы т ия o n lo ad .
кресел
-----------
};
Таким образом, именно обработчик события onload становится
функцией, инициализирующей все прочие события. Это удобно,
так как в результате запуск соответствующих фрагментов кода
осуществляется после загрузки страницы.
304
глава б
Обработчик события
onload прекрасно
подходит для
инициализации всех
остальных событий.
К о д , связанны й с с о ~~ б ы т и е м o n lo a d , до
си х пор за п у с к а е т с я
в н у т р и о б р а б о т ч и ка
эт о го собы т ия.
функции
_
часзво
чаДаБаеМые
Б о Т 1 |> о С Ь 1
Почему функциям обратного
вызова придается такое значение?
3 * Отличаются ли функции обратного
вызова от обработчиков событий?
0 ; Функции обратного вызова позволяют
; Да. В главе 12 вы познакомитесь
с другим способом применения функций
обратного вызова, в процессе которого
они обрабатывают данные, посланные
реагировать на события, происходящие
за пределами сценария. Для их
запуска требуется, чтобы произошли
определенные события. Узнать о том,
что нужное событие произошло, функции
обратного вызова позволяет браузер. Для
этого нужно связать функцию с пусковым
механизмом, роль которого обычно
играют различные события.
сервером в ответ на запрос Ajax.
обратного вызова вызывается только
один раз. То есть когда функция
вызывается один раз и не вашим кодом.
Литералы назначаются непосредственно
свойствам события, в то время как на
именованные функции в таких ситуациях
делается ссылка. Фактически это просто
более эффективный способ работы
в случаях, когда вам не требуются
именованные функции. Кроме того,
именно литералы приходят на помощь,
если нужно не только сослаться на
функцию, но и передать ей аргумент.
Я так и не понял, почему важны
литералы функции.
: Литералом называется тело функции
без имени. Литералы идеально подходят
для тех ситуаций, когда функция
возьми в руку карандаш
Впишите недостающий код в новый обработчик события
onload программы Mandango.
window.onload = function О
{
// с в я з ы в а е м со щ е л ч к о м на к н о п к е F i n d Seat
document.getElementByld ( " f i n d s e a t s " ) .........
// с в я з ы в а е м со щ е л ч к а м и на и з о б р а ж е н и я х к р е с е л
vn.ti
= fun c t i o n (evt)
d o c u m e n t . g e t E l e m e n t B y l d ( seatO ) . ........
{
„
=
'M
= f u n c t i o n (evt)
d o c u m e n t . g e t E l e m e n t B y l d ( s eatl ). ........
(
4.0 .M
= f u n c t i o n (evt)
d o c u m e n t . g e t E l e m e n t B y l d ( seat2 ) . ........
{
// З а д а е м в и д к р е с е л
далее >
305
реш ение упражнения
Возьми В руку карандаш
Решение
Вот как выглядит код нового обработчика события onload
в программе Mandango.
О б р а б о т ч и к со б ы ­
т и я o n lo a d я в л я ­
е т ся а н о н и м н о й
ф ункц ией .
w i n d o w . o n l o a d = f u n c t i o n ()
11
Ф у н к ц и я fin d S e a ts O
связана с со б ы т и е м
o n c lic k п р и п о м о щ и
ссы лки.
{
С в я з ы в а е м со щ е л ч к о м н а к н о п к е F i n d Seat
d o c u m e n t .g e t E l e m e n t B y l d ("f i n d s e a t s ") . ,
// С в я з ы в а е м CO щ е л ч к а м и на и з о б р а ж е н и я х к р е с е л
d o c u m e n t. g e tE le m e n tB y ld ( " s e a tO " ) . , 0 п с 1 / с к =
f u n c tio n (e v t)
f
’
d o c u m e n t . g e t E l e m e n t B y I d ( " s e a t l " ) . .OnC/!Ck= fun c t i o n (evt)
(
>
d o c u m e n t. g e tE le m e n tB y I d ( " s e a t 2 " ) . ..0 n c /ic k =
{StpwSeatStatu^^^^
]
II
f u n c tio n (e v t)
Задае м вид кресел
initSeatsQ;
функция init5eats0
вы зы вает ся для з а ­
верш ения задач, с в я ­
занны х с за гр узко й .
С войст во опИ ск для ка ж до го
из и зо б р а ж е н и й за д а е т код,
з а п у с к а е м ы й п р и щ елчке.
п о э т о м и ей
КЛЮ ЧЕВЫЕ Щ
МОМЕНТЫ
Функции обратного вызова вызываются браузером
в ответ на события вне пределов сценария.
Ссылки позволяют назначать функции, как если бы
они были переменными.
306
глава 6
Ссылки позволяют связать функции обработчиков
событий с кодом иауаЗсг1р1, не затрагивая НТМ1.
Литералами называются безымянные функции.
функции
Ч асто
З ад авае м ы е
В опросы '
Почему обработчик события o n l o a d в Mandango
создан как литерал функции?
; Потому что у нас нет причин использовать в этом
месте именованную функцию. Наша функция вызывается
только один раз в ответ на событие o n l o a d . Можно было
создать именованную функцию и назначить ссылку на нее
w i n d o w . o n l o a d , но связь между функцией и событием
становится более прозрачной, если их связать друг с другом
при помощи литерала.
Q ; Да. Вы можете решить, что лучше связать их непо­
средственно в теге < s c r i p t > . Но вспомните о том, что
на этом этапе содержимое страницы еще не загружено. Со­
ответственно, функции g e t E l e m e n t B y l d () не будут
вызываться. Полную загрузку страницы гарантирует только
событие o n l o a d , с которым следует связать нужные вам
обработчики.
Оболочка HTML-страницы
Разделение JavaScript и H T M L -кодов в програм­
ме Mandango приводит к тому, что структурная
часть страницы становится совсем небольшой.
В результате вы можете легко редактировать
HTML, не боясь случайно внести изменения
в код JavaScript.
Я хочу это
видеть!
Нужно ли связывать с обработчиком события
o n l o a d все остальные функции обратного вызова?
Посмотри на
код! Он такой...
редактируемый!
<body>
<div style«"margin-top :75px; text-ali
gn;center">
<amg id-"seatO" src<img id="seatl" src-’
<img id="seat2" src='
<img id»"seat3" src-'
<irag ld«"seat4" src-'
<img id-"seat5" src="
<lmg ld="seat6" src="
<img id-"seat7" src-"
<img id="seat8" src-"
<img id-"seat9" src-"
<img id-"seatlO" src<img id-"seatll" src-=
alt= .... />
<img id-"seatl2" src/>
alt='
<img id-"seatl3" srcalt=’ />
<lmg id-"seatl4" src- "" alt=’
^
<img ld-"seatl5" src-'
alt=’■" />
<img id="seatl6" src-'
alt='’ />
<img id="seatl7" src-'"" alt»"
" />
<img ld-"seatl8" src»""" alt="
" />
<img id-"seatl9" src-""" alt="
" / X b r />
<img id-"seat20" src-" alt="
" />
<lmg id="seat21" src-" alt="
" />
<img id-"seat22" src-" alt="'
" />
<img id-"seat23" src-" " alt="'
" />
<img id-"seat24" src=" " alt="’
’ />
<img id-"seat25" src-"'" alt="'
* />
<img id="seat26 " src-"'" alt=""
' />
<img ld-"seat27" src-"'" alt=""
' />
<img id-"seat28" src-""" alt=""
/>
<img id-"seat29" src-""" alt=""
/ X b r />
<lmg ld-"seat30" src-""' alt='"'
/>
<img id="seat31" src-""’ alt=""
/>
<img id="seat32" src-""' alt=""
/>
<img id-"seat33" src-""' alt=""
/>
<img ld-"seat34" src-"" alt=""
/>
<lmg id-"seat35" src-"" alt=""
/>
<img id-"seat36" src-"" alt=""
/>
<img id-"seat37" src-"" alt=""
/>
<img id-"seat38" src-"" alt=""
/>
<img ld="seat39" src-"" alt=""
/ X b r />
<rnput type-"buttcn" id=
findseats" value-"Find Seats"
</aiv>
</body>
далее >
307
работ аю щ ий JavaScript
и еще немноМо про JavaScr^pt...
Добиться мира во всем мире м ы не смогли, зато научились
управлять температурой в комнате при помощи JavaScript. М ы
узнали, как улучшить наши сценарии, деля крупные задачи на
более мелкие, фокусируясь на единственной цели и создавая
код, пригодный для многократного использования.
HEAT FIRST
С т ройка
1
Кров
Сет и Джейсон также воспользовались данной технологией
и создали более эффективную и простую в редактировании вер­
сию Mandango. П о крайней мере, в души наших мачо пришло
спокойствие...
«34
i f 3
V-" -ч
_
r
-
;
o
a
X
a
r
*
through 3 in Row 4 are available. Ассврл?
(
D
D
O
0
i
Г
П ервы й р яд !
308
глава 6
f
Canctl
функции
Вкладка
Согните страницу
по вертикали,чтобы
совместить два мозга
и решить задачу.
^
Что дали вам функции?
< г-
---------
\ Ы хороШ о, а ДВа ,ЩЧШе!
< г-
Установить мир во всем мире всегда сложно. Даже
в JavaScript только самый систематизированный
код даст вам спокойствие и уверенность.
Комфортная жизнь дается нелегко,
по крайней мере, в 1ауа8спр1.
у
ф о р м ы и ч^’ о Б е р к а д а н н ь х х
★
Пусть он все расскажет
Для получения информации от пользователей при помо­
щи иауаЗсг1р1 вам не потребуется быть джентльменом.
Но вы должны быть аккуратны. Люди часто делают ошибки, а это озна­
чает, что данные, полученные при помощи веб-форм, далеко не всегда
корректны. Проверяя вводимые данные при помощи JavaScript, вы
увеличиваете надежность веб-приложений и снимаете дополнительную
нагрузку с серверов. Полоса пропускания нам пригодится для восхити­
тельных видеороликов и чудесных фотографий.
ПОЛЯ данны х для баннера
Фирма ВаппегосКу
Высококлассный летчик Говард решил превратить свою любовь к полетам
в бизнес по развешиванию баннеров и основать фирму Ваппегос11у. Говард
хочет придать новый вид понятию «баннерная реклама», принимая через
Интернет заказы на воздушные баннеры. О н надеется, что новая система
приема заказов освободит ему время для столь любимых полетов.
Г овард р е ш и л извлечь
х о р о ш у ю выгоду из эт о го
аэр о п л а н а в р е м е н В т о р о й
м и р о в о й войны.
Пр и номош,и веб-формы крайне важно собрать всю нужную
для заказа баннеров информацию. Говард решил, что на
странице кроме стандартных пунктов заказа должно быть
еще и поле для ввода адреса электронной почты.
Текст
Собственно текст объ­
явления.
Указывает, в каком именно
регионе должно быть показа­
но объявление.
Даша полета
О пределяет, когда бу­
дет вывеш ен баннер.
Email
Телефон
(1мя
И м я заказчика.
312
глава 7
К онтактная инф орм а­
ция заказчика.
Адрес электронной
почты для связи с за­
казчиком.
формы и проверка данны х
HTML-форма
П р и помощи Н Т М Ь первая форма Говарда приоб­
рела вот такой вид:
Sannerodty - P « r s o « a t i z e d ^ i « J k y B a n n m
©00
CD
B A N N E R O C I T Y
Enter ms banner m essage: |
_______
Enter ZIP « Jd e of the tocation: |
Enter the d ate for th e m essage to be s h o i^ :
Enter your nam e; j
___________
Enter your phone number;
_
Enter your email address; |
Order Banner
Эта форма для сбора заказов имеет все необхо­
димые поля и, кажется, готова"к работе даже без
JavaScript. Так ли это?
V
Форма заказов вы
глядит здорово!
Говард с т о л ь ко л е т
от работ ал л е т чи ­
к о м . ч т о до сих п о р не
м о ж е т ю а сст ат ься
с кр а си б ой ф о р м о й .
^ * ^ ч а т ь ко д ф о р м ы м о ж н о п о адреса
5озьми в руку карандаш
^^ttpУ/www.headfirstlabs.com/booй/hfjs/
Давайте попробуем заполнить форму от руки. Не волнуйтесь,
денег за рекламу нам платить не придется.
Enter the banner message;
Enter ZIP code of the location:
Enter the date for the message to be shown:
Enter v^ur name:
Enter your phone number;
Enter your email address;
далее >
313
реш ение упражнения
Возьми в руку карандаш
Решение
М ы не знали,, ч т о д л и ­
на баннера не м о ж е т
п р е в ы ш а т ь 32- зн а ко в,
и ввели с л и ш к о м д л и н ­
ный т е к с т .
Вот каким образом мы заполнили предоставленную Говардом
форму.
А м е р и к а н с к и е индексы
с о с т о я т всего из п я т и
циф р, в т о врем я ка к
т у т у к а за н о ш ест ь.
■
Enter the banner message:
Mandango... выбор мест в кино для настоящих
Enter ZIP code of the (ocatton: 100012 ^
Enter the date for the message to be shown:
Enter your name:
1 1 ,2009
Seth Tinselman
/ Ш е г i^ur phone number: |(212)
Enter your email address:
И м я за ка зч и ка
о порядке.
March
555-5339
setht@mandango
В адресе э л е кт р о н н о й ^
п о ч т ы долж ен бы т ь
у к а за н до м е н , н а п р и м е р .biz.
Номер т еле­
ф она следовало
ввест и 6 виде
7
А б о т дат у т ребова­
лось у к а з а т ь в ф о р м а ­
т е М М /Д Д /Г Г Г Г .
без всяки х скобок.
Когда языка НТМ1 недостаточно
Говард убедился, что без помощи JavaScript, который будет про­
верять корректность вводимой информации, ему не обойтись.
Кроме того, ему нужно донести до пользователей, какие именно
данные считаются «корректными». Ведь без подсказки невозмож­
но догадаться о 32-символьном ограничении на текст баннера или
о том, что дату следует вводить в форме ММ/ДД/ГГГГ.
Enter the banner
глава 7
О
message: | Mandango... выбор мест в кино для настоящих
J a v a S c rip t п о м о ж е т
и зб е ж а т ь ввода не к о р р е к т н ы х данных.
314
Прошу прощения, но
длина текста ограничена
32 символами.
В о т т о л ь ко ф о р м ы )
H T M L не у м е ю т
р а зг о в а р и в а т ь !
О сновная проблем а состоит в том, что все умение JavaScript
управляться с данны ми не помож ет Говарду, пока он не
поймет, каким образом предоставить5ауа8сг1р1 доступ
к вводимой в форму инф орм ации...
ф ормы и проверка данны х
Д оступ к данным формы
Получение доступа к введенным в форму данным нужно начать
с идентификации каждого из нолей. Такая задача решается средствами H T M L при помощи одного или двух атрибутов.
кш ьны Т об р^оТ за ^
I
Э д е т поле ф о р м ы .
А т р и б у т id
уникальным оа~
id = "zip co d e " name="zipcode"
<input
type="text"
size="5"
/>
р азо/л зад йе т
лю бой э л е м е н т
ст р а н и ц ы .
Enter ZIP code of the location: Iw o iT
I
------------
О
эт их ат рибут а служ ат
О ба
ба эн
идент
ввода.
Наличие двух идентификаторов объясняется существованием
нескольких способов получения доступа к полю. Во-первых,
с помощью функции g e tE le m e n tB y ld ( ) .Этот способ прекрас­
но работает, но есть и более простая альтернатива.
Каждому полю фо рмы соответствует объект form , который
можно передать функции, проверяющей корректность введен­
ных данных.
<input
id="zipcode"
name="zipcode"
type="text"
size="5"
o n c l i c k = " s h o w I t ( t h i s .f o r m ) " />
Объект fo rm представляет собой массив, содержащий все поля
формы. Пр и этом индексы массива не являются числами; их
роль играют уникальные значения атрибутов name! Поэтому
при передаче функции объекта fo rm в виде аргумента с именем
t h e Form доступ к полю ZIP code осуществляется следующим
образом:
П оказано значение
по л я Z IP code.
И м я аргум ент а.
У
function
showit(theForm)
{
100012
a l e r t (theS’o rm ["zip co d e "] .v a lu e ) ;
};
И м я поля ф о р м ы , з а данное 8 а т р и б у т е
п а т е т ега < in p u t> .
J
Н а м т р е б у е т с я не с а м о
п о л е , а хра нящ е е ся в нем
значение.
Данный способ доступа к данным ф о рмы не лучше и не хуже,
чем доступ с помощью функции g e tE le m e n tB y ld (), но он
проще для восприятия и требует меньшего количества кода.
далее >
315
когда нужна проверка
Ч асто
^аД аБ аеМ ы е
Б о І їр о С ь і'
Почему даже отдельное поле формы имеет доступ
к объекту form?
кобт
0:
I Иногда это не так, но следует помнить, что поля формы
могут вызывать функцию проверки, которой требуется доступ
к данным. В этом случае удобный доступ к остальным полям
формы обеспечивает именно объект
form.
Этот объект
обычно передается функции проверки, поэтому она может
быстро получить данные из любого нужного ей поля. Вы
в этом еще убедитесь на примере с формой Bannerocity.
То(
) есть значение является свойством ПОЛЯ формы?
То есть все ПОЛЯ формы являются объектами?
0 :,I Да. Каждое поле формы в коде JavaScript представлено
объектом form, который предоставляет быстрый и легкий
способ доступа к введенной в поля информации. Запись вида
f о rm [" оЬ j е с tn a m e " ] дает доступ к значению при по­
мощи свойства v a l u e . Но об этом мы поговорим в главах
9 и 10.
Я только что узнала, насколько важен до­
ступ к данным в JavaScгipt. Ведь именно он
позволяет проверить их корректность. Но как
понять, когда требуется проверка?
Проверку данных следует производить сразу
после их ввода.
Это означает, что ответ на вопрос «Когда произво­
дить проверку?» связан с событиями. Нужно знать,
какое именно событие позволяет обнаружить ввод
данных в поле. Именно с ним м ы познакомимся в сле­
дующем разделе.
316
глава 7
ф ормы и проверка данны х
Цепочка событий
Ввод данных в форму сопровождается целым рядом событий.
Эти события можно использовать как точку входа для операции
проверки данных. Рассмотрим типичную последовательность
действий при вводе информации, чтобы понять, какие именно
события при этом возникают и в какой именно момент.
О
Выделите поле (опГосиз).
©
Введите данные.
е
о
о
Ввод данных в поля
формы сопровождается
целой цепочкой
событий Дауа8спр1.
Перейдите к следующему полю
(опЫиг/опсЬапде).
Выделите его (onf ocus).
Введите в поле данные...
0
onfocus!
------
Enter the banner message: |м ^ а п д о ...
Enter Zip code of the location:
100012
выбор мест в кино для настоящих мужчинГ
onblur!
. 0 onfocus!
0
OonchangeT
Enter the date for the message to be shown;
Enter your name;
Enter your phone number:
Enter your email address:
При выделении поля появляется событие
оп£осиз, в то время как снятие выделения
сопровождается событием опЫиг. Событие
опсЬапде в отличие от события о п Ы и г появля­
ется в случае, когда с поля снимается выделение,
но его содержимое уже было изменено.
Ш ТУРМ
Какие из вышеупомянутых событий нам
потребуются для проверки данных?
далее ►
317
виж у л и я что-нибудь?
Событие onblur
Было бы логично начинать проверку данных после события
o n c h a n g e , но непонятно, как при этом поступать с пустыми
полями. Ведь для них ничего не изменилось, даже если поль­
зователь и выделял такое поле в процессе заполнения формы.
Проблема решается при помош;и события o n b l u r , возникаю­
щего при потере объектом фокуса.
onfocus!
Фокус на поле означает го­
товность к вводу данных.
Событие onblur является
замечательным сигналом
к началу проверки данных.
Поле осталось пуст ы м ,
как заказчик не
указал своего имени.
Enter your name: ][
^оле теряет фокус.
Текстовое поле оказывается в фокцсе
его и
«ользобйтель выделил
его щелчком или нажат ием клавиши
В отличие от события o n c h a n g e , событие o n b l u r возникает
вне зависимости от того, были ли введены в поле данные.
Таким образом, событие o n b l u r , конечно, является полезным
инструментом, но нужно внимательно отслеживать, когда
и как вы применяете его для уведомления пользователей о ре­
зультатах проверки данных.
чаап°
^адаБ аеМ ы е
БоЦроСЬ!
я правильно понимаю, что ряд событий возникает по­
сле ввода данных пользователем?
• Что означает это странное название o n b lu r ?
I Событие o n b l u r является противоположным по смыслу
Q ; Да. в ответ на нажатие клавиш появляются события
onkeypress, onkeyup, onkeydown и т. п. Иногда имеет
смысл написать реагирующий на них код, но для проверки инфор­
мации они не подходят, так как окно с предупреждением будет
появляться еще до завершения ввода. Фактически это приведет
к появлению уведомлений о каадой опечатке и каждом незавершен­
ном фрагменте информации. Поэтому лучше дождаться момента,
когда пользователь покинет поле. Именно в этот момент появляется
событие onblur.
318
глава 7
событию
o n f оси S. То есть если событие o n f o c u s
возника­
ет в момент фокусировки на поле, то время события o n b l u r
наступает после потери полем фокуса. Даже слово «фокус»
в данном контексте неточно отражает смысл происходящего, но
именно от него пошло слово «Ыиг» (размывание), указывающее
на отсутствие фокуса.
ф ормы и проверка данны х
Сообщение проверки
Самым простым способом быстро донести до пользователя нужную
информацию является использование всплывающего окна. Именно
таким способом пользователей уведомляют о некорректном вводе
данных. Для этого нужно вызвать функцию alert {) при обработке
события onblur.
Проверим, введены ли
данные в поле формы.
function validateNonEmpty(inputField)
{
// Проверка на наличие текста
Ф у н к ц и я п р о в е р ки
вы зы вает ся для
по л я п а т е .
if (inputField. value.length == 0) {
// Сообщаем пользователю, что данные не введены
a l e r t ( " P l e a s e e n t e r а v alue.");
И нф ормация о т о м , к а к
уст р а н и т ь проблему.
Пользователя просят
ввест и данные.
return false;
return true;
Please enter а value.
Т а к к а к поле n a m e
являет ся п у с т ы м ,
вы зы ваем окн о с с о общ ением .
Возьми в руку карандаш
С кол ько собы тий
%
onblur
появляется при такой последовательности
ввода данных? А с ко л ь ко собы тий
Enter your name:
onchange?
e in w ^
Seth Tinselman
Enter your phone num
Enter your email address:
setht@mandango
Событий onblur:
Событий onchange:
далее >
319
собы т ия onblur и onchange лицом к лицу
Возьми в руку карандаш_ _ _
\
Рош оиыр
Enter your name:
Вот сколько событий onblur и onchange появляется при таком
способе ввода данных.
Seth Tinselman
iseiman у
onbhtf!qj
onchange!
Enter your phone numb
Enter your email address:
—
setht@mandango
onchange!
—
Событий onblur: ..^
Событий onchange:
Беседа у камина
Собы тия onblur и onchange решают, когда следует реагировать
на некорректные данные.
onblur:
onchange:
Кажется, в наши дни сценарии только и за­
ботятся об отслеживании действий пользо­
вателей. Вот тут-то я и пригождаюсь.
Именно об этом я и хотел с тобой погово­
рить. Ходят слухи о каких-то пустых полях.
И все показывают пальцем на тебя.
Это да. М ы всегда даем знать, если элемент
форм ы вдруг оказался измененным или по­
терял фокус... или все сразу!
Честно говоря, твой намек меня шокирует.
Т ы же знаешь, что я всегда оповещаю о лю­
бых внесенных в форму изменениях.
Так никто и не сомневался в твоей способ­
ности реагировать на изменения. Н о вот
как ты поступаешь в случае, когда в поле так
ничего и не ввели?
320
глава 7
ф ормы и проверка данны х
onblur:
Вот именно. Это не имеет смысла. Точно так
же, как здравый смысл отсутствует у многих
пользователей, но при этом они заполняют
формы.
onchange;
Т ы утверждаешь, что пользователь может
попытаться отправить форму с незаполнен­
ными полями? Н о это же не имеет никакого
смысла.
Хорошо. Рассмотрим форму, в которой
пользователь не заполнил некоторые поля,
но тем не менее решил ее отправить... черт.,
мне страшно!
Не волнуйся, ты тут ни при чем. В конце
концов, данные, оставшиеся без изменений,
не твоя забота. Тебя зовут onchange.
Н о как же быть с предложенным тобой сце­
нарием, при котором отправляется форма
с незаполненными полями?
Я уже сказал, что это не твоя забота. Просто,
если для сценария важно, чтобы все поля
были заполнены, ему не следует прибегать
к твоим услугам.
Не стоит так нервно реагировать. Ты, ко­
нечно, не очень подходишь для запуска кода
проверки, но это не означает, что сценарию
не нужно узнавать об изменении данных.
Ведь есть еще и формы, позволяющие
редактировать хранящиеся в других местах
данные. Т ы можешь запускать процедуру
сохранения, только если изменения были
действительно внесены.
Рад это услышать, даже если твое утвержде­
ние и означает, что со мной вообще не надо
работать. О боже, мне опять плохо...
Да, действительно. Получается, что от меня
все-таки есть польза?
Конечно! Так что не переживай.
Спасибо. Т ы меня обнадежил.
Пожалуйста. Рад был с тобой поболтать, но
мне нужно проверить достоверность вон тех
данных.
далее ►
321
есть ли тут что-нибудь?
ищем... что-нибудь
Вернемся к странице Bannerocity. Говард понимает, что ему для
начала следует проверить, были ли введены данные в поля его
формы. С точки зрения JavaScript эта задача выглядит немного
по-другому. Лучше проверять не отсутствие данных в поле, а их
наличие. Другими словами, «что-то» — это «не ничего».
Что-то
Не ничего
Причиной такого парадоксального на первый взгляд подхода является
тот факт, что намного проще проверить отсутствие данных.
Не п у с м о .
Enter your name:
Seth Tinselman
Enter youf phone number:
П уст о .
Функция проверки должна реагировать на событие onblur для каждого
из полей, проверяя, не осталось ли поле пустым. Например:
Поле ф о р м ы и м & с т у н и ка л ьн ы е
и ден т и ф икат о ры , эт о пр е д о ­
с т а в л я е т к н е м у д о с т у п из
д р у г и х ч а ст е й сценария.
<input
id="phone"
name="phone"
type="text"
size="12"
onblur="validateNonEmpty(this);"/>
/К
Ф у н к ц и я v a iid a te N o n E m p tu O
вы зы вает ся в о т в е т на с о aw m ue o n b lu r и п р о в е р я е т ,
введены ли в поле данные
Ключевое слово this является ссылкой на поле формы.
Передавая поле в виде объекта функции проверки, оно
предоставляет доступ к введенному в это поле значению.
Ведь все поля формы содержат именно объект form.
322
глава 7
Поле ф о р м ы п е р е д а е т _ся ф у н к ц и и п р и п о м о щ и
клю чевого слова
ф ормы и проверка данны х
проверка полей на наличие данных
Для каждого из полей формы существует код, связывающий событие
о п Ы и г с функцией validateNonEmpty (). Это обеспечивает проверку
всех полей.
< in p u t id = "n a m e " nam e="nam e" t y p e = " t e x t "
s iz e = " 3 2 "
o n b lu r = " v a lid a t e N o n E m p ty (t h i s ) ; " / >
Поле п а т е ф у н кц и я
п р о в е р я е т на н а л и ­
чие им е н и .
ф ц н т и я п р о в е р я е т поле
pho n e n u m b e r на наличие
те л е сЬ о н н о го м Ш £ а .
--function validateNonEmpty (inputField)
// Проверка на наличие
{
С войст во le n g th
за д а е т ко ли че ст во
с и м во л о в в ст р о ке .
--
if (inputField.value.length == 0) (
// Сообщаем пользователю, что данные не введены
al e r t
("Please enter а value.");
Телефонный номер
не введен, п о э т о м у
ф ункция возвращ а­
е т значение false
и от кры вает окно
с предупреждением-
return false;
И м я в поле о б н а р у ж е ­
но, п о э т а м и ф у н кц и я
возёраицает значение
tru e .
return true;
1
Please enter а value.
В данном примере пока никак не задействованы значения, воз­
вращаемые функцией validateNonEmpty (). О н и сообщают
вызвавшему функцию коду о результатах проверки: true, если
данные обнаружены, и false в противном случае. Немного
позже вы увидите, каким образом эти значения используются
для обеспечения корректности данных перед отправкой их на
сервер для дальнейшей обработки.
Функция проверки
гарантирует заполнение
всех нолей формы.
Ш ТУРМ
Какие недостатки имеет всплывающее окно
с оповещением о вводе некорректных данных?
далее у
323
не будем раздражат ь пользователей
Проверка без предупре)кдаюцих
всплывающих окон
Говард быстро сообразил, что всплывающие окна не самый
лучший способ информирования о вводе некорректных данных.
Слишком много жалоб поступало от потенциальных заказчиков.
Ведь рано или поздно любого начинает раздражать, когда ввод
данных прерывается появлением окна. Пусть даже в этом окне
и содержится нужная пользователю информация.
у,
„
Н овы й H T M L -э л е м е н т
п р е д о с т а в и л м е с т о для
‘и н ф о р м а ц и о н н о го с о -
1овард решил переити к «пассивным подсказкам», которые не пре- общения
рывают процесс ввода. О н предпочел добавить к форме несколько
элементов НТМЬ.
Enter your phone number:
P fe a s e e n t e r a v a lu e .
Новые H T M L -элементы позволяют донести до пользователя полезную информацию без участия всплывающих окон. Достаточно
добавить тег <span> ,задающий контейнер для внутреннего текста.
г
/ г_
Этот тег появляется в коде веб-страницы сразу под полем input.
В т о р о й а р гу м е н т ф у н кц и и
va lia a teN o n tm p у и
т е м р ь передает ся
^ вспом огат ельны м
т екст ом .
< in p u t id="phone" name="phone" ty p e = " te x t" size= "1 2 "
o n b lu r= " v a lid a te N o n E m p ty (th is, docum ent. g e tE le m e n tB y ld ( 'p h o n e _ h e lp ') ) " />
<span id= "phone_help" c l a s s = " h e lp " x /s p a n >
Тег <span> изначально
являет ся п у с т ы м , но
он и м е е т IP , связанное
с полем ф орм ы phone
n u m b e r.
Д л я ф о р м а т и р о в а н и я вспо
м о г а т е л ьн о го т е к с т а
и с п о л ь зу е т с я с т и л ь class
В р е з у л ь т а т е он п и ш е т с я
наклонны м ш р и ф т о м к р а с ­
ного ц в е т а , х о т я в книге
эт о го и не видно!
С овпадение э т и х двух
и д е н т и ф и к а т о р о в о бе ­
с п е ч и ва е т появление
в с п о м о га т е л ьн о го т е к ­
с т а в поле ввода.
Итак, м ы вставили элемент span, содержащий вспомо­
гательный текст, и теперь нам требуется код, который
будет его отображать. Сделаем ответственной за эту
операцию функцию validateNonEmpty ().
324
глава 7
ф ормы и проверка данны х
УсАО}княем наш Валидатор
Новый подход к вспомогательным сообщениям заставляет нас от­
редактировать функцию v a lid a te N o n E m p ty (). Теперь она должна
еще и отображать и убирать текст из полей формы.
fu n c tio n v a lid a te N o n E m p ty (in p u tF ie ld ,
//
h e lp T e x t)
О б ъ е к т h e lp te x t
п е р е да е т ся ф у н кц и и
в ка че ст ве вт орого
аргум ент а.
{
П роверка на н али чи е т е к с т а
if (InputField.value.length == 0) (
//
Сообщаем п о л ь з о в а т е л ю , ч т о данн ы е н е в в е д е н ы
if (helpText != null)
-----
helpText.innerHTML = "Please enter a value.";
re tu rn
e ls e
fa ls e ;
(
/ / Данные о бн ар у ж ен ы , у б и р а е м в с п о м о г а т е л ь н ы й
текст
if
(h e lp T e x t
!= n u l l )
Убеж даем ся, чт о
э л е м е н т h e lp te x t
сущ ест вует
(h e lp T e x t != n u ll),
■и присваиваем свой­
с т в у in n e rH T M L
в с п о м о га т е л ьн ы й
т екст .
Н у ж н о сде л а т ь т а к ,
чт обы после ввода данны х
■ всп о м о г а т е л ь н ы й т е к с т
исчезал из поля.
-^ Г "
helpText.innerHTML =
return true;
тш
Проверка данных на странице Bannerocity стала заметно лучше
благодаря новому подходу. М ы все еще используем для этой
цели JavaScript, но уже более деликатным способом.
Enter ZIP code of m e loMtior,: [
Enter the d ate for the m essag e to b e shown:
Теперь вам не будут
надоедать всплывающие
окна.
■V
m m r a Ш иб.
m a s e enter a value.
Enter your nam e: | S e th T in selm an
Enter your phone nymber: |
' Please enter a value.
' m e s s enter а value.
Enter your email address: f
Если данные о т с у т с т в у ­
ю т , в поле о т о б р а ж а е т с я просьба и х ввест и.
Т а к к а к все введено,
в с п о м о га т е л ьн ы й
т е к с т не появляет ся.
далее ►
325
оно помест илось?
Хорошенького понемно>кку
Наша проверка на наличие данных работает отменно, но за­
думывались ли вы о том, что избыток может быть так же вреден,
как и недостаток? Чтобы понять суть проблемы, достаточно
посмотреть на последний заказанный Говарду баннер.
На баннер п о м е с т и л а с ь
т о л ь ко ч а с т ь т е кст а ...
С ет с Д ж е й с о н о м р в у т .
ы м еч у т?
^
ШТУРМ
Что же случилось с баннером и каким об­
разом можно решить данную проблему?
326
глава 7
формы и проверка данны х
Размер имеет значение...
Проблема в том, что на воздушном баннере помещается всего
32 символа, в то время как в соответствующее поле можно вво­
дить фразы произвольной длины. Пока что появляется только
вспомогательное сообщение о необходимости ввода данных,
но нигде не написано об ограничениях на ввод. Вот и причина
проблем Говарда!
Enter the banner message:
5 ы л введен с л и ш к о м
длинны й т е к с т , но
п о льзо ва т е ля не
проинф ормировали
00 э т о м .
Mandango... выбор мест в кино для настоящих мужчин'
Т а к к а к весь т е к с т
не с м о г п о м е с т и т ь ­
ся нд баннере, он был
обрезан...
Невозможно поместить неограниченное количество символов
на ограниченное место, а в результате м ы имеем недовольных
клиентов. Значит, требуется проверять еще и длину вводимых
фраз. Разумеется, снабдив форму еще одним вспомогательным
сообщением для пользователей.
Новы й т е к с т ограничен
ЗЯ сим волам и.
Enter the banner message: Mandangc-.. места для w
А т е к с т , не п р е в ы ш а ю щ и й
заданного л и м и т а , п р е к р а с н о
п о м е с т и л с я на баннере.
Возьми в руку карандаш
Напишите псевдокод, демонстрирующий работу функции,
которая проверяет длину сообщений. Не забудьте проверить
не только максимальную, но и минимальную длину.
далее >
327
проверка длины
Возьми в руку карандаш
Решение
А р гу м е н т а м ф унк~ ции m in L e n g tk и
m a x L e n g th следует
п р и с в о и т ь значения
i м Ъ7- с о о т в е т ст венно.
Вот принцип работы функции, проверяющей длину вводимых
в поле сообщений.
длиннее, чем m axLenyth)
„
„
Показашь оспомогательныи текст
Else
Убрать вспомогательный текст
Проверка длины
Новая функция v a l i d a t e L e n g t h () должна проверять, не вы­
ходит ли длина сообщения за отведенные границы. В случае
с Bannerocity она должна проводить ограничения сверху, хотя
проверка на минимальное количество символов в нее тоже
встроена. На всякий случай. Причина в том, что Говард сомне­
вается в существовании клиентов, которые захотят написать на
баннере всего одну букву.
h e lp T e x t) ;
Новой функции потребуется таюке аргумент для поля ввода
и вспомогательный текст, призванный помочь пользователю
правильно составить фразу. То есть всего у функции будет четы­
ре аргумента.
m in U n g th
— ^
maxLength
Максимальная длина вводимо­
го в поле текста.
............^ i n p u f F i e l d ..........
М инимальная длина вводимого в поле текста.
П оле, количество символов в котором проверяется.
Элемент, отображ аю щ ий
вспомогательны й текст.
< in p u t id="m essage" name="message" ty p e = " te x t" size= "3 2 "
onblur="validateLength(l, 32, this, document.getElementByld('message_help'))" />
<span id = "m essage_help" c la ss= " h e lp " > < /sp a n >
~—
Функция v a l i d a t e L e n g t h {) берет значение аргумента
i n p u t F i e l d и проверяет, что это значение имеет (как минимум)
длину, заданную параметром m in L e n g th , но не превышает па­
раметра m ax L en g th . В случае слишком короткого или слишком
длинного значения в элементе h e l p T e x t появится подсказка.
328
глава 7
^
? o fo T T o л T в fo д 7 fл 7 Z 7 к c ^ ^ a
баннера.
формы и проверка данны х
>
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
л
Все поля формы являются объектами JavaScript.
Каждое поле формы имеет свойство fo rm , пред­
ставляющее всю форму в виде массива полей.
Событие o n b lu r возникает при потере объектом
фокуса, и именно оно запускает функцию проверки
Всплывающие окна — не самый лучший способ ин­
формирования пользователей о проблемах с вводом
данных.
Пассивный подход к проверке данных меньше раз­
дражает пользователей.
Свойство l e n g t h указывает на количество симво­
данных.
лов в строке.
Возьми в руку карандаш
Напишите код функции v a l i d a t e L e n g t h ( ) , уделяя особое
внимание передаваемым ей аргументам.
function
/ /
validateLength(minLength,
maxLength,
inputField,
helpText)
{
Смот рим, содержит ли т екст как м и ни м ум m inLength, но не 5ольиле m axLength символов.
/ / С ообщ аем п о л ь з о в а т е л ю о б^оде н & к о р р е к т н ш
.................................
/ / С д а н н ы м и все в п о р я д ке , у б и р а е м п о д с ка зку .
}
далее ►
329
реш ение упражнения
Возьми в руку карандаш
'ешение
function
Вот как выглядит код функции v a l i d a t e L e n g t h ().
validateLength(minLength,
maxLength,
inputField,
helpText)
{
«« больше m axLength символов
П роверяе м к а к
i f (in p u tF ie ld .v a iu e .le n g th < m in L e n g th
in p u tF ie ld .v a lu e .le n q th > m a x L e n a th ) (
..............' 3 ? ^'....................... ..................................................... .......................... v .... л .
т ак и м ини/ / С ообщ аем п о л ь з о в а т е л ю о вводе н е к о р р е к т н ы х данны х
м а л ь н у ю д л и н у ........................................................................................... ............................................................................
вводим ого
,jf,( h e lp T e x t != n u ll)
в поле т е к с т а .'
+■ " i o " + t ^ a x L e n g t h +
c h a ra c te rs in le n g th .";
r e t u r n false;
У ведом ление
0 т о м , чт о
вводим ы й
т екст огр а ничей сверху
г
............................................................................................................
г
................................................................................................
к о л и ч е ст в у
9.
сим волов.
Г
.
б п о р яд ке , у б и р а е м п о д с к а зк у
-п ,, ,
,
,,,
(Г (h e lp T e x t != n u ll)
■
П ри вводе
коррект но­
го т е к с т а
убираем
по д ска зку.
he Ip T e xt. іп п е г Н Т М L =
r e t u r n tr u e ;
I
Проблема с те к сто м решена
Говард может вздохнуть с облегчением. Ведь у него пока нет
денег на покупку большего баннера, поэтому он может решить
проблему только на уровне JavaScript. П о крайней мере теперь
пользователи будут узнавать об ограничении на длину текста до
того, как сделали заказ.
В спом огат ельны й
т е к с т появляет ся
ілри вводе с л и ш к о м
больш ого ко л и ч е ст ва
сим волов.
Enter the banner message: jcet your adventure on with Stick Figure Adventure! Pioase entof a value 1 to 32 characters in length. |
330
глава 7
ф ормы и проверка данны х
Часзцо
З адаваем ы е
В опросы
Чем так плохи всплывающие
окна? Разве большинство
пользователей не понимает, что это не
реклама?
Какую роль играют атрибуты n a m e
и i d при связывании вспомогательного
текста с полем ввода?
! К сожалению, раздражающими
являются любые действия, которые
основан на атрибутах i d / n a m e
связанного с ним поля ввода, но это
заставляют человека прервать свое
занятие, чтобы закрыть появившееся
окно. Именно поэтому мы крайне не
рекомендуем использовать всплывающие
окна при проверке данных.
вовсе не одно и то же. Идентификатор
вспомогательного текста получается из
; Атрибут i d элемента h e l p t e x t
слова t h i s в коде для события
o n b l u r . Объектом является поле или
сама форма?
ID поля ввода добавлением _ h e l p .
Подобная система именования позволяет
создать прозрачную связь между полем
и элементом, отображающим в этом поле
текст подсказки. Хотя выбирать имя для
идентификатора элемента h e l p t e x t
можно и самостоятельно, главное, чтобы
оно было уникальным и корректно
передавалось в функцию проверки.
Q ; Оба ответа верны. В HTML ключевое
слово t h i s ссылается на элемент как
на объект. То есть в случае поля t h i s
это ссылка на объект «поле». Этот объект
обладает свойством f o r m , дающим
доступ к форме. То есть запись t h i s .
f o r m в коде, связанном с событием
o n b l u r , означает ссылку на форму, как
на объект.
Написав t h i s . f o r m в коде
Bannerocity мы получим доступ
к элементу «вспомогательный текст»,
связанному с определенным полем
ввода. Запомните, что t h i s . f o r m —
это ссылка на объект f o r m , который
представляет собой массив со всеми
полями формы. Поэтому для быстрого
доступа к полю с именем
ту_
f i e l d достаточно написать t h i s .
f o r m [ " m y _ f i e l d " ] . Аналогичный
результат можно получить и с помощью
функции g e t E l e m e n t B y l d ( ) , но
продемонстрированный выше подход
является более лаконичным.
Зачем удалять вспомогательный
текст, если проверка показала
корректность введенных данных?
; Назначением вспомогательного
текста является помощь пользователю
при возникновении проблем. Если же
данные введены корректно, проблемы
нет и нет причины для отображения
подсказки. А так как подсказка может
оказаться видимой из-за более ранних
проверок данного поля, в случае когда
пользователь все ввел правильно, имеет
Q * Сценарий будет снова и снова
искать отсутствующий элемент, раскалит
страницу до красна и оставит от браузера
обуглившиеся остатки. Шучу, на самом
деле просто исчезнет система пассивной
помощи пользователям на странице
Bannerocity И вспомогательный текст
перестанет появляться. Это говорит
о необязательности данной функции.
То есть вы можете по желанию убрать
подсказки или вывести их только для
отдельных полей формы.
Если код проверки увидит, что аргумент
helpText имеет значение, отличное
от null, значит, нужный нам элемент
существует и может быть отображен.
Ограничивает ли атрибут size
поля формы длину вводимого
сообщения?
! Нет, HTML-атрибут size
ограничивает только физический размер
поля формы на странице — на количество
вводимых символов он никак не влияет.
К примеру, для поля ZIP code на странице
Bannerocity атрибут size имеет
значение 5, что означает возможность
показа только пяти символов. Но, чтобы
ограничить длину вводимого текста,
потребуется уже атрибут maxlength.
Функция проверки позволяет достаточно
гибко управлять количеством вводимых
символов. Так, в случае с индексами имеет
смысл не только офаничить максимальное
количество пятью, но и проверять,
являются ли вводимые символы цифрами.
Подозреваю, что Говард в один прекрасный
момент захочет это реализовать.
смысл ее удалить.
Что произойдет, если элемента
h e lp t e x t не окажется в числе
аргументов функции проверки?
Б
далее >
331
где т ы ?
Некорректное местополо)кение
Несмотря на все усилия Говарда по проверке вводимых в форму данных,
он снова и снова сталкивается с проблемами при приеме заказов. На этот
раз пользователь ввел неправильный индекс, и Говард несколько часов
летал над совсем другой местностью. Больше всех от этой ошибки постра­
дал Дункан, так надеявшийся на новых потенциальных любителей своих
пончиков.
Еп1ег 2!Р сос1во1т е 1о<я1Ьп;
Введенная заглавная
I ол4есто ц и ф р ы я
была в о с п р и н я т а
к а к циф ра 1 .
О сш сап’з В о п ^ 'З
Я и не мог надеяться на
такую удачу. Баннер Дун­
кана показали над другим
штатом!
Вот так обычная опечатка стала причиной
ошибки ввода данных и привела к полной
путанице. Клиент нечаянно нажал I вме­
сто 9, ведь эти клавиши расположены рядом.
Говард же решил, что I — это 1, и вывесил
баннер совсем в другом месте.
П ом нит е Ф ренки,
к о н к у р е н т а Д ункана.
ГШ ТУРМ
Как проверить правильность ввода
индекса?
332
глава 7
ф ормы и проверка данны х
Н и к а к и х букв.
Проверка индексов
Итак, очередная проблема Говарда связана с неверно вве­
денным индексом. В С Ш А индексы состоят из пяти цифр.
Поэтому для начала следует проверить, чтобы клиент ввел
именно пять цифр — ни больше, ни меньше.
37205
С л и ш ко м
длинный.
робно Пйть
# # # # #
цифр-
о кг
С лиш ком ^
ко ро тки м -
Возьми в руку карандаш
Закончите код функции v a lid a t e Z I P C o d e ( ) , проверяющей
правильность ввода индексов.
function
//
if
validateZIPCode(inputField,
Проверяем
количество
вводимых
)
(
//
if
Если
их
количество
(helpText
не
helpText)
символов.
{
Их
должно
быть
ровно
5
{
совпадает,
показываем
подсказку
!= n u l l )
helpText.innerHTML
=
"Введите
ровно
пять
цифр.";
}
//
Проверяем,
else
//
if
if
что
все
символы
(
Если
являются
)
данные
(helpText
введены
числами
{
некорректно,
показываем
"Пожалуйста,
введите
подсказку
!= n u l l )
helpText.innerHTML
=
число";
}
else
//
if
{
Данные
введены
(helpText
корректно,
убираем
подсказку
!= n u l l )
helpText.innerHTML
=
"";
далее ►
333
реш ение упражнения
Возьми Вруку карандаш
Р рш рц ы р
как выглядит функция v a l i d a t e Z I P C o d e ( ) , проверяющая
корректность ввода индексов.
Д л и н а введенной с т р о ­
ки д о л ж н а с о с т а в л я т ь ^
5 сим волов.
function
■'N.
validateZIPCode(InpLtField,
//
Проверяем
if
{
helpText)
вводимых
символов. Их
in p u tF ie ld .v a lu e .le n g th
!=
{
Если их количество
( h e l p T e x t != n u l l )
не
//
if
количество
h e l p T e x t .i n n e r H T M L
,
=
S
)
совпадает,
"Введите
{
должно
показываем
ровно
пять
быть
5.
подсказку
цифр.";
______ ипАичест во введенных
р ,
}
в о звр а щ а е т ся значение w ise.
//
Проверяем,
else
//
if
if
что
все
символы
Если
данные
(helpText
введены
r e t u r n fa k e ........................ ........
=
~~
}
//
if
числами
■
ф у н кц и я isN aN Q п р о в е р я е т , р а вен ли а р г у м е н т зн а ч е н и ю N a N
(н е -ч и с л о ).
некорректно,
показываем
"Пожалуйста,
введите
подсказку
!= n u l l )
h e l p T e x t .i n n e r H T M L
else
являются
^ ------------( is N a N (in p u tF ie ld .v a lu e )
) {
.........................................................
число";
^
введены с и м в о л ы ,
о т л и ч н ы е о т чисел, во звр а щ а е т ся
значение false.
{
Данные
введены
(helpText
корректно,
убираем
подсказку,
!= n u l l )
helpText.innerHTML
=
Показанная выше функция не универсальна.
Больш е
I
осш орож ны !
334
глава 7
Например, она не подходит для проверки индексов других стран.
Существуют страны, в которых индексы составлены не толь­
ко из цифр, но и из букв. Более того, американские индексы
в полной форме состоят из 9 цифр и имеют вид #####-####. На­
личие дефиса делает индекс нечисловым.
ф ормы и проверка данны х
А что произойдет, если клиент не будет обра­
щать внимания на вспом огательны е сообщения? Будет
л и заполненная и м форма с данным и все равно отправ­
лена на сервер?
Некорректные данные отправляться не должны.
В конце концов, зачем нужен код проверки, если
пользователь все равно может отправить неверно
введенные данные? На странице Bannerocity пока что
отсутствует процедура проверки информации перед
отправкой содержимого формы, а значит, не исключе­
на вероятность дальнейших ошибок.
П р оверка к о р р е к т н о с т и не и м е е т
с м ы с л а , если п о л ьзо ва т е л ь и м е е т
в о з м о ж н о с т ь п р о и г н о р и р о в а т ь все
п р е д у п р е ж д е н и я и все р а вн о о т п р а в и т
оанные.
о
gantieroclw -
b
a
n
n
e
r
o
c
i t
y
/
Pfease m tera value 1 to 32 chemoter$ in length.
Enter the banner message: |
ptease enter exsclly ffve dftte.
Enter ZIP code of the tocatton:
Enter the date (or the message to be shown:
"
"
Enter your nanne; |
Enter your phone number: j
Явз8в enter a value,
nsase enter a vatas.
_
' Please enter a value.
Please enter в value.
Enter your emaB address: |
Order Banner
Самы е уст о й чи в ы е
п р и л о ж е н и я на всякий
сл уч а й п р о в е р я ю т д а н ­
ные еще и на сервере.
Н у ж н о , чт обы щ е л ч ­
к о м на к н о п ке O r d e r
B anner от правит ь
м о ж н о было т о л ь ко
к о р р е к т н ы е данные.
У
Таким образом, странице Bannerocity требуется еще
одна функция, которая будет проверять все поля фор­
м ы перед отправкой данных на обработку. Эту функцию
placeOrder () м ы свяжем с кнопкой Order Banner, и имен­
но она будет осуществлять финальную проверку.
< in p u t t y p e = " b u t t o n " v a lu e = " O r d e r B a n n e r" o n c l i c k = " p l a c e O r d e r ( t h i s . f o r m ) ; "
/>
далее >
335
сделай заказ и удостоверься
|J o A j3 o g H o о « ф у н к ц и и
f la c e O r J e r ( )
8 ка че ст ве а р г у м е н т а ф у н к ц и и
п е р е да е т ся о б ъ е к т fo r m , ч т о
дает ей д о с т у п к полям ф о р м ы ,
^ элем ент ам n Z t Z o K
о сущ е ст в л я е т ся ч е Т е Т
^ ^ ъ е к т fo r m п о и н й к с а м
м а сси ва .
function placeOrder(form
if
( v a l i d a t e L e n g t h (1,
32,
f o r m [" m e s s a g e " ],
f o r m ["message _ h e l p "
v a l i d a t e Z I P C o d e ( f o r m [ " z i p c o d e " ] , f o r m [ " z i p c o d e _ h e l p " ] ) &&
v a l i d a t e N o n E m p t y ( f o r m [" d a t e " ],
f o r m [" d a t e _ h e l p " ))
&s
v a l i d a t e N o n E m p t y ( f o r m [" n a m e " ] , f o r m [ " n a m e _ h e l p " ] ) s&
v a l i d a t e N o n E m p t y ( f o r m [ " p h o n e " ],
f o r m [" p h o n e ^ h e l p " ])
v a l i d a t e N o n E m p t y ( f o r m [ " e m a i l " ] , f o r m [" e m a i l _ h e l p " ]))
// О т п р а в к а з а к а з а на с е р в е р
{
__
a l e r t ("Простите,
{
М е т о д 5иЬ т И () вы зы вает ся
для о т п р а в к и данны х на сервер
т олько при полож ит ельном
р е з у л ь т а т е п р о в е р ки .
f o r m . s u b m i t ();
else
SS
В о л ь ш у ю ч а с т ь т ел а
ф у н кц и и з а н и м а е т
_ больш ой о п е р а т о р
' if/e ls e , вы зы ваю щ ий
ф у н к ц и ю п р о в е р ки
для ка ж до го из полей
ф ормы .
но ф о р м а з а п о л н е н а неверно")
в в о д н е к о р р е к т н ы х данны х яв­
л я е т с я д о с т а т о ч н о зн а ч и м о й
п р о б л е м о й , чт обы о п р а в д а т ь
появление всплы ваю щ его окна.
_
Чаапо
^аД аБ аеМ ы е
Bonj>oCbi
Каким образом функция p l a c e O r d e r () управляет
отправкой данных формы на сервер?
3 * Вы же говорили, что не стоит пользоваться
всплывающими окнами при проверке данных...
; Оператор i f / e l s e в теле функции структурирован таким
образом, что при обнаружении некорректных данных в любом из
В большинстве случаев это действительно так, потому
что пользователю в результате приходится прервать процесс
заполнения формы, чтобы прочитать сообщение и щелкнуть на
кнопке ОК. Но щелчок на кнопке Order Banner осуществляется
только после завершения ввода данных. И попытка отправить
некорректно заполненную форму является достаточно
веской причиной для появления всплывающего окна
с предупреждением.
полей будет запущен оператор e l s e , вызывающий функцию
a l e r t ( ) . Если же проверка всех полей покажет корректность
введенных данных, будет вызван метод s u b m i t () объекта
fo r m , который и отправит данные на сервер. То есть
отправка информации зависит от того, будет ли вызван метод
s u b m i t ( ) . Он является эквивалентом кнопки submit в языке
HTML.
336
глава 7
S
формы и проверка данны х
Проверка Времени
к сожалению, проверка корректности ввода индексов принесла Го­
варду только временное облегчение, потому что практически сразу он
столкнулся с новой проблемой. Теперь он показал баннер в нужном
месте, но в другой день, так как что-то произошло с введенной датой...
Enter thedate for the message to be shown: |05/1o/2008
Еще один не
довольны й
кл и е н т .
далее ►
337
проблемы с датой
Проверка даты
Говард понял, что недостаточно проверить, ввел ли пользователь
дату, следует также удостовериться, что дата была введена кор­
ректно. Для этого нужно выбрать формат даты. Например, пусть
сначала двумя цифрами обозначается месяц, потом двумя цифра­
ми — день и наконец четырьмя цифрами — год.
ММ/ДД/ГГГГ
Месяц^ Как и день,
одозначается
двумя цифрами.
ф рагм ент ы
. даты отделены
друг о т друга
косой чертой.
Пусть год обозначается ч е- м ы р ш я символами... мы же не
х о т и м ст олкнут ься с п роб ле­
мой 3 0 0 0 года!
>
Е м егІІ,еаа8Іі,,і|,ет.5м ;і.1о в,
I
Выбор формата даты — это самая простая часть задачи. Намного слож­
ней реализовать процедуру проверки на соответствие этому формату.
Существуют функции, позволяющие разделить строку на части, исполь­
зовав в качестве разделителя какой-либо заранее выбранный символ,
например косую черту. Н о такая задача слишком сложна. Ведь придется
сначала поделить строку на фрагменты, а затем удостовериться, что каж­
дый фрагмент содержит только цифры и имеет заданную длину.
Вот как эта процедура будет выглядеть пошагово:
©
О
А
Разобьем значение поля на набор строк, использовав
в качестве разделителя косую черту.
"05"
Убедимся, что первая строка состоит из двух симво­
лов, и это — цифры.
"05"
Убедимся, что вторая строка состоит из двух симво­
лов, и это — цифры.
Убедимся, что третья строка состоит из четырех сим­
волов, и это — цифры.
338
глава 7
символа сост ав­
л я ю т число... ОК.
"1 о " ф
символа, но
эт о не число!
"2008"
О
Проигнорируем все данные после второй черты.
с точки зрения написания кода такая последовательность выгля­
дит достаточно просто, но проверить повторяющийся несложный
шаблон можно и еще более простым способом.
"2 0 0 8 "
"1о"
__ Четыре символа
сост авляю т число...
0
ОК.
-Н ет данных.
формы и проверка данны х
А вот если бы даты можно было прове­
рять без разделения на строки... Мечтать
ведь не запрещено?
далее *
339
разве вы не слыш али этого выражения?
Регулярные выра)кения не «регулярны»
в JavaScript имеется такой мощный инструмент, как регулярные выра­
жения, созданный специально для поиска в текстах совпадений с вы­
бранным шаблоном. В ы создаете шаблон и применяете его к строке, ища
совпадение, точно так же, как в полиции проводят опознание подозревае­
мых... впрочем, вы работаете с более сговорчивыми объектами!
С ов падение!
Высокий, без очков, короткие волосы
Регулярные выражения
используются для поиска
совпадений в тексте.
340
глава 7
Ш аблон сост оит
из п еречня ф и зи ч е ­
ских ха р а кт е р и ст и к
вн е ш н о ст и человека.
С
Шаблон описывает физические свойства, которые затем
рассматриваются в приложении к реальным людям. Регуляр­
ные выражения позволяют делать то же самое со строками.
ф ормы и проверка данны х
Задание шаблона
Если при опознании в полиции используют шаблон
с перечнем физических характеристик внешности чело­
века, текстовые шаблоны включают в себя определен­
ную последовательность символов, например набор из
пяти цифр подряд. Именно так выглядит американский
индекс.
Шаблон
-у
Совпадение!
"37205"
" 5 2 80"
”А 3492"
"741265"
"0070В"
Слишком, много символов.
Содержит буквы.
К сожалению, превратить состояш,ий
из пяти цифр индекс в регулярное
выражение не так-то просто. Ведь
для описания шаблонов используется
компактный и на первый взгляд совер­
шенно непонятный синтаксис. Сразу
и не догадаешься, что такое выражение
означает всего лишь состоящий из пяти
цифр индекс:
А ну тихо! Я пытаюсь
разглядеть шаблон...
^
Шаблон представ­
ляет собой п о ­
следовательность
из пяти цифр.
Слиш ком ЛЛйЛО
символов.
Содержит
буквы.
= #####
Э т о т символ
обозначает начало
входных данных.
, Цифровой символ
должен повторяться
S раз.
ч/
Шаблон
/■ '\< Ц 5 }$ /
Все регулярные
выражения начи-^_
наются и закан­
чиваются косой
чертой.
Г
Цифровой
символ.
Э т о т си м во л
указывает на
коней, ввода.
Н е волнуйтесь, если вам кажется,
что в ы ничего не понимаете.
М ы еще не раз будем возвращаться
к этому шаблону.
далее ►
341
анализ регулярного выражения
Структура регулярного Выра}кения
Регулярное выражение напоминает строковый литергш, но в от­
личие от последнего не заключается в кавычки или в апострофы,
а начинается и заканчивается косой чертой (/ /).
Выраж ение
Регулярное выражение
начинается с косой черты
и заканчивается ею.
ш
Регулярные выражения
располагаю т ся между
абумя косыми черт ам и
Тело регулярного выражения состоит из набора так называемых
метасимволов, которые вместе с буквами и цифрами формируют
лаконичный, но исчерпывающий щаблоп. Для создания рабочих
шаблонов вовсе не обязательно знать все нюансы «языка». Доста­
точно запомнить самые распространенные метасимволы:
э т о всего
л и ш ь т о ч ка .
Обозначает любой
символ, кроме перево­
да строки.
\< 1
Обозначает любую
цифру.
\ з
К т а ки м сим волам
о т н о с я т с я п робелы ,
т а б у л я ц и я , зн а ки
перевода с т р о к и
и т . п.
Обозначает символы
пробела.
, М н о ги е м е ­
т асим волы
начинаю т ся
с обрат ной
косой черт ы .
Перед э т и м с и м ­
Символ обозначает на­ волом м о ж е т р а с ­
полагат ься т о л ь ­
чало ввода данных.
ко ко са я че р т а .
\w
Обозначает любой
символ латинского
алфавита.
Символ конца
ввода данных.
М ы постарались дать как можно более исчерпывающие опи­
сания метасимволов, но их назначение станет еще более по­
нятным в процессе практического составления шаблонов...
342
глава 7
После эт о го си м во л а
м о ж е т на хо ди т ься
т о л ь ко косая че р т а.
ф ормы и проверка данны х
Метасимволы
/ \ w /
О д и н сим вол.
о д н а буквл
д а и А и н с ко г
аА ф лвы т а-
/\d/<e
О дна ц и ф ­
р а в начале
ст роки.
Л
Метасимволами называют­
ся символы, используемые
для написания регулярных
выражений.
О д н а циф ра.
в регулярных выражениях один символ можно обозначить
разными способами. А как быть со строками из нескольких
символов? Давайте посмотрим на примеры таких строк:
/cat$/
[буквосочет ание \
« c a t» в конце
ст ро ки...нигд е
не п о п а д а е т ся!
/\d /
"2 n ite "
Д б е циф р»!
в конце
с т р о к и .^
"c a t c h 2 2 "
/\d\d$/
" 007"
Т р и циф ры
подряд.
О дна ц и ф ­
ра в начале
ст роки.
1 ^ с ,з Х .1
\ " / d /
/\d\d\d/
'
нение
б у кв о с о ч е т а н и е « с а 1»
о начале с т р о к и .
Напишите регулярное выражение для полного американского индекса,
который имеет форму # # # # # - # # # # и должен появляться отдельно.
далее >
343
реш ение упражнения
-
Вот как выглядит регулярное выражение для полной формы американского
индекса # # # # # - # # # # ,
•Р тЖ е н и е
решение
Э т о т си м во л
ст авит ся в к о н -
Э т о т си м во л
ст авит ся в и а чале с т р о к и .
ст роки.
В конце регуляр но го в ы ­
р а ж е н и я с т а в и т с я еще
одна косая че р т а .
^
Р егулярное
л
вы р а ж е н и е — ^
начи н а е т ся
с косой ч е р т ы
Т а к о б о зн а ча ю т ся
п я т ь ц и ф р подряд.
Д е ф и с в да н н о м с л у ­
чае не и м е е т особого
значения... О н всего
ли ш ь р а зд е л яе т две
ч а с т и индекса.
,Т а к о б о зн а ч а ю т ся ч е i^ b ip e ц и ф р ы подряд.
Количество повторений
в регулярных выражениях любой текст, не относящийся к метасимволам,
проверяется на совпадение. Это означает, например, что последовательность
символов /howard/ совпадает с текстом «howard» в произвольной части
строки. Кроме того, существуют метасимволы, задающие количество повто­
рений. И х называют квантификаторами.
Л П редш ест вую щ ий
с и м в о л не обязат елен
и м о ж е т п о являт ься
Предшествующий
символ должен совпасть пр о и зво льн о е число
раз.
{Л }
Предшествующий
шаблон должен
появиться ровно
п раз.
ноль или более раз.
Управляет числом п о ­
явлений илаблона.
Предшествующий
Предшествующий
символ должен совпасть
один или более раз.
с и м в о л обязат елен
и м о ж е т появлят ь­
ся п роизвольное
число раз.
П редш ест вую щ ий
------ —э л е м е н т не о бяза ­
т е л ен , но п о я в и т ь с я
м о ж е т т о л ь к о один
Предшествующий
элемент может как при- Р‘^3.
сутствовать, так и отсут­
ствовать.
344
глава 7
Т ехнически э т о не
квант иф икат ор.
С кобки и с п о л ь з у ю т с я
для г р у п п и р о в к и о т ­
дельны х сим волов.
о
Группирует символы
и (или) метасимволы
формы и проверка данны х
Повторение шаблона
Квантификаторы
задают количество
повторений шаблона.
Квантификаторы позволяют сделать регулярные выражения
более краткими. Теперь вам не требуется в явном виде писать
все символы, достаточно указать, сколько раз их следует по­
вторить. Вот как будет выглядеть шаблон для полной формы
индекса после записи с использованием квантификаторов:
К вант иф икат ор {}
избавляет от н е ­
обходимости писат ь
все цифре?!.
Метасимволы и квантификаторы позволяют создавать регуляр­
ные выражения для любых сочетаний, которые могут появлять­
ся в строках.
/ • + /
/ ( H o t ) ?
? D o n u ts /
/ \ у г * /
Совпадает с произвольны м
количест вом а лф авит н оцифровых символов, оклнзчая п ус т ую ст року.
Любой сим вол должен
появит ься один или
более раз... совпадает
с непуст ой строкой.
Совпадает с выражением
« p o n u ts » или « H o t Ропиг$».
Укажите назначение перечисленных слева метасимволов
и квантификаторов.
Символ указывает на конец строки.
\w
Предшествуюш;ий символ обязателен и мо­
жет появиться произвольное число раз.
$
Означает любой алфавитноцифровой символ.
\с1
Означает любой символ, кроме пере­
носа строки.
-I-
Означает любую цифру.
*
Предшествующий символ не обязателен
и может появиться произвольное число раз.
далее ^
345
спросит е прямо сейчас
КТО
Вот какое описание соответствует каждому из указанных
в левом столбце метасимволов и квантификаторов.
Символ указывает на конец строки.
Предшествующий символ не обязателен
и может появиться произвольное число раз.
Означает любой алфавитноцифровой символ.
Означает любой символ, кроме пере­
носа строки.
Означает любую цифру.
Предшествующий символ обязателен и мо­
жет появиться произвольное число раз.
_
Часщо
^аД аБ аеМ ы е
Б о ц |э о с :ь 1
Регулярное выражение — это
строка?
• Как найти в тексте знак доллара?
; Как и в случае со строками,
в иауаЗспр! специальные символы
выделяются обратными косыми чертами.
Q ; Немножко терпения. Скоро
вы попрактикуетесь в применении
регулярных выражений. Они
нужно написать символ $ как \ $ .
Аналогичное правило действует для
прочих специальных символов, например
действительно очень удобны для
проверки данных сложных форматов,
например дат или адреса элекгронной
почты. В форме Bannerocity еще
много нуждающихся в проверке полей,
для части которых вам потребуются
регулярные выражения.
Можно ли применять регулярные
выражения к другим типам данных?
таких, к а к * и +. Все прочие символы
помещаются в регулярное выражение
в своем обычном виде, без всякого
А каким образом в JavaScript
используются регулярные выражения?
0 ? Нет, регулярные выражения были
созданы специально для поиска заданных
шаблонов в текстовых строках. Но это не
дополнительного форматирования.
! Нет. Регулярное выражение можно
считать описанием строки или ее части.
Регулярные выражения тесно связаны
со строками и ищут в них указанные
пользователем текстовые шаблоны, но
строками они при этом не являются.
умаляет значения данного инструмента,
позволяющего искать в текстовых строках
самые разные варианты шаблонов.
346
глава 7
Соответственно, для указания на знак
доллара в регулярном выражении
Имеют ли регулярные выражения
отношение к проверке данных? Ведь
мы заговорили о них в теме про
проверку ввода дат.
Ql
1\Лы дойдем и до этого, честное
слово! Регулярные выражения
в JavaScript представляются в виде
объектов, снабженных набором
необходимых для функционирования
методов.
ф ормы и проверка данны х
М Л С Т Ё Р Ш Л Б1л«Й Ж В
Интервью недели:
З ага д о ч н ы е , но м о щ н ы е
р егул яр н ы е в ы р аж ен и я
Head First:Я много слышал о вашей способно­
сти находить в тексте указанные шаблоны. Это
действительно так?
Head First: Кажется, я понял, что вы имеете в
виду. Шаблон — это описание текста, которое
может появиться в строке, но не сам текст?
Регулярное выражение: Да, я своего рода рас-
Регулярное выражение: Именно так. Пред­
ставьте, что я прошу вас дать мне знать, когда
пройдет человек, высокий, с короткими воло­
сами и без очков. Это же описание человека,
а не он сам. Как только появится парень Ален,
подходящий под это описание, м ы скажем, что
шаблон совпал. Н о под описание могут попасть
и другие люди. Без шаблонов м ы не смогли бы
проверять, подходит ли человек под описание.
Так что разница между методом in d e x O f ()
и мной в том, что он ищет Алена, а я высокого
человека, с короткой стрижкой и без очков.
членитель кода, способный, взглянув на строку,
сразу обнаружить нужный шаблон. Меня можно
использовать даже в ЦРУ... Н о они не отвечают
на мои звонки.
Head First:Хотите ловить шпионов?
Регулярное выражение: Нет, я просто л ю ­
блю отыскивать шаблоны. Дайте мне какие
угодно параметры, и я тут же их найду, ну или,
по крайней мере, сообшу, что совпадений не
обнаружено.
Head First:А разве метод i n d e x O f {) объекта
S t r i n g не делает то же самое?
Регулярное выражение: Этот любитель даже
не представляет, что такое работа с шаблонами.
Нет, если вам нужен простейший механизм по­
иска, который, к примеру, ищет в строке слово
« lam e», метод i n d e x O f () вам поможет. Н о
в более серьезных случаях он бессилен, так как
не умеет анализировать строки.
Head First: Н о разве поиск по строкам не явля­
ется поиском шаблонов?
Регулярное выражение: Разумеется. Дойти
до почтового ящика — это тоже физическое
упражнение, но что-то его не включают в про­
грамму Олимпийских игр, по крайней мере
пока. Так и обычный поиск. В ы ищете совпаде­
ния простейших шаблонов — статических слов
или фраз. А теперь представьте, что требуется
найти дату или адрес URL. Такие запросы хотя
и имеют строковый формат, но не являются
статическими.
Head First:А каким образом ваши способности
могут применяться для проверки данных?
Регулярное выражение: Такая проверка
выполняется именно на соответствие опреде­
ленному, заранее заданному формату. Так что
я беру шаблон и смотрю, подходит ли он к дан­
ным. Положительный результат означает, что
данные введены корректно.
Head First: Регулярных выражений должно
быть очень много?
Регулярное выражение: Конечно. И именно
эта часть моей работы требует наибольшей
сосредоточенности — написание регулярного
выражения, описывающего очередной формат.
Head First: Большое спасибо, что рассказали
про вашу роль в проверке данных.
Регулярное выражение: Нет проблем. Я при­
вык объяснять... Думаю, это мой поведенческий
шаблон.
далее *
347
проверка при помощ и регулярны х выражений
Проверка данных при помо1ци
регулярных Выраукений
Давайте перестанем создавать регулярные выражения просто для
того, чтобы посмотреть, как они работают, вернемся к полю для
ввода дат на странице Bannerocity и поможем Говарду с заказа­
ми. В JavaScript регулярные выражения представлены объектом
R e g E x p , который снабжен методом t e s t {). Именно этот метод
и проверяет соответствие нужному нам шаблону.
Метод test() объекта
RegExp проверяет
наличие в строках
заданного шаблона.
Э т о р е гуля р ное
вы раж ение для
индекса из п я т и
циф р.
Д анны й лит ерал авт ом ат ически
создает о б ъ е к т RegEx.
,В ка че ст ве ахр гум е нт а
м е т о д и п е р е да е т ся з н а чение,, введенное в поле.
var геаех = /^\d{5}$/;
if (!regex test{inputField.-value))
/ Индекс
Если м е т о д te s t()
в о звра щ ае т значение
Ш 5 е , з н а ч и т , данные
не п р о ш л и п р о в е р ку .
введен
V
неверно!
М е т о д te s to вы зы ­
вает ся о б ъ е к т о м
RegEx.
М е т о д te s t o в о звр а щ а е т
значение tr u e п р и с о в п а ­
дении с ш аблоном .
Метод t e s t () можно вызвать для каждой из функций проверки,
но м ы предпочтем создать обобш;енную функцию на основе регу­
лярных выражений. Присвоим ей имя v a l i d a t e R e g E x (). Вот как
выглядит принцип ее работы:
Проверяет, совпадают ли переданные ей в качестве
аргументов шаблон и строка.
При совпадении присваивает подсказке переданный
ей в качестве аргумента текст и возвраш;ает f a l s e .
validateRegEx(regex,
В случае несовпадения удаляет подсказку и возвраща­
ет значение t r u e .
Осталось только написать код этой функции. Большая его
часть уже попадалась нам в составе других функций провер­
ки, чем м ы и воспользуемся.
348
глава 7
inputStr,
helpText,
help№ssage) ;
формы и проверка данны х
----------- --------- — ------
■
fu n c t i o n validateRegEx(regex,
// п р о в е р и м к о р р е к т н о с т ь
// Д а н н ы е
некорректны,
if (helpText != null)
.{
r e t u r n false;
if
«»»е
h e lpMessage)
I
^
задал
^
helpText. i n n e r H T M L = helpMessage;
"Г /
hllpText,
д а н н ы х ^ ^ п р ^
(iregex.tes
0
. e g e x . t e stt((ii n ppuut St bt rt r)n)
if
'■
xnputStr,
В качестве а р г у ­
м ент ов передаю т ся
регулярны е вы ра­
жения, данные ввода,
т екст и элем ент
подсказки.
Н есоот вет ст вие
условию означает
некоррект ност ь дан­
ных, поэт ом у о т о ­
бразим подсказку.
Регулярное выраже­
ние сравнивается
с данными ввода.
» р р -» » “ '
(helpText
!= null)
helpText. i n n e r H T M L =
r e t u r n true;
Если проверка пройдена,
т е кс т подсказки исчезает.
)
Возьми в руку карандаш
Напишите код функции v a l i d a t e D a t e ( ) , которая для проверки
введенной в поле на странице Bannerocity даты использует функции
v a l i d a t e N o n E m p t y ( ) и v a l i d a t e R e g E x ( ) . Подсказка: у этой
функции два аргумента — данные ввода и элемент со вспомогатель­
ным текстом.
далее *
349
реш ение упражнения
Возьми В руку карандаш
Решение
Вот как выглядит функция v a l i d a t e D a t e ( ) , которая
для проверки введенной в поле на странице Bannerocity
даты использует функции v a l i d a t e N o n E m p t y ()
и v a l i d a t e R e g E x ().
Сначала функция
v a lid a t e N o n E m p t y ( )
проверяет , чт о поле
не являет ся пуст ы м.
function validateD ate(jn^utFieid, helpText) {
// Проверяем, введены ли данные в поле
if (Jva(idateN onEm pty(inputFie!d, helpText))
Ф ун кц и и
регулярное
—
вы раж ение для
дат ы .
/ / Проверяем, являю т ся ли эт и Эйнн\(е датой
re tu rn va lid a teR eg E x (/'^\d iZ }V \d {Z }\/\d {4 -}$ /, inputField.vaiue, kelpText,
^
"Пожалуйста, Ь в е а и т ^ а т у (н априм ерТ ^^ЇТ Ч Л /І й 75).");
}
Так как косая черт а являет ся
м ет а си м во лом , ее заклю ча­
ю т между обратными косыми
черт ами.
Для задания выражения ф орм ат а М М /
Д Д /Г Г Г Г использую т ся как м е т а с и м ­
волы, т а к и квант иф икат оры .
А почему бы не
допустить ввод года
в виде только двух
символов?
¥
И нт ересно, будут
ли пользоват ься
ваш им сценарием
в Z 1 0 0 году?
Проблема 2100 года еще так далеко...
Учитывая, что до следующего рубежа веков еще очень много
времени, наверное, можно позволить пользователям вводить год
в виде только двух цифр. Вряд ли какой-то из написанных в наши
дни сценариев JavaScript проживет 90 лет и столкнется с пробле­
мой. Говард сначала хотел для надежности в Bannerocity вводить
год в виде четырех символов, но потом решил, что, если его де­
тище и доживет до следующего века, тогда и можно будет внести
в него исправления.
350
глава 7
формы и проверка данны х
Часзцо
З ад аваем ы е
вызывать функцию v a lid a t e N o n E m p t y ()
Бвнутри
: Зачем
функции v a l i d a t e D a t e () ? Разве регулярные
А что, если я хочу написать сценарий с учетом
треї
требований завтрашнего дня. Это сложно?
выражения не умеют работать с пустыми полями?
О
0:
; Да, регулярные выражения умеют проверять наличие
I Вовсе нет. Предвосхищение будущих требований
и написание кода с их учетом обычно не является проблемой.
или отсутствие данных, поэтому упомянутую вами функцию
можно удалить. Однако, проверяя, были ли введены данные,
и отображая соответствующий вспомогательный текст, мы
В случае с Bannerocity мы учтем будущие требования, оставив
ввод года в виде четырех символов. Профессиональные
программисты позволяют пользователям вводить только две
делаем страницу интуитивно понятной для пользователей.
Отсутствие данных и ввод некоррекгных данных должны
последние цифры, добавляя первые две в тексте сценария.
В результате данные, вводимые в форму, все равно будут
храниться в виде четырех цифр.
сопровождаться разными подсказками. Именно на этом принципе
работает наша система помощи, позволяющая пользователю
понять, как именно следует заполнять форму. И ради этого
маленького усовершенствования можно написать несколько
дополнительных строчек кода.
Диапазон Вхо}кдений
Квантификатор {} используется для указания коли­
чества появлений шаблона в строке. О н может запи­
сываться и в другой форме, уже с двумя аргументами,
определяющими минимально и максимально возможное
количество повторений шаблона. Это дает еще один до­
полнительный инструмент настройки:
{ m i n ^ т а х ]
Предшествующий шаблон
должен появиться как ми­
нимум min раз подряд, но
не больше, чем max раз.
ММ/ДД/ГГГГ —
не единствен­
)у д ь те
I ный возмож­
0 СІЦ 0|> 0 Ж Н ь і!
ный формат
дат.
В ряде стран более привыч­
ным является указание дня, а
только затем месяца, то есть
запись производится в форма­
те ДД/ММ/ГГГГ
У казы вает ^ с ко л ько р а з
ш аблон м о ж е т п о я ви т ься
как м и н и м у м и как м а к ­
сим ум -
Некоторые пароли позволяю т вво­
дит ь от пят и до восьми буквенноцифровых сим волов, чт о за м еча ­
т ельно описывается при помощ и
коант иф икат ора {}.
возьми в руку карандаш
Перепишите регулярное выражение из функции v a l i d a t e D a t e ()
таким образом, чтобы оно позволяло ввод года как в виде двух, так
и в виде четырех цифр.
далее ►
351
реш ение упражнения
Возьми в руку карандаш
'^ о т о ш л а
бШсНИб
выглядит регулярное выражение из функции v a l i d a t e D a t e ( ) ,
позволяющее вводить год как в виде двух, так и в виде четырех цифр.
В т аком виде
квант иф икат ор {}
задает миним альное
и М аксимальное к о ­
личест во циф р при
оводе года.
То есть получается, что код провер­
ки позволяет вводить год тремя цифра­
ми? Это же лишено смысла...
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
Регулярное выражение для
даты дейст вит ельно ПО ~
зволяет ввест и в конце
т олько т ри цифры!
Ente the date for the message to be shown; [03/01/200
Регулярное выражение
совмещает шаблон с тек­
стом строки.
L
Кроме обычного текста
в регулярных выражениях
используются метасимво­
Никакие ревизионисты не
помогут вернуть JavaScгipt во
времена до десятого века.
Соответственно, нам нет ника­
кого смысла поддерживать ввод
года в виде трех цифр. Убрав эту
возможность, вы уменьшите коли­
чество потенциальных проблем
в бизнесе Говарда.
лы и квантификаторы.
В JavaScript регулярные
выражения поддержива­
ются объектом R e g E x p ,
но обычно создаются
в виде литералов.
Метод t e s t {) объек­
та R e g E x p проверяет
заданный регулярным вы­
ражением шаблон на соот­
ветствие строке текста.
352
глава 7
формы и проверка данны х
Выбери это... или т о
Другим полезным метасимволом для построения регулярных выражений
является перечисление. П о своему виду и функциональности перечисление
напоминает оператор ИЛИ. Но, в отличие от этого оператора, для записи
перечисления используется всего одна вертикальная черта |,разделяющая
допустимые варианты. Другими словами, шаблон считается совпавшим при
соответствии одному из двух указанных выражений.
это\ то
Шаблон совпадает при
совпадении с одним из
указанных вариантов.
М ет асим вол перечисления
позволяет реализовы ват ь
выбор из двух альт ернат ив.
/ s m a l l I m e d ii im | l a r g e /
/ ( r e d Ib lu e )
p ill/
Это выражение
совпадает как со
'ст р о ко й « re d рЩ»,
т ак и со ст рокой
«blue pill».
Волге сложные
вариант ы выбора
реализую т ся при
помощ и набора
перечислений.
далее *
353
это действительно ваш номер?
Возьми в руку карандаш.
IX
'ешение
Вот как выглядит регулярное выражение из функции
v a l i d a t e D a t e ( ) , совпадающее только со строками из двух или четы­
рех символов.
М ет асим вол перечисления ( )
задает шаблон для ввода года
как 6 виде двух, т ак и в виде
чет ы рех цифр.
Никаких случайностей
Говарду очень понравился новый, надежный способ проверки
дат, обеспечивающий точное следование заданному шаблону. И он
решил воспользоваться регулярными выражениями для проверки
корректности ввода данных и в двух оставшихся полях формы
Bannerocity: номер телефона и адрес электронной почты.
прекрасно... но
gantïerocity - P ersonateed Online S ^ S w n e f ^
# 0 в
я хочу большего!
b a n n e r o c i t y
^Vlandariga .. MecTa
Enter th e b an n er m essag e:
Enter ZIP co d e of the tocatton: jl 0012
Mano!
________ __
Enter th e d ate for th e m ess a g e to b e show n: j 03/11 /200 ' » « « «
Enter youf nam e; j
Enter your phone nym ber;
j
___ _________ _____
Enter your em ail ad d ress; j
Order Banner
Done
Вводимые пользоват елям и даты
т еперь проверяю т ся при п о м о ици регулярны х выражений, чт о
обеспечивает ст рогое следование
ф орм ат у.
Идея Говарда о необходимости проверки вводимых телефонов
и адресов электронной почты вполне здравая, но для ее реали­
зации нам потребуются новые регулярные выражения.
354
глава 7
m/14/1976}
^
1
ф ормы и проверка данны х
Вы меня слышите?
Проверить корректность ввода телефонных номеров достаточно
просто, так как они записываются в достаточно строгом формате.
Разумеется, без регулярных выражений нам пришлось бы стол­
кнуться с необходимостью деления строк, но нам этого делать не
придется. Американские телефонные номера строятся по следую­
щему шаблону:
Шаблон
= # # # -# # # -# # # #
Так как Говард не со ­
бирается предлагат ь
свои услуги ииост ран■цам . можно ограничит ься
ам ериканским ф орм ат ом
т елеф онны х номеров.
Заменим дефисы косыми чертами и укажем, из скольких
цифр состоит каждый фрагмент. Получившееся регуляр­
ное выражение имеет практически такой же формат, как
и в предыдущем случае.
Шаблон для даты был
создан при помощ и м е ­
т асим вола \с1 и кван­
т иф икат ора {},
Шаблон для номера т елеф она
от личает ся от шаблона для даты
наличием дефисов, разделяюи^их
группы цифр.
Благодаря регулярным выражениям и функции validateRegEx ()
написать код функции validatePhone (), проверяющей номер
телефона, несложно.
function validatePhone(inputField,
// Проверяем,
helpText)
{
бьши ли введены данные
if (!validateNonEmpty(inputField,
helpText))
return false;
// Проверяем,
являются ли данные номером телефона
return validateRegEx(/''\d{3}-\d{3)-\d{4}$/,
inputField.vaiue,
helpText,
"Пожалуйста, введите номер телефона
(например,
123-456-7890).");
далее >
355
это .сот или .огд?
Вам письмо
Теперь, когда функция проверки номера телефона готова,
у Говарда осталась только одна забота. Проверить коррект­
ность ввода адресов электронной почты в форму Bannerocity.
Как и раньше, м ы начнем решение этой задачи с написания
регулярного выражения.
Шаблон
Zj 3 или 4
а лф а ви т н о цифровых символа.
LocalName^DomainPrefix.DomainSuffix
....
Все выглядит не так уж страшно — адрес электронной почты
представляет собой всего лишь три текстовых фрагмента,
которые могут быть составлены из букв латинского алфавита
и цифр, а также символа (0) и набора точек.
_
Здесь могут бстрецаться как буквы,
т ак и цифры.
Все эт и адреса подходят
под шаблон. Значит , дело
сд&Айно... или вce~^л^aкы
неилр
howard0bannerocity.com
sales@duncansdonuts.
puzzler0youcube.са
Создание шаблона для адреса электронной почты является не­
сложным процессом.
А дрес должен начинаться
Ч/
с одного или нескольких
/^ \w + (i\w + \
буквенно-циф ровы х с и м \ •\
волов.
Шаблон кажется вполне рабочим. Оста­
лось понять, всегда ли адреса электрон­
ной почты записываются именно
в таком формате.
2
г
}
Так как точка входит в число
. специальных сим волов, ее
следует п о м ест и т ь между
обрат ными косыми черт ам и.
41Й/
/ /у/
•После символа @ появляет ­
ся еще один или несколько
буквенно-циф ровы х сим во­
лов.
В конце адреса
элект ронной почт ы
должны ст оят ь 2., 3
или 4 а лф а ви т н о цифровых символа.
Ш ТУРМ
Возможны ли другие варианты шаблона
для адреса электронной почты? Вспомни­
те, какие еще адреса вы видели.
356
глава 7
ф ормы и проверка данны х
исключение — это праВило
Адреса электронной почты более сложны, чем это кажется
на первый взгляд. При написании нами шаблона необходимо
учесть существование других вариантов написания адреса
электронной почты. Вот примеры совершенно корректных
адресов:
cube
lovers@youc\3be
aviator.howard0bannerocity.com
Подчеркивание
в имени по ст о во ­
го ящика.
}
\_ Т о ч к а в имени п о ­
чтового ящика.
i-love-donuts@duncansdonuts.com
Дефмс в до
мгнном
имени.
Четыре символа
о имени домена
первого уровня.
------------- X
.
Для проверки адресов
электронной почты нам по­
требуются дополнительные
символы.
Д еф исы в имени
почтового ящика.
seth+jason0mandamд о . u s
Знак ь в имени
почтового ящика.
гтдЬу0 уоисиЬе.сот.nz
т я т т ш я ш т т т ш т т г /ftw
Многоуровневое
. доменное имя.
Что б ы описать все многообразие адресов электронной
почты, нам не хватает символов.
Изначально м ы считали, что фрагменты адреса электронной
почты записываются только буквами и цифрами. Теперь в ша­
блон требуется вставить дополнительные символы...
далее ►
357
выбор символа
Дополнительные символы
Еще одной функцией, которая непосредственно касается спо­
соба написания шаблонов для адресов электронной почты, яв­
ляются символьные классы. Именно они позволяют задавать
правила вставки дополнительных символов. Символьный класс
можно представить в виде набора правил для представления
одного символа.
к г
[ C h a r a c t e r C l a s s ]
Символьный класс — это
набор правил для задания
определенного символа.
Символьные классы
заклю чаю т ся в к ва ­
дратные скобки.
Символьные классы
позволяют вставлять
в шаблоны для
регулярных выражений
дополнительные символы.
Выбор подходящего символа осуществляется среди набо­
ра, указанного в квадратных скобках. Рассмотрим несколь­
ко примеров:
/сі[іи]
д/
" с і і д "
С шаблоном совпадают
обе ст роки.
"сіид"
" $ 3 .50 "
"$ 5 "
Под шаблон подходят
все эт и ст роки.
)у д ь т е
" $ 19 .95"
Символьные классы — это именно то, чего нам
не хватало для приведения в порядок шаблона
записи адресов электронной почты.
358
глава 7
Не забывайте про
знаки перехода.
Если вам требуется
включить в выражение
символ, совпадающий
с метасимволом, ставьте перед ним
обратную косую черту. Такой чертой
(\), в частности, предваряются сим­
волы: [ \ ^ $ . I ?*-ь {).
ооцорожны !
формы и проверка данны х
Проверка адреса электронной почты
Теперь м ы можем написать корректный шаблон для адресов элек­
тронной почты, который будет учитывать все возможные варианты
написания имени почтового яш;ика и доменных имен.
Шаблон
ф р а гм ент может
появит 1?ся один или не сколько раз.
LocalNameQDomainPrefix.DomainSuffix
Любые буквы,
цифры и с и м ­
вол ~.
Любые буквы, цифры,
а также символы
Точка счит ает ся
част ью имени
домена первого
уровня.
Любые Z , 3 или 4
буквенно-цифровых
сим вола, кот оры м
предш ест вует
точка.
Помните, что любой шаблон может быть создан несколькими способа­
ми. Это относится и к шаблону для адресов электронной почты. Ведь так
сложно учесть все нюансы указанного формата данных. Впрочем, вы уже
получили навыки конструирования шаблонов и убедились, насколько про­
сто они преобразовываются в регулярные выражения.
Возьми в руку карандаш_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
Закончите код функции v a l i d a t e E m a i l ( ) , предназначенной
для проверки корректности ввода адресов электронной почты.
function validateEmail(inputField,
//
if
Проверяем,
были
ли
введены
(!
helpText)
{
данные,
(inputField, helpText))
return false;
//
Проверяем,
являются
ли
данные
return validateRegEx(
адресом
электронной
почты
.......................................
,
inputField.vaiue, helpText,
);
}
далее >
359
реш ение упражнения
Возьми Вруку карандаш
Решение
function
//
Вот как выглядит функция validateEmail (), проверяющая
корректность ввода адресов электронной почты.
validateEmail(inputField,
Проверяем,
были
ли
введены
helpText)
{
данные
helpText))
return
//
false;
Проверяем,
'^turn
1
продолж аем проверят ь о т сцт ст вие данных при помощ и
ф ункции validateN onEm ptyO -
являются
ли
данные
адресом
Шаблон для проверки адреса
элект ронной почт ы был со ­
ст авлен с прим енением боль­
ш инст ва м ет одов, которые
мы изучали в эт ой главе.
электронной
validateRegEx (
inputField.vaiue,
helpText,
.Й9!У}!^.\
Имя почтового ящика м о ­
ж е т сост оят ь из букв, цифр,
т аких символов, как ., ,
и
и должно ст оят ь в начале
ст роки.
Д ом енное им я
первого уровня
мож ет сост о’ я т ь как из Я,
т ак и из
4 символов.
(наприм ер, Johndoe@ acme.com)."
Если провеюка не будет пройдена,
-появит ся вспом огат ельное со ­
общение с образцом коррект ного
адреса элект ронной почты.
Наде)кная форма
Благодаря усилиям, направленным на проверку вводи­
мых в форму Bannerocity данных, заказы обрабатывают­
ся без проблем. Говард так счастлив, что по собствен­
ной инициативе показал вот такой баннер.
Говард с вост оргом
возвращ ает ся к л ю ­
бим ом у занят ию ~
полет ам !
Enter the banner m essage: jl^ n d a n g o ... м еста д л я
Enter ZIP code of the tocatton; |10012
Enter the date tor the m essage to be shown: [03/11/21
Вводимые номера т елеф онов и адреса
элект ронной почт ы т еперь п р о ве­
ряю т ся на соот вет ст вие заданному
ф о р м а т у данных.
Enter your name: jS eth Tinselnnan
Enter yoyr phone numtier: |2 1 2 ) 555-5339 « e a s e enter a phone number (tor example, f 23-455-7890),
Enter your emalt address: jseth t@ m an d an g o
rte e se enter an emeit address (for example, phmSo@Qecrm.oom).
Order Banner i
360
глава 7
ф ормы и проверка данны х
Вкладка
Согните страницу
по вертикали, чтобы
совместить два мозга
и решить задачу.
/
Зачем Іауа8сгір1 веб-формам?
хо|>оШ о, а ДБа лучше!
<г-
«Mandango...выбор мест в кино для настоящих нуткчлн! >
105012
03/11/200
212-555-5339
setht@mandango
/ ' " v a l ( l e y 1u e I k r i e ) /
«...места для мачо!»
100012
March 11, 2009
(212) 555-5339
seth%t0mandango.us
/n a m e I i d $ /
JavaScript может так много нрерожить
веб-формам, что сложно даже выбрать
что-то одно. Ответ на вопрос в заголовке
почти всегда включает в себя
какой-то уровень данных. Но как они используются?
Управление
а й р а н и Ц а М и
Управление HTML
с DOM
Управлениесодержимым веб-страницы при помощи JavaScript
напоминает приготовление еды. Конечно, это не настолько грязное
занятие... И, увы, вы не сможете съесть результат своих трудов. Тем не ме­
нее вы получаете полный доступ и Hr/WL-ингредиентам, из которых состоит
веб-страница, и, что еще важнее, вы можете менять исходный рецепт. Ведь
JavaScript дает возможность управлять HTML-кодом веб-страницы, что
открывает для вас целый ряд интереснейших перспектив, которые реализуют­
ся посредством набора стандартных объектов DOM.
%
преобразование интерфейса
Функциональный, но неудобный
Сценарий «Приключений нарисованного человечка» из главы 4
является хорошим примером интерактивной страницы, полу­
ченной при помощи JavaScript, но пользовательский интерфейс
немного неудобен, особенно с точки зрения современных стандар­
тов. Всплываюш,ие окна с навигацией быстро начинают надоедать,
а понять назначение кнопок перехода невозможно, потому что они
помечены как 1 и 2.
Всплывающие окна
м огут вызвать
раздражение и даже
прервать работку
приложения.
Your journey begins at a fork in the road.
©00
«Приключения» ра­
ботают прекрасно... но
могло быть и лучше.
Stick Fig ure Arfvem ure
VJelcOKG "to
STICK f m e
Clickeitlner
b u tto M "t®
Sbri..
Please choose; Л У
Из названий кнопок
перехода совершенно н е ­
понят но, куда они при оедут.
Элли решает поработать над интерфейсом
своего приложения...
364
глава 8
управление страницами
Без Всплывающих окон
Всплывающие окна с описанием сцены плохи еще и тем, что
текст исчезает после щелчка на кнопке ОК. Лучше поме­
стить описание непосредственно на страницу. Вот как после у
этого будут выглядеть «Приключения»:
Нобый набор ф айлов для «При клю чений нарисованного человеч­
ка» дост упен по адресу Ш р ://ш ш ш
h ea d fm tia b s.c o m /b o o ks/kfjs/.
куда мне это помест ит ь?
Тег div
Чтобы отобразить на странице описание сцены, сначала нужно
выделить под него область страницы в виде H T M L -элемента.
Так как описание появляется в виде отдельного параграфа, за­
дача решается при помощи тега <div>.
Тег
и м еет а т р и ­
б ут (Р. уникальны м об­
разом задающий элемент, в кот ором буда,т
располагат ься т екст
описания
< body >
text-au g,:,en ter..>
Please choose:
^decisioni" Value="l" „
Дает Л И атрибут ID тега <div>
_______ ___ _____ ________^
доступ к описанию сцены?
,■
"'^^^^'^-''changeScened) " />
f2 " value="2" onoHov .. ^
J
oncJ.iok= ChangeScene (2)" />
-v_
Именно при помощи атрибута 1В осуществляется доступ
к элементам страницы, в том числе и к описанию сцены.
И именно атрибут 1с1тега <div> даст кoдyJavaScгipt доступ
к описанию. Кстати, подобную операцию вы уже проделы­
вали...
ь
i|
)удыпе
оСЩо|>оЖНь1
Идентификаторы должны
быть уникальными.
Не забудьте, что атрибут
1с1предназначен для уникаль­
ной идентификации элементов страницы.
366
глава 8
управление страницами
Д оступ к HTML-эАементам
с методом g e t E l e m e n t B y l d
() стандартного объекта
d o c u m e n t м ы уже не раз сталкивались. Именно он дает до­
ступ к H T M L -элементам страницы... Пр и условии наличия
у них уникального ID.
Это должно совпадать
.с ат р и б ут о м id э л е ­
м ент а HTML, в наш ем
случае т ега div.
v a r sceneDesc = d o c u m e n t.g e tE le m e n tB y ld C 's c e n e te x t" )
\
Д о с т у п к элем ент у div o c y щ ест вляет ся при помош,и
его ат риб ут а id.
Имея в руках элемент с описанием сцены, м ы можем управ­
лять его содержимым. Н о сначала познакомимся с методом
g e tE le m e n ts B y T a g N a m e (), коллекционирующим все
элементы страницы с определенным тегом, например d i v
или img, и помещающим их в массив в порядке появления
на странице.
. Имя т ега, без <>■
Г
v a r d iv s = docum ent.getElem entsB yTagN am e("div");
Напишите код JavaScript, предоставляющий доступ к оранжевому изобра­
йражнение
^йражн
жению. Сначала при помощи метода g e t E l e m e n t B y l d (), а затем —
при помощи метода g e tE le m e n ts B y T a g N a m e () .
<body>
<р>Выберите уровень сложности приключений;</р>
<img id="green" src="green.png" alt="Расслабленный" / x b r />
<img id="blue" sro="blue.png" а1Ъ="Раздражающий" / x b r />
<img id="yellow" src="yellow.png" а11="Изматывающий" / x b r />
<lmg id="orange" src="orange .png" а11="Пугающий" / x b r />
<img id="red" src="red.png" а11="Суыасшедший" />
</body>
Методом g e t E l e m e n t B y l d {):,
Методом g e tE le m e n ts B y T a g N a m e ():,
далее ►
367
решение упражнения
Вот как выглядят варианты кода иауаЗспр!, предоставляющие доступ
к оранжевому изображению.
нение
]''ешение
<body>
<p>Before starting, please choose an adventure stress level:</p>
<img id="green" src="green.png" alt="Relaxing" / x b r />
<img ld="blue" src=”blue-png" alt="Irritating" / x b r />
<img id="yellow" src="yellow.png" alt="Frazzled" / x b r />
__ i d = " o r a n g e " s r c = " ' o r a n g e . p n g " a l t = " P a n l c ked^^~~7?y
Оранжевое
изображе­
ние являет ся
чет верт ы м
элем ент ом
массива,
поэт ом у его
индекс 3.
r />
<img id="red" src="red.png" alt="Maddening" />
</body>
Методом g e t E l e m e n t B y l d ( ) : ...... 4^f:'^jC (^.^nt.^etElem entByld[''oranQ e'')_
Методом g e tE le m e n tsB y T a g N a m e ( ) : ......
Внутренний код элемента
Под доступом к элементу H T M L подразумевается доступ к со­
держащейся в нем информации. В случае H T M L -элементов,
содержащих текст, таких как d i v и р, это осуществляется при
помощи свойства innerHTML.
Вы стоите
в лесу.
Свойство innerHTML дает
доступ к содержимому
элементов.
один
<р id = " s to r y " >
Вы стоите
<strong>oflMH</at;rong> в л е с у ,
О т ф орм ат ированное
содержимое также __
хранит ся в свойстве
</р>
innerHTML.
J
Г
d o c u m e n t.g e tE le m e n tB y ld C 's to ry " ) .innerHTML -<r-
368
глава 8
, С во й ст во innerH TM L
им еет дост уп ко всему
содерж имому элем ент а,
включая теги.
управление страницами
Создается впечатление, что
можно не только легко прочитать
содержимое НТМи-элемента, но и за­
писать туда новые данные.
Свойство innerHTML применяется
и для задания содержимого страницы.
Ведь оно позволяет осуществлять не
только чтение, но и запись информации.
Достаточно назначить этому свойству
строку текста, и содержимое контейнера
элемента будет заменено новым.
d o c u m e n t.g e tE le m e n tB y ld ( " s to ry " ) . innerHTML
"Вы <strong>H6</strong> один!";
Содержимое э л е м е н т а за
дается UAU, как 6 данном
САЦчае. зам ещ ает ся п у т е м
назначения ст роки свойству
innerHTML.
Вы н е один!
т ш яш ш
решение упражнения
Возьми в руку карандаш
Решение
Атрибут IP
Вот как выглядит код, присваивающий текст элементу, содержащему
описание сцены, написанный при помощи свойства innerHTML.
т е га <aiv> с
сообщением —
эт о "sceneText".
in n e r Н Т М L - message
Непрерывное «приключение»
Динамическое изменение описания сцен делает интер­
фейс «Приключений» более удобным и плавным. Ведь
теперь вам не придется отвлекаться на всплывающие окна.
Stick f igure Adventure
Такие небольшие переме­
ны, но мне они нравятся!
Т еперь описание
сцены м е н я ет с я
п р и переходе на
о р у гу ю ст раницу
Youаюstandingon*е bridgeoveriookingарешжЛ! steam.
Hcasechoose: _ lj _iJ
Теперь, когда при помощи тега < d iv > вы поменяли местоположение
описания и задали значение свойства innerHTML, осталось добавить
к «Приключениям» переменную m e s s a g e и в каждой из сцен присво­
ить ей нужное значение...
370
глава 8
управление страницами
У оДробНо ripo Код
«]|]= Ч 1КЛ 1о Ч е Н и й »
< h tm l>
<head>
< title> npH K nra4eH M H
нарисованного
< sc rip t ty p e = "te x t/ja v a sc rip t">
//В
к а ч е с т в е текущ ей выбираем
var
cu rS cen e
4 e n O B 0 4 K a< /title>
сцену
fu n c tio n c h an g e S c e n e (d ec isio n )
/ / У даляем о п и сан и е сцены
{
var message =
sw itch
(cu rS cen e)
case 0:
cu rS cen e
О (В вед ени е)
= 0;
Л окальная перелленная
message будет хранит ь
описание каждой новой
сцены.
Переменной message
присваивает ся
т екст с описанием
т екущ ей сцены.
{
= 1;
message = "yoar journey begins at a fork in the road.";
break;
case 1:
if
(d e c isio n
cu rS cen e
==
1)
{
= 2
message * "Tou have arrived at a cute little house in the woods.";
xo
are standing on the br dge overlooking a peaceful stream.'
/ / О бновляем и зображ ен ие сцены
d o c u m e n t.g e tE le m e n tB y ld C 's c e n e im g " ) .s r c
= "scene"
+ cu rS cen e
// Обновляем описание сцены
document.getElementByld("scenetext").innerHTMb = message;
< /sc rip t>
< /h ead >
Текст описания при ■
сваивается п е р е ' менной message при
помощ и свойства
innerHTML.
<body>
< d iv s ty le = " m a rg in -to p :lO O p x ; t e x t - a l i g n : c e n te r " >
< im g i d = " s c e n e i m g " s r c = " s c e n e O .p n g " a l t = " S t i c k F i g u r e
< d iv
+ ".p n g ";
id = " sc en e te x t"> < /d iv x b r
P le a se
< in p u t
< in p u t
A d v en tu re"
/x b r
/>
o n c lic k = " c h a n g e S c e n e (1)"
o n c lic k = " c h a n g e S c e n e (2)"
/>
/>
/>
choose:
ty p e = "b u tto n ” id = " d e c isio n l"
ty p e = "b u tto n " id = " d e c isio n 2 "
v alu e = "l"
v a lu e = "2 "
< /d iv >
< /body>
< /h tm l>
далее >
371
спроси прямо сейчас
_
Часщ о
^адаБаеМые
Bonj=>oc;j,i
Предоставляет ли метод
Позволяет ли свойство
g e t E l e m e n t B y l d O доступ
innerHTML задавать значение любых
к элементам страницы?
HTML-элементов?
Q ; Да, но только при условии уникального
! Нет. Ведь далеко не все HTMLэлементы имеют какое-то значение.
значения атрибута i d . Именно этот
атрибут делает возможным применение
метода
g e tE le m e n tB y ld ().
Поэтому свойство innerHTML.
применяется только для задания значений
таких элементов, как d iv ,
и прочих контейнеров.
s p an , р
Что просиходит со значением, когда
оно задается свойством innerHTML?
! Свойство innerHTML полностью
переписывает предыдущее значение
атрибута. То есть вы не можете добавить
значение в innerHTML. Хотя можно
осуществить соединение старого и нового
значений и уже затем назначить его
при помощи свойства
innerHTML.
Это может выглядеть, например, так:
e le m .in n e rH T M L += " Это
п р ед лож ен и е п р и б а в л я е т с я .
Я слышала, что свойство
innerHTML не входит в стандарт.
Это правда?
N.
1
)
Да. Н о почему нас д о л ж н ы заботить стандарты?
Свойство innerHTML изначально было создано Microsoft
как функция браузера Internet Explorer. Постепенно с ним
научились работать и другие браузеры, и свойство стало
неофициальным стандартом быстрого и удобного изме­
нения значений веб-элементов.
Н о факт остается фактом, в стандарт innerHTML не
входит. А ведь стандарты позволяют унифицировать при­
ложения, заставляя их работать с как можно большим ко­
личеством браузеров. Кроме того, существуют стандарт­
ные способы решения ряда задач, более гибкие и более
мощные, хотя и не всегда простые. М ы говорим сейчас
о D O M , или объектной модели документа (Document
Object Model). Именно так называется набор объектов,
позволяющий JavaScript полностью контролировать
структуру и содержимое веб-страниц.
372
глава 8
управление страницами
Объектная модель документа (РО М )
Объектная модель документа предлагает удобный с точки зрения сценария
взгляд на структуру и содержимое веб-страниц, благодаря которому возмож­ Да, эт о дерево ыМее т ст ранный вид, но
но их динамическое редактирование средствами JavaScript. В D O M стра­
именно т ак принят о
ницы представляются в виде иерархического дерева элементов. Каждый
предст авлят ь надор^
листок этого дерева называется узлом и непосредственно связан с каким-то
узлов, ф opмupyн^m ^*
элементом страницы. Узлы, расположенные снизу, считаются дочерними
страницупо отношению к вышестояш;им.
<html>
<headX/head>
<body>
<р id=" story" >
вы стоите < s t r o n g > o « H H < / s t r o n g > в лесу
</р>
</body>
</html>
DOM «видит» стра­
ницу как иерархию
узлов.
Пробелы, окружающие
т ег <р> на ст ранице,
и н т ер п р ет ирую т ся
как пуст ой т екст .
Выделенный
жирным т екст
«один» располо
жен под узло м
т ега <strong>.
далее *
373
классификация узлов
Страница как набор узлов
в модели D O M существуют различные типы узлов. Основные
типы соответствуют структурной части страницы и главным
образом состоят из узлов element и text.
document
Узлы DOM классифицируются
в соответствии с их типом.
ELEMENT
Самый верхний узел дерева,
представляющий собствен­
но документ и стоящий над
элементом html.
Любой H T M L -элемент, соответ­
ствующий H T M L -тегу.
ATTRIBUTE
TEXT
Атрибут элемента.
В иерархическом дереве
не фигурирует, но досту­
пен через узел element.
Текстовое значение
элемента, всегда храня­
щееся в дочернем для
узла element-узле.
DOCUMENT
Указав типы узлов в иерархическом дереве, вы сможете понять,
каким образом в объектной модели представлен каждый фраг­
мент страницы. В частности, обратите внимание на то, что
узлы TEXT всегда располагаются сразу под узлами ELEMENT как
часть их содержимого (или содержимое целиком).
Document
i
E LE M E N T
<html>
html
<headx/head>
<ьобу>
^
Хот я в РОМ сущ ест вует
дост уп к а т р и б ут а м и им^
соо т вет ст вует отдельный
т и п узлов, в составе дерева
они не появляю т ся.
ELEM ENT
elem ent
7
body
E LE M E N T
head
Вн соите <strong>o«™</stro„3> а
лесу.
</р>
J
</body>
TEXT
TEXT
TEX T
"Вы стоите"
ELEM ENT
Jl
strongl
TEX T
'один"
374
глава 8
"b лесу."
8 данном случае элем ент
head являет ся пуст ы м ,
но обычно под ним р а сп о ­
лагаю т ся дочерние узлы.
управление страницами
далее *
375
реш ение упражнения
-|^ з ь м и в руку карандаш
Решение
Вот как выглядит дерево иерархии узлов для показан­
ного ниже кода.
</head>
<body>
tevt
Г
Т
—
s.«
<dxv ^d=..scenetexf></di.xb, />
Please choose:
DOCUMENT
S<input type="button" ld=..decislonr' v a l u e - l " о
<
W
,■
^
^‘^^^'=''“"=hangeScene(ll "
tvpe=..b„tton.. id-..decisio„2.. val„e=..2~ on . ■ .
</div>^\^
/>
D ocum ent
°"=li=''-'t:hangescene(2)" />
element
j
html
Пробелы, предш ест вую щ ие элем ент у
и следующие за ним . и н т е р п р е т и р у ю т ся как пуст ы е элем ент ы т ипа text.
head
ELEMENT
r
TEXT
im g g
1,^ I —
I
- J
ГЕХТ
уг
TEXT
TEXT
ELEMENT
376
I
ELEMENT
глава 8
elem ent
elem ent
E ^ M ^ t te x t
управление страницами
CBoucmBa узлоВ
в большинстве случаев работа с D O M начинается с объекта
d o c u m e n t, который располагается на самом верху иерархического
дерева. Этот объект имеет такие методы, как g e t E l e m e n t B y l d () и
g e tE le m e n ts B y T a g N a m e (), а также набор свойств. Доступ ко мно­
гим из этих свойств возможен из любого узла дерева. Некоторые из
объектов допускают перемеш;ения к другим узлам. То есть свойства
узлов позволяют двигаться по их дереву.
Свойства узлов
позволяют
перемещаться
по дереву DOM
nodeТуре
пос1еУа1ие
Значения хранятся в текстовых
узлах и узлах атрибутов, но не
в узлах элементов.
Тип узла, например
DOCUMENT или TEXT, вы­
раженный числом.
сЫ1сШос1ез
firstChild
lastChild
Массив, содержаш;ий перечень
всех дочерних узлов в порядке
их появления в коде страницы.
Первый дочерний
узел.
Последний дочер­
ний узел.
Эти свойства дают возможность перемеш;аться по иерархическому
дереву и получать доступ к данным отдельных узлов. Например, для
быстрого выделения нужного узла достаточно воспользоваться его
свойствами и методом g e t E l e m e n t B y l d ().
a l e r t ( d o c u m e n t . g e tE le m e n tB y ld (" s c e n e t e x t " ) .n o d e V a lu e );
Свойство nodeValue Ъает
дост уп к хранящ емуся
в узле т екст у.
Свойство nodeValue
содержит т олько
неф ормат ированны й
т екст .
Т екст описания сцены
в «П риклю чении» и з ­
начально пуст ой.
Наверное, м ы выбрали для демонстрации не лучший пример,
ведь в исходной сцене «Приключений» тег d i v не содержит
текста. Н о уже для следуюш;их сцен появится текст с описанием,
и ситуация будет выглядеть намного лучше.
ажнение
Вот код одного из узлов дерева со страницы 376. Рассмотрите его внимательно
и укажите, какие узлы в нем упоминаются.
document.getElementsByTagName("body")[0].childNodes[1].lastChild
далее >
377
реш ение упражнения
нение
Вот какие узлы нашего иерархического дерева упоминаются в показанной
ниже строчке кода.
------'
Г
dociiment.getElementsByTagName("body")[0].childNodes[1].lastChild
.
У
Последним дочерним
узло м главного э л е ­
м ент а div являет ся
элем ент с пуст ы м
т екст ом .
М етод getE lem entsB yldQ
возвращ ает элем ент
с определенным IP-
Ч асто
Ч аД аБ аеМ ы е
М ет од в^^^^степЬвВуТадЫатеО
позволяет получит ь все элем ент ы
с определенным т егом , наприм ер с
т егом <lnput>.
БоЦроСЬ!
В чем разница между методами g e t E l e m e n t B y l d ()
и g e tE le m e n tsB y T a g N a m e () при работе с деревом
DOM?
Например, чтобы скрыть все изображения на странице
средствами JavaScript, нужно сначала вызвать метод
g e tE le m e n ts B y T a g N a m e
() и передать ему аргумент
" i m g " , выделив таким образом все узлы изображений. Затем
Q ; Выбор метода зависит от того, нужно ли вам выделить один
элемент или же группу сходных элементов, в первом случае
останется изменить свойство v i s i b i l i t y языка CSS
каждого из элементов. Но мы немножко забежали вперед, к DOM
следует использовать метод g e t E l e m e n t B y l d
достаточно указать идентификатор элемента.
знать, что, хотя метод
() —
Если же вашей целью является группа узлов, лучше
воспользоваться методом
378
глава 8
g e tE lem en tB y T ag N am e ().
и CSS мы вернемся позднее. На данный момент вам достаточно
g e tE le m e n ts B y T a g N a m e ()
(),
применяется реже метода g e t E l e m e n t B y l d
в некоторых ситуациях без него не обойтись.
управление страницами
То есть свойства узлов позволя­
ют проникать в код НТМЬ и получать
доступ к содержимому страниц... А как
насчет изменения этого содержи­
мого?
_______ /
Свойства D O M позволяют редактировать содержимое
веб-страниц и поддерживать соответствие стандартам.
Так как в D O M веб-страница представлена в виде набора
узлов, именно их редактирование приводит к изменению
ее содержимого. Текст в таких элементах, как div, span
или р, всегда фигурирует в виде дочернего узла или узлов.
Если текст содержится в едином узле, без дополнительных
элементов H TML, значит, м ы имеем всего один дочерний
узел. Рассмотрим пример:
d o cu m e n t.g e tE le m e n tB y ld (" s t o r y " ) . f i r s t C h i I d . nodeValue
Ты не один.
Ш ТУРМ
Каким образом DOM позволяет
менять текст?
далее >
379
детские проблемы
Редактирование те к ста
Если для простоты предположить, что существует только один дочерний узел,
который и содержит текст, то ничто не помешает нам назначить этому узлу
новый текст при помощи свойства nodeValue. Н о еще раз напомним, что дан­
ный подход работает только при наличии единственного дочернего узла.
d o c u m e n t . g e t E l e m e n t B y ld C 's t o r y " ) . f i r s t C h il d . n o d e V a l u e = "OK, может быть ты один.";
LEMENT
Текст в дочернем
узле заменен новой
версией.
TEXT
"ОК, может быть, ты один.
Н о проблема не всегда решается так просто. Что
делать, если дочерних узлов несколько, как в слу­
чае вот такого кода?
<р id = "sto rY ">
LEMENT
Ты < stro n g > н e < /s tro n g > один.
</р>
Эта с т р о ­
ка содержится
в целом наборе
дочерних узлов.
TEXT
ELEMENT
Г
"Ты"
j
strong
I
Л
TEXT
"один.'
К
Р едакт ирования содержимого
пер во го дочернего узла нед о ­
ст а т о ч н о для изм ен ен и я всей
ст роки.
TEXT
Л
Причиной появления
набора узлов являю т ся
дополнит ельны е теги.
Пр и замене содержимого первого дочернего узла остальные
узлы не изменятся, и м ы получим странный результат:
d o c u m e n t . g e t E l e m e n t B y I d ( " s t o r y " ) .f i r s t C h i ld . n o d e V a l u e = "OK, может быть ты о д ин .";
Редакт ирует ся т олько со ­
держимое первого дочернего
узла , все ост альное о с т а е т ­
ся без изменений...
380
глава 8
может быть, ты один)^ ^ д и н .
у
у
управление страницами
Три шага для изменения
Итак, м ы убедились, что замена значения одного узла не влияет на состояние
остальных. Получается, что для редактирования информации в данном случае
нужно сначала удалить все дочерние узлы, а затем добавить новые, уже с но­
выми значениями.
^
Удаляем все дочерние узлы.
О
Создаем текстовый узел с новым значением.
Добавляем его в качестве дочернего узла.
Для этого нам потребуются три метода:
Удаляет дочерний узел, пере­
данный ему в качестве аргу­
мента.
©
Г
createTextNode()
Из строки создает текстовый узел.
О appendChild()
Добавляет переданный ему узел в ка­
честве последнего дочернего узла.
Для редактирования текста «ты не один» нам потре­
буются именно эти методы. Сначала убедимся, что все
дочерние узлы удалены, затем создадим новый тексто­
вый узел и, наконец, добавим его к строке.
'
Выделим элемент
(узел) но его IP-
v a r node = docum ent. g e tE le m e n tB y ld (" s t o r y " );
w h ile (node. f i r s t C h i l d )
Удаляем дочерний узе л, пока
--------- — не очист им весь Массив.
n o d e . rem o ve C h ild (n o d e. f i r s t C h i l d ) ;
n o d e . app en dC hild(d ocum ent. c r e a te T e x tN o d e ("OK, может быть ты о д и н . " ) ) ;
0
4
J
После удаления всех — ^
дочерних узло в до­
бавим родит елю
новый т екст овы й
узел.
O
K
^ Создадим новый
т&кстобый узел,
(б к , может быть, ты
далее у
381
DOM о себе
Интервью недели:
Загадочные, но мощные
регулярные выражения
Head First: Мне говорили, что вы являетесь са­
м ы м маленьким кирпичиком в D O M , своего рода
атомом в H T M L -содержимом. Это так?
Узел: Н е знаю, насколько я атомарен, но не могу
не согласиться, что в дереве D O M я представляю
именно дискретные фрагменты информации.
Представим, что D O M разбивает каждую веб­
страницу на байтовые кусочки... Вот таким кусоч­
ком я и являюсь!
Head First: А почему это имеет такое значение?
Зачем нужна возможность деления страницы на
фрагменты?
Узел: Это важно только в случаях, когда вам тре­
буется доступ к информации или возможность ее
редактирования.
Head First: А не рискуем ли м ы в процессе такого
деления потерять какой-нибудь фрагмент? Ведь
часто люди разбирают что-то на части, а потом
оказывается, что вещь банально сломана.
Узел: При работе с D O M такой проблемы не
возникает, ведь вам не приходится в буквальном
смысле разбирать страницу. D O M всего лишь
представляет ее в виде иерархического дерева.
Head First: Даже так? А вы, я так понимаю, выхо­
дите на сцену, когда требуется что-то упростить?
Узел: Да. Н о речь не идет только об упрощении,
к дереву можно ведь и добавить данные.
Head First: Потрясающе! А как все это работает?
Узел: Помните, что каждый фрагмент информа­
ции является узлом? Вот через узлы и осущест­
вляется доступ к содержимому страниц. М о ж н о
создать новый узел и добавить его к дереву.
D O M — крайне гибкая структура.
382
глава 8
Head First: А как вы связаны с элементами? Или
это просто еще одно ваше имя?
Узел: П о большому счету, да. Элемент — это всего
лишь еще один способ восприятия тегов, напри­
мер < d i v > или <sp an > . Все элементы страницы
представлены на иерархическом дереве в виде
узлов, так что можно сказать, что м ы одно целое.
Н о я могу представлять не только элемент, но
и хранящееся в нем содержимое. Так, тексту,
хранящемуся в контейнере < d iv > , соответствует
собственный узел, дочерний по отношению к узлу
d iv .
Head First: А как не перепутать элемент с его со­
держимым?
Узел: Начнем с того, что в дереве D O M содержи­
мое всегда представлено в виде дочерних узлов.
Кроме того, каждый узел имеет собственный тип:
для элементов это тип ELEMENT, в то время как их
содержимое относится к типу TEXT.
Head First: То есть для доступа к хранящемуся
в элементе тексту мне потребуется узел типа
TEXT?
Узел: Да. Н о следует помнить, что свойство
no d e T y p e возвращает лишь номера типов. На­
пример, типу TEXT соответствует номер 3, а типу
ELEMENT — номер 1. Впрочем, это можно не запо­
минать, ведь для доступа к содержимому элемента
вам достаточно найти дочерний по отношению
к нему узел.
Head First: Понятно. Спасибо, что согласились
к нам прийти и рассказать про чудеса дерева
DOM.
Узел: Пожалуйста. И если когда-нибудь вы ре­
шите заняться приведением в порядок деревьев
в вашем саду, не забудьте позвать меня.
управление страницами
Часто
Задаваемые
БоЩроСЬ!
у э л е м е н т а р pElem .childN odes[z]
т ри дочерних
1
Я не совсем понимаю, как
систематизированы дочерние узлы.
Например, как работает свойство
ч -^ -J L
г ^ л -Г
childNodes?
_
^
Strong
1
Узел, содержащий данные,
считается родительским. Данные,
0 ='
“ Г ” Элемент
strong и м е ­
представляющие собой больше,
чем лросто текстовую строку,
формируют набор дочерних узлов.
Этот набор указывается в свойстве
p E iem .ckM N o d e.s[0]
childNodes
родительского узла
как массив. Порядок элементов массива
определяется порядком появления
узлов на странице. В результате
для получения доступа к первому
дочернему узлу достаточно написать
childNodes [ О ] .
Для поочередного
ет один до<
черний узел.
,"
доступа ко всем дочерним элементам
используются циклы.
Ql
Вот как выглядит это условие:
while(node.firstChild)
Мы проверяем, присутствует ли
в родительском узле первый дочерний
узел, в случае положительного ответа
возвращается значение true, и цикл
продолжает работу. Отрицательный
ответ означает, что дочерних узлов
больше не осталось. Выражение
node.firstChild приобретает
значение null, которое автоматически
преобразовывается в false. После этого
происходит выход из цикла.
Б:
Каким образом выполняется
проверка условия в цикле while, код
которого удаляет все дочерние узлы?
Магниты JavaScript
в ООМ-совместимой версии «Приключений» отсутствуют несколько важных фрагмен­
тов. Расставьте магниты таким образом, чтобы получить код, меняющий содержимое
текстового узла. Каждый магнит может быть использован несколько раз.
/ / Обновление описания сцены
= d o c u m en t.g etE lem en tB y ld ("
Vo.]-
)
w h ile (
(
(document. c re a te T e x tN o d e (
));
далее ►
383
решение задачи с магнитами
Решение задачи с магаитами
Вот как выглядит код, меняющий содержимое текстового элемента.
Ц икл работ ает ,
пока ост ает ся кот я
бы один дочерний
т екст овы й узел.
Ц икл работ ает , пока
суш ,ест вует первый
дочерний узел.
Выделилл т екст овы й
элем ен т по его IP.
Переменная message
содержать
>^олшо т екст , без
ф орм ат ирования
и тегов.
Обновление описания сцены
sceneTexI Л = d o c u m e n t . g e t E l e m e ^ ^ I d C
w h ile (
firstChild
sceneText
sceneText
I
i
I
F
removeChild к (
sceneText
^ ^ ^ ^ p ^ ^ K h i W j ^ d o c u m e n t . createT extN o de {
По очереди удаляем первые
дочерние элем ент ы до п о л ного их исчезновения.
д
Теперь, когда дочерних
элем ент ов не о с т а АОСЬ) добавление И00020
т екст ового узла га р а н ­
т и р у е т полную зам ену
т екст а.
После удаления всех
предш ест вую щ их дочер­
них элем ент ов созда ет ся новый т екст овы й
узел, кот орый добавля­
ет ся в качест ве дочер­
него.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
384
Свойство innerHTML, не входящее в стандарт,
дает доступ ко всему содержимому элементов.
В DOM веб-страницы представлены в виде дерева
связанных узлов.
Объектная модель документа, или DOM, предо­
ставляет стандартизованный механизм доступа
к данным и их редактирования.
В DOM редактирование содержимого страницы
включает в себя удаление всех дочерних узлов эле­
глава 8
мента, с последующим созданием и добавлением
дочернего узла с новым содержимым.
управление страницами
«Приключение», совместимое со стандартами
Разве это не здорово! Признаком хорошего «Приключения» стало соответствие
стандартам. В ы согласны? В контексте современных веб-приложений это большое
преимуш;ество. Важнее всего значительные изменения, которые благодаря D O M
произошли с описаниями сцен...
Да, внешний вид страницы не поменялся, но теперь,
благодаря D O M , она сконструирована в соответствии
с новейшими веб-стандартами. Далеко не всегда код
JavaScript можно оценить визуально. Так и в данном
случае, изменения коснулись аспектов, находяш,ихся
«за кулисами».
Стандарт DOM
предоставляет
больший контроль над
редактированием HTML,
чем свойство innerHTML.
далее >
385
улушвнныв варианты
В поисках лучших Вариантов
к настоящему моменту текстовые описания сцен были дважды
переделаны, а вот вид кнопок так и не поменялся. А ведь можно
придумать более понятный способ перехода к следующей сцене,
нежели выбор межд)' цифрами 1 и 2!
Кнопки с цифрами прекрас­
но выполняют свою работу,
но все-таки стоит их сделать
более наглядными.
Pleasechoose; I
Цифровые кнопки неудачны, т ак
как они не даю т предст авления
о т о м , куда после их нажатия
от правит ся пользоват ель.
Нужно снабдить кнопки кратким описанием ситуации,
в которую в результате нажатия одной из них попадет поль­
зователь. То есть, если предстоит совершить выбор между
«Перейти через мост» и «Остановиться на мосту и посмо­
треть на воду», кнопки могут выглядеть вот так:
Ш Л
B rU ge
G a ise h te Stream
Намного лучше! Г е п ^
_
кнопки пом огаю т в п р и н я­
т ии решения.
Для решения нашей задачи не нужны кнопки ф ор м ы —
с этим справится любой элемент HTML, служащий контей­
нером для текста. А в оформлении кнопок помогут сти­
ли CSS.
Ш ТУРМ
Каким образом реализовать отображение на кнопках текста с кратким
описанием следующей сцены?
386
глава 8
управление страницами
Проектирование лучше, варианты чии^е
Так как новые кнопки перехода в «Приключениях» представляют
собой H T M L -элементы, содержащие текст, для динамического
изменения их содержимого воспользуемся средствами DOM.
В результате для каждой сцены будет задаваться не только свое
описание, но и свой вид кнопок. Значит, функции changeScene ()
потребуются две новые переменные для хранения еще двух тек­
стовых фрагментов. Назовем их decisionl и decision2.
Вот каким образом в функции changeScene () будет задан текст
для кнопки перехода от сцены 1 к сцене 3:
curScene = 3;
message = "You a r e s t a n d i n g on t h e b r i d g e o v e r lo o k in g a p e a c e f u l stre a m ,
d e c i s i o n l = "Walk a c r o s s b r i d g e " ;
Т екст с описанием
возможных вариант ов
перехода хранится^
в переменны х decision!
и decisionZ-
d e c is i o n 2 = "Gaze i n t o s tre a m " ;
Возьми в руку карандаш
Динамически меняющиеся надписи на кнопках в нашем «Приклю­
чении» требуют нового подхода. Напишите код для новых тексто­
вых элементов, которые заместят кнопки <input>.
Подсказка; класс CSS-стиля для новых элементов называется «decision».
В самой первой сцене на кнопке должен присутствовать текст «Start Game»
(Начать игру).
Pksiscchoose;
'>
Га:"'ГсГв1Гп2'.'.
Н апиш ит е код для
кнопок, т екст на
кот оры х меняет ся
Iдинамически!
SttrttSere
далее k
387
реш ение упражнения
- ^ з ь м и в руку карандаш
'ешение
Итак, вот новый код для текстовых элементов, которыми мы заме­
ним ранее использовавшиеся кнопки < in p u t > :
Please choose:
I
j
2
<lnput type="button" id="declsionl" v a l u e - n - onclick="changeSce.ie (1) " />
<inp“t tffe="button" id-"decision2" value="2" onclick="c:hangeScene(2)
/>
Дбе кнопки
превращаются
в элементы span.
Stan Game
I
А
I не создать ли нам функ
цию для замены текста
в узлах?
U сноВа замена те к ста В узлах
Для того чтобы кнопки в «Приключениях» стали функциониро­
вать нужным образом, не хватает кода, задающего текст в эле­
ментах span. П о большому счету он должен работать аналогично
написанному ранее для динамической замены описания сцены
коду D OM . Основная проблема в том, что теперь нам каким-то
образом нужно решить одну и ту же задачу для трех элементов
сразу: для описания сцены и двух кнопок перехода...
388
глава 8
управление страницами
Функция, заменяюи^ая т е к с т узла
Функция, реализующая замену текста в узлах, пригодится нам
не только для «Приключения». Она должна работать по прин­
ципу ранее написанного нами кода замены описания сцены.
У этой функции будет два аргумента:
f u n c t i o n re p la c e N o d e T e x t(id , newText)
{
, узла, т е кс т к о ­
т орого нам нужно
поменят ь.
Новый т екст .
В качестве аргументов функции replaceNodeText () выступает, вопервых, идентификатор узла, содержимое которого следует заменить,
во-вторых, новый текст, функция позволит редактировать любые эле­
менты, являющиеся текстовыми контейнерами. В «Приключениях»
она будет динамически менять текст описания сцены и переходных
кнопок. Н о сначала нам нужно будет написать ее код.
Теперь мы в м е ^
ст о т рехкрат ного Л
написания одного и т ого же кода
т ри раза вызываем
функции).
кг~
r e p la c e N o d e T e x t ( " s c e n e t e x t " , m e ss a g e );
Замена т екст а
'с описанием сцены.
r e p la c e H o d e T e x t ( " d e c is i o n l " , d e c i s i o n l )
re p la c e N o d e T e x t( " d e c is io n 2 " , d e c is io n 2 )
Замена т е к ­
ст а двух кнопок
перехода.
реш ение упражнения
Возьми в руку карандаш
^ВОЗЬМ!
Решение
Вот код функции r e p la c e N o d e T e x t {), меняющей
текст в узле с указанным ID.
Выделяем элем ент
по его ID.
function replaceNodeText(id, new Text) {
var node = docum ent.getElem ent8yld(id)-,
Удаляем все
дочерние узлы.
while (node.firstChild)
node.removeChild(node. firstChild);
Создаем
новый дочер­
ний элем ент ,
используя
переданный
в качестве
аргум ент а
т екст .
node.appendC hild(docum ent.createTextN ode(new Text));
}
функция createTextNodeQ
дост упна т олько в объект е
d o cu m en t и не связана с о т ­
дельными узлам и.
Динамические параметры
Новые варианты кнопок перехода с динамически меняющимся
текстом более наглядны, чем кнопки с номерами из предыдущей
Динамиче(
ский, нагляд/ ный, восхититель-
390
глава 8
управление страницами
Часдао
'^адаБаеМые
БоИроСь!
Где оказывается узел, созданный
функцией c r e a t e T e x t N o d e ( ) ?
Почему вместо элементов d i v
в «Приключении» используются
элементы s p a n ?
содержать только текст?
; Так как кнопки выбора должны
располагаться рядом, для их задания не
могут использоваться блочные элемен­
ты, такие как d i v . Соответственно, мы
применяем для них строковой элемент
span.
Созданный при помощи функции
c r e a t e T e x t N o d e ( ) узел может
Q ; Нигде. В первый момент созданный
текстовый узел оказывается в неизвест­
ности, по крайней мере с точки зрения
дерева DOM. Вы вручную должны
добавить его к уже существующему узлу
в качестве дочернего, и после этого он
оказывается в структуре дерева.
! Да. При работе со свойством
in n e r H T M L вы можете назначать
текст прямо с тегами. А вот в DOM сло­
восочетание «текстовый узел» означает
только текст, без всякого форматиро­
вания.
интерактивность
Новые варианты кнопок перехода намного лучше нредыдуш;их,
но даже их можно усовершенствовать. К примеру, можно сделать
так, чтобы кнопка подсвечивалась при наведении на нее указателя
мыши, как бы подсказывая, что на ней можно ш,елкнуть.
W alk a r o m d Back
Текстовые элем ент ы вы ­
деляю т ся при наведении
на них указат еля мыши.
Knock on D oor
J
Я была уверена, что все эти
визуальные эффекты связаны
с CSS, а не с DOM.
П о д с в е ч и в а н и е э л е м е н т о в с в я з а н о с C SS, н о и м е е т
н еп оср едств ен н ое отнош ение и к D O M .
Подсвечивание содержимого веб-страницы реализуется
средствами CSS, так как оно связано с небольшим изменением
фонового цвета элемента. При этом D O M обеспечивает про­
граммный доступ к CSS-стилям элементов...
далее у
391
элегантные стили
Значение стиля: C SS и DOM
CSS-стили связаны с H T M L -элементами, в то время как D O M обе­
спечивает доступ к стилям посредством элементов (узлов). П р и ­
менение D O M к редактированию CSS-стилей позволяет динами­
чески менять вид страницы. Стили назначаются элементу через
класс styl^.
<span i d = " d e c i s i o n l " c l a s s = " d e c i s i o n " o n c lic k = " c h a n g e S c e n e ( 1 ) " > S t a r t Game</span>
<span i d = " d e c i s i o n 2 " c l a s s = " d e c i s i o n " o n c lic k = " c h a n g e S c e n e ( 2 ) "></span>
< s ty le ty p e = " te x t/c s s ”>
sp an .d ecisio n
{
fo n t-w eig h t:b o ld ;
Внешний вид кнопок
перехода определяет
их класс style.
b o r d e r : t h i n s o l i d # 000000;
p a d d i n g : 5px;
b a c k g r o u n d - c o l o r : #DDDDDD;
I
)
< /sty le >
D O M предоставляет доступ к классу стилей элемента при по­
мощи свойства className узла.
a l e r t ( d o c u m e n t . g e t E l e m e n t B y l d ( " d e c i s i o n l " ) .c l a s s N a m e ) ;
Свойство className
дает дост уп к классу
ст илей элем ент а.
decision
Свойство className узла
предоставляет доступ
к классу стилей.
392
глава 8
Не путайте
классы сти­
РуДыпе
I
лей CSS
оСШо р^ о ЖН ы !
с классами
JavaScript.
t o
Классы стилей в CSS
и классы в JavaScript не
имеют между собой ничего
общего. В CSS классом на­
зывается набор стилей, ко­
торый может быть приме­
нен к элементу страницы,
в то время как в JavaScript
классом называется шаблон
создания объектов. Более
подробно классы и объекты
будут рассматриваться
в главе 10.
управление страницами
Замена классоВ стилей
К ласс ст илей
dec\яoniv\verse
■меняет щВетовую схему к н о п ­
ки перехода.
Чтобы поменять внешний вид элемента, достаточно указать для
него имя другого класса стилей.
d o c u m e n t.g e tE le m e n tB y ld C 'd e c is io n l" ).c la s s N a m e = " d e c i s i o n i n v e r s e " ;
Вид т ой же самой
кнопки перехода после
замены класса ст илей!
<style type="text/css">
span.decisioninverse {
font-weight.
-bold,•
Новый класс стилем был на
значен кнопке перехода при
поМош,и свойства className.
font-color;#FFFFFF;
border:thin solid #DDDDDD;
padding:5px;
Start Game
background-color:#000000;
)
Замена класса стилей элемента в свойстве className
немедленно отражается на внешнем виде элемента.
Данная техника позволяет кардинальным образом
менять внешний вид элементов страницы, не тратя
практически никаких усилий.
</style>
Возьми В руку карандаш
Напишите код для элемента < s p a n > кнопки перехода, который
при помощи событий o n m o u s e o v e r и о п т о и з е о и 1 меняет
класс стиля при наведении на кнопку указателя мыши.
Подсказка: класс стиля, который используется при наведенном
на кнопку указателе, называется d e c i s i o n h o v e r .
<зрап i d = " d e c i s i o n l " c l a s s = " d e c i s i o n " опс11ск="сЬапдеЗсепе(1)"
> S t a r t Game</span>
<span i d = " d e c i s i o n 2 " c l a s s = " d e c i s i o n " o n click = "ch an geS cen e (2)"
></span>
далее ►
393
реш ение упражнения
Возьми Вруку карандаш
Решение
Вот как выглядит код для элемента < зр а п > кнопки перехода, кото­
рый при помощи событий o n m o u s e o v e r и o n m o u s e o u t меняет
класс стиля при наведении на кнопку указателя мыши.
К ласс ст иля declsionkover п о ­
яв л яется б о т в ет на событие
onmouseover.
<span i d = " d e c i s i o n l " c l a s s = " d e c i s i o n " o n c lic k = " c h a n g e S c e n e (1)"
^^^~^onm ouseover= "tkis.classN am e - 'decisionhover'"
............... > S t a r t Game</span>
e m n u Z f^ n p u
наведении у к а злтеля мыши
на элем ент
span.
<span i d = " d e c i s i o n 2 " c l a s s = " d e c i s i o n " o n click = "ch an qeS cen e (2)"
>c9,'^,^omeoYer=4his.className - 'decisionkover'"
o nm ouseout-4kis.classN am e - 'decision'"
></span>
Это событие возникает , когда ук а за ­
т ель мыши убирает ся с элем ент а span. п.
Д аД аБ аеМ ы е
ка событие o n m ouseout
БоЦ|ЭоСЬ 1
Можно ли создать кнопку, которая подсвечивается
при наведении на нее указателя, только средствами CSS?
0
Стильные Варианты
Благодаря классам стилей кнопки перехо­
да в наших «Приключениях» теперь могут
быть представлены в двух вариантах: обыч­
ном и подсвеченном.
! Да. В большинстве случаев именно так и следует посту­
пать, потому что CSS поддерживается ббльшим количеством
браузеров, чем JavaScript. Но наши «Приключения» — это
приложение, написанное на JavaScript, и многие его функции
нельзя реализовать средствами CSS. Соответственно, мы соч­
ли возможным продемонстрировать другой подход к решению
данной задачи.
<style type="text/css">
span.decision {
<style type="text/css">
font-weight:bold;
border;thin solid #000000;
padding:5px;
background-color:#DDDDDD;
41
}
Единственным различием
между эт им и классами
ст илей являет ся цвет
фона.
span.decisionhover {
font-weight;bold;
border:thin solid #000000;
padding;5px;
background-color:#EEEEEE;
</style>
</style>
Обычный
WaBt around Back Knock on Door
394
глава 8
управление страницами
Проверка работы приАО)кения
Благодаря возможностям D O M менять класс стиля элемента по
требованию наши «Приключения нарисованного человечка»
получили новый интерфейс. Элли очень довольна.
Как Эффектно
теперь выглядят
кнопки перехода!
]
л
1
Stick
»в®.
©Стучим
в M&pü
Y « have m ived м а
hfosefn й* « /« d s.
I '
■
Чаои-
Кнопки перехода т е перь подсвечивают ся
при наведении на них
указат еля мыши.
"^аДаБаеМые
BoiiJ^oCbi
Б:
Они входят в стандарт?
' Почему для задания класса стиля
|Гнопок перехода нам не потребовался
кно
метод g e t E l e m e n t B y l d {) ?
мет
Q ; Да, на самом деле есть еще
много стандартных событий JavaScript,
с которыми вы пока не знакомы. Впрочем,
объектом, а в HTML-коде элемента
доступ к объекту осуществляется при
^ 1яне помню событий
o n m o u s e o v e r и o n m o u s e o u t.
важно только то, как вы реагируете на
событие, даже ничего не зная о нем.
В данном случае по именам событий
можно понять, что первое возникает,
когда указатель мыши оказывается над
0;; Каждый элемент JavaScript является
помощи ключевого слова t h i s . В коде
«Приключений» это ключевое слово
относится к узлу элемента span.
Именно этот объект при помощи свойства
Классы стилей — это здорово, но
бы предпочел менять всего одно
я 6i
свойство. Это возможно?
сво
0:; у вас замечательная интуиция!
Именно над этой проблемой бьется
сейчас автор «Приключений» Элли. И эта
проблема включает в себя применение
JavaScript и DOIV! для индивидуального
управления свойствами стилей...
classN am e
элементом, а второе — когда указатель
получает доступ к своему
классу стилей. Поэтому для изменения
убирается с элемента.
класса стилей достаточно написать
t h i s . c la s s N a m e .
далее у
395
когда у кнопок нет имен
Пустая кнопка
Данная проблема возникла давно, но до этого момента Элли
старалась не обращать на нее внимания. Хотя из некоторых сцен
возможен только один переход, отображаются все равно обе кноп­
ки, как показано на снимке экрана. С этим нужно что-то делать,
потому что интерактивные элементы, не содержащие информа­
ции, создают путаницу.
stick Figure feJvervture
в О 0
Меня беспокоит наличие пу­
стых кнопок перехода в некоторых
сценах. Они бессмысленны и толь­
ко путают пользователей.
VJelcONVe { о
STICK FIGURE
ADVENTURE
в каких еще сценах присутствует данная
проблема? Как ее можно решить?
396
глава 8
управление страницами
Настройка «а ля style»
Иногда не нужно менять весь класс стилей. Для случаев, когда
требуется большая детализация, существует объект style. Объ­
ект style доступен как свойство узла и дает доступ к индивиду­
альным стилям как к свойствам. Так, свойство visibility при­
меняется для управления видимостью элементов. В НТМЬ-коде
«Приключений» вторую кнопку можно изначально скрыть:
Свойство style узла предо­
ставляет доступ к индивиду­
альным свойствам стиля.
<span i d = " d e c i s i o n 2 " c l a s s = " d e c i s i o n " o n c lic k = " c h a n g e S c e n e (2)"
onmouseover=”t h i s . className = 'd e c i s i o n h o v e r '"
o n m o u s e o u t= " th is . className = ' d e c i s i o n ' "
s t y l e = ”v i s i b i l i t y : hidden'*>< / span>
Таким образом, для изменения видимости элемента достаточно менять
значение свойства visibility с visible на hidden и обратно.
:
у
d o c u m e n t . g e t E l e m e n t B y I d ( " d e c i s i o n 2 " ) .s t y l e .visibility = "visible";
d o c u m e n t . g e t E l e m e n t B y I d { " d e c i s i o n 2 " ) .s t y l e .visibility = "hidden";
^
Start Game
Возьми в руку карандаш
ix
Вт орая кнопка.
В некоторых сценах «Приключений» должна меняться видимость второй
кнопки перехода. Пометьте эти сцены и укажите, каким образом должно
осуществляться это изменение.
далее ►
397
решение упражнения
Возьми в руку карандаш,
Решение
Вот каким образом в некоторых сценах «Приключений» долж­
на меняться видимость второй кнопки перехода.
Вт орая кнопка.
Start Game
Вт орая кнопка перехода
__^
должна быть
бо бсех — .
сценах., из кот оры х возможен
т олько один выход.
^
^
В т орой элем ент перехода
нужно показат ь один раз
в м о м ен т начала новой
игры.
Скрыть втоюой элем ент
^ р е б у е т с я б сценах, ведущ их
к концу игры.
В каждой сцене изменение
оидимости вт орой кнопки
Т/лл
fУ y^^c m 6 ляem cя при
помощ и свойства уШЬПЦц
объект а 5Ы е.
case 7:
if (decision == 1) {
curScene = 6
,
V
message = "Sorry, you became the troll's tasty lunch.
decisionl = "Start Over";
decision2 =
// Скрыть вторую кнопку перехода
d o c u m e n t . g e t E l e m e n t B y l d ( " d e c l s i o n 2 " ) .s t y l e . v i s i b i l i t y
else {
curScene = 9;
decisionl =
decision2 =
}
break;
398
глава 8
и
управление страницами
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
Свойство className узла меняет весь класс
стиля этого узла.
Элементы страницы можно динамически прятать
или снова делать видимыми при помощи свойства
visibility элемента.
Свойство style дает доступ к отдельным свой­
ствам стиля узла.
Классы стилей CSS не имеют ничего общего с клас­
сами JavaScript — это совсем разные вещи.
Аналогично дейст вует свойство
ст иля display. Присвоив ем у зн а ­
чение попе, вы скроет е элем ент ,
а присвоив значение block, наобо­
р о т , сделает е видимым.
Без фиктивных кнопок
Управление отдельными стилями при помощи D O M позволяет
по вашему выбору скрывать или делать видимой вторую кнопку
перехода. В результате вы получаете более функциональный
пользовательский интерфейс, ведь лишних кнопок больше нет.
.»в».
PtgureAdventare
Т
_______________
(
WelcOhAG to
^
\
Намного лучше... эти
пустые кнопки так раз
дражали!
ST IC K FIGURE
Теперь в сценах, для к о т о ­
рых вт орая кнопка п е р е ­
хода не т ребует ся, она
оказывается скрытой.
далее >
399
старое, доброе дерево решений
Усло)княем «Приключения»
Поскольку Элли собиралась написать длинную и интересную
историю со множеством ветвлений, в управлении столь слож­
ной структурой ей поможет DOM.
Новые <<Приключения>> = Рост дерева решений!
Самая последняя версия «П риклю чений нарисованного
человечка» уже выложена в И нт ернет е и ждет ваших
дополнений. Если вы еще не скачали ее, сделайт е эт о
по адресу k t t p : / / w w w .kea d firstla b s.co m /b o o ks/h ijs/.
400
глава 8
управление страницами
Столько развилок сюжета... Как же напи­
сать все эти проверки условий?
<
Вряд ли в ы напишете длинную
историю без хорошего способа
проверки условий.
П о мере добавления новых сцен
и переходов становится все слож­
нее обычным способом проверять
условия и гарантировать, что на
каждой развилке пользователь будет
попадать туда, куда нужно. Поэтому
нам определенно требуется новый
механизм проверки условий.
ШТУРМ
Каким образом лучше всего осуществлять проверку
условий при таком огромном количестве ветвлений?
далее >
401
следуем по пути
Поход по дереву решений
Браузеры умеют запоминать список посещенных
пользователем страниц. Аналогичную функцию
можно использовать в «Приключениях» для провер­
ки и отладки сюжетных ходов. Вам нужно выделить
набор сцен, ведущий к определенному результату.
Только таким способом Элли сможет убедиться, что
все работает именно так, как ожидалось.
—
РйЗЙилкй
История переходов конструируется как список посещенных по
мере продвижения по игре сцен. Именно она потом будет ис­
пользоваться в качестве отладчика.
Начало Сцена О — Введение
Выби­
рает ся
первый
вариант...
Сцена 1 — Развилка на дороге.
Сцена 2 — Хижина в лесу.
♦
Сцена 3 — Ведьма в окне.
❖
Сцена 8 — .
Сцена 11-
Конец
402
глава 8
■■■Которяя ведет
к сцене 4.
Каждая пройденная
сцена добавляется
_к ист ории вм ест е
с реш ением , к о т о ­
рое к ней привело.
Ш ТУРМ
Каким образом следу­
ет изменить страницу
«Приключений» для
включения поддержки
«истории пройденных
сцен»?
управление страницами
Превратим историю в HTML
с точки зрения H T M L
код истории решений не является слиш­
ком сложным: вам понадобится элемент d i v и строка текста,
описывающая следующую сцену.
Каждый элем ент р
содержит один из
п ун кт о в ист ории
переходов.
<div i d = " h is t o r y " >
<p>Decision 1 -> Сцена 1
Развилка на д о р о г е .</
<p>Decision 1 -> Сцена 2
Хижина в л е с у .< /р >
<p>Decision 1 -> Сцена 3
Ведьма в окне.</р>
</div>
Осталось написать K O A ja v a S c r ip t, который при помощи D O M
превратит историю посещений в набор узлов.
(
ФуНКЦИЯ фиКСЯЦИИ ИСТОрИИ
посещенных страниц может
быть полезным инструментом
отладки.
А разве мы
можем создавать
новые строки
по желанию?
D O M позволяет создать любой H T M L -элемент.
А значит, вы можете создать и строку. Для этого
вам потребуется еще один метод объекта документа
c r e a t e E l e m e n t (). Именно он создает новый контейнер,
в который вы добавляете текст, формируя дочерний узел
при помощи функции c r e a t e T e x t N o d e (). В результате
на дереве появляется новая ветка узлов.
div I
document.createElement("р");
Г
ELEMENT
docviment.createTextNode (" .. . ") ;
Vs____
TEXT
"Decisxon 1 -> Сцена 1 : Развилка на д о р о г е . ” |
mp
далее >
403
манипулируем с HTML
Обработка НТМ1-кода
Для создания нового элемента методом c r e a te E le m e n t ()
достаточно указать имя тега. Так, чтобы создать элемент (р),
достаточно вызвать метод с аргументом "р" и указать, куда при­
соединить конечный результат.
Мы начнем с нового
элемента р , «парящ его
° ‘п р о ст р а н ст в е » .
v a r d ec isio n E lem = document. c r e a t e E l e m e n t (" р " );
Итак, у нас есть новый элемент без содержимого, пока еще не
принадлежащий никакой странице. То есть нам нужно доба­
вить к нему текст, создать текстовый узел и добавить его в каче­
стве дочернего к узлу р.
d e c is io n E le m .a p p e n d C h ild C 'D e c is io n 1 -> Сцена 1 : Развилка на д о р о г е . " ) ) ;
Э л е м е н т р до сих пор никуда не
присоединен, но он перест ал быть
п у с т ь , м благодаря новому дочер­
нему т екст овом у узлу
^
" D ecisio n 1 -> Сцена 1 : Развилка на д о р о ге.'
Теперь новый элемент нужно добавить в качестве дочернего
к элементу d iv истории переходов.
d o c u m e n t .g e t E l e m e n t B y I d ( " h i s to r y " ) . app en dC hild (d e cisio n E le m )
Элемент и добавлен
о качестве дочернего
к сущ ест вую щ ем у эле­
м ент у div, то ест ь он
оказался в составе веб­
страницы.
<div id="history">
" D e c is io n 1 -> Сцена 1
дороге.
^^<p>Decision 1 -> Сцена 1 : Развилка на дороге.</
</div>
Повторяя эти процедуры при каждом переходе к новой сцене,
мы динамически формируем историю «Приключений».
404
глава 8
Развилка на
управление страницами
-ft-
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
Все HTML-элементы можно создать
методом c r e a t e E le m e n t о объекта
Аккуратно добавляя и удаляя узлы на дереве DOM,
можно по желанию разбирать страницу на состав­
d o c u m e n t.
ные части и собирать обратно.
Для добавления текстового содержимого нужно соз­
дать текстовый узел и присоединить его к элементу.
Возьми в руку карандаш
Напишите функцию c h a n g e S c e n e ( ) , фиксирующую историю
пройденных сцен в «Приключениях». Подсказка: когда текущая
сцена отлична от нулевой, нужно добавить новый параграф с до­
черним текстовым узлом к элементу с историей переходов. Для
сцены номер о нужно удалить историю.
f u n c t i o n c h a n g e S c e n e (d e c is io n )
{
/ / Обновление истории пройденных сцен
далее *
405
реш ение упражнения
щМьт в руку карандаш
Решение
Вот код функции c h a n g e S c e n e ( ) , фиксирующей историю
пройденных сцен в «Приключениях».
АобавиМ новый т е к ­
стовый узел к новом у
п а р а гр а ф у.
ф ункция changeSceneQ уже
снабжена локальной п е р е м е н ­
ной decision, п о э т о м у данной
f u n c t i o n c h a n g e S c e n e (d e c isio n )
{
переменной присваивает ся
другое имя.
В ы делим связанные
с ист орией элем ент ы
по и д е н т и ф и к а т о р у .
/ / Обновление истории пройденных сцен_»^
var history = d o cu m en tg etE !em en tB yfd ("h isto ry”);
if (curScene != о) {
var
" + decision
........' 1 . 7 . ^ , [[.t.9!^^.ccne + "..•■..t.
history.appendChi!d(decisionElem);
^
Д о б а ви м новый
параграф
к элем ент у
div.
}
eise (
// Удалим ист орию переходов
while (history.firstChild)_
О чист им ист орию ,
уд а ли в все дочерние
узлы .
406
глава 8
Создадим новый
т екст овы й узел
с инф ормацией
о переходе к оче­
редной сцене.
управление страницами
ОтсАе)кивание «Приключений»
Функция фиксации истории в «Приключениях нарисованного человеч­
ка» дает возможность аккуратно отследить логику происходящего.
.аде
— ------
VJelcoweto
STICK FIGURE
adventure
/->4 »
©
J
Л
Vour journey begha at a f a t in ee io» 3.
[f»fce tt e ftw H j [ T . t o l l« m % > |
DedsiM b > S e e * t ; Y a » jOBrtcy Ьедп» * • f t r t m the Л1В 1
—
I
,Приключения еще не
начались, поэт ом у
ист ория пока о т ­
сут ст вует .
Благодаря новой функции
я могу заняться творчеством,
не упуская контроля над де­
ревом переходов.
Ист ория р а ст ет
по м ере продви­
жения по сценам.
V
«I» t o 1
„Sfc,„ И*„ ^
^
Фиксация ист ории
заканчивается в п о ­
следней сцене.
далее *■
407
бесконечная история
Длинное, странное путешествие...
Что ж, пришло время напрячь вашу фантазию и превратить
«Приключения нарисованного человечка» в настоящую длин­
ную игру, на примере которой можно будет осуществить отлад­
ку функции, фиксирующей историю. Ваш нарисованный друг
ждет приключений...
аЖ Н бИ И б
Придумайте ваше собственное продолжение «Приключений нарисованного чело­
вечка» и добавьте соответствующий код.
Для этого упражнения не существует готового решения... Так что получайте удо­
вольствие от самостоятельных приключений!
408
глава 8
управление страницами
Вкладка
Согните страницу
по вертикали, чтобы
совместить два мозга
и решить задачу.
Так что же это такое, DOM?
---------
\% ! хо|>оШо,
а ДВа лучше!
<:-----
D o cum ent I.
Программистам JavaScript не следует
сильно увлекаться DOM.
Эта функция дает доступ
к HTML-тегам, но старайтесь
не слишком ею злоупотреблять.
данные
Объекты как франкенданные
Объекты иауаЗспр! вовсе не так ужасны, как заставил вас
думать доктор. Зато они интересны тем, что соединяют друг с другом
отдельные части языка иауаЗспр!, делая его более мощным. Объекты объ­
единяют данные с действиями в новый тип, намного более «живой», чем
все, что вы использовали раньше. Вы познакомитесь с массивами, которые
сортируют себя сами, со строками, которые умеют искать в своем составе
указанные последовательности символов, и многими другими замечательны­
ми особенностями.
время веселиться
Вечеринка В стиле JavaScript
Давайте устроим вечеринку. Вам нужно пригласить на нее
гостей. Какая информация вам для этого требуется?
Где?
К то?
Когда?
(^^^Приглашенный^
Д анны е п р и глаш ен ия.
Отобразишь!
Д ейст вия для
приглаш ения.
Доставить!
оставить данные
^Отобразить данные
В JavaScript смоделировать приглашения на вечеринку можно, представив
данные в виде переменных, а действия в виде функций. Пр и этом м ы сталки­
ваемся с проблемой, которой не существует в реальном мире, — как разде­
лить данные и действия.
Ч т о?
Д ост авка!
К то?
You’re invited to.
Оборотная
сторона!
A Puzzle Party!
October 24th ^
Date:
Puzzler Ruby
2112 Confounding Street
Location:
95099
иЗА
5280 Unravel Avenue
Conundrum, AZ 85399
USA
Когда?
Л
Где?
Отображение!
Реальные приглашения совмещ;ают данные и действия
в одной сущности, называемой объектом.
412
глава 9
оживляем данные
Данные + действия = объект
в 5ауа8спр1 вовсе не обязательно всегда соблюдать раздельный
режим работы с данными и действиями. Более того, существует
такая уникальная структурная единица, как объект, одновременно
хранящая данные и выполняющая над ними различные действия.
Рассмотрев приглашения на вечеринку с точки зрения объектов
JavaScript, получим следующую схему:
О бъ ект
Данны е
var who;
Д ействия
function display(what, when, where)
{
function display!)
{
function deliver 0
{
var what;
var when;
var where;
Вне объект ов данные
передаю т ся ф ункциям
в виде аргум ент ов.
В объекте invitation данные и функции существуют одновре­
менно и близко связаны друг с другом. Функциям, помещенным
внутрь объекта, уже не нужно передавать данные в виде аргумен­
тов, так как эти функции имеют к данным прямой доступ.
Объекты связывают
данные и функции
в пределах одного
контейнера.
Данные внутри объекта доступны для функции, но скрыты
от внешнего мира. Поэтому объект можно рассматривать
как контейнер, хранящий данные и связывающий их с об­
рабатывающим кодом.
далее >
413
привилегии для членов
Данные — это собственность объекта
Помещенные в объект данные и действия принято называть членами
объекта. Переменные также называются свойствами, а функции мето­
дами. Эти структурные единицы по-прежнему выполняют свои функции,
то есть хранят данные и выполняют над ними различные операции, но
теперь они делают это в контексте определенного объекта.
*^® реме
Свойства и методы
объекта являются
эквивалентами
переменных
и функций.
414
глава 9
Свойства и методы являются «собственностью» объекта. Это
означает, что они хранятся внутри объекта, примерно как дан­
ные внутри массива. Для доступа к свойствам и методам исполь­
зуется специальный оператор, называемый «точкой».
О бъект
С в о й с т в о /М е т о д
Г"
И мя объекта.
обычная точка.
Имя свойства /
или метода.
оживляем данные
Ссылка на члены объекта
Оператор «точка» устанавливает связь между свойством или ме­
тодом и объектом, к которому они принадлежат. Примерно так
же, как имя дает представление о самом человеке, а фамилия,
о том, из какой он семьи.
Вооруженные этими знаниями, соединим данные для объекта
invitation. Для этого нам понадобится перечень его свойств
и оператор «точка»:
Оператор <<точка>> дает
ссьику па свойства или
методы объекта.
Имя свойства.
Имя объекта.
i n v i t a t i o n . who = " P u z z le r Ruby";
i n v i t a t i o n . w h a t = "A p u z z le p a r t y ! " ;
i n v i t a t i o n . w h e n = "O ctober 2 4 th " ;
i n v i t a t i o n . w h e r e = "2112 Confounding S t r e e t " ;
Точка da&m дост уп
к каждому из свойств.
Помните, что, так как данные и действия являются частью
одного объекта, методам не нужно передавать какие бы то ни
было параметры. В результате любые действия с объектом
invitation выполняются очень просто:
i n v i t a t i o n . d e l i v e r ();
. Имя метода.
И м я объекта.
ажнение
Нашим приглашениям не хватает свойства, позволяющего ответить, придет гость на
вечеринку или нет. Напишите код, добавляющий объекту свойство r s v p , а затем вы­
зовите метод з е п с 1 к з у р { ) , ответственный за отправление ответов.
далее >
415
спроси у меня что угодно
ажнение
Вот как выглядит код свойства r s v p , ответственного за отправку ответов
на приглашения.
|''ешше
invitation.rsvp^ = "attending"^
invitationsendRSVPQ ;
О перат ор "т оч­
ка" дает ссылку на
свойство и м ет од
объект а invitation.
Сюда можно пост авит ь также
булевское свойство. В эт ом случае
значение tru e будет означать п р и н я­
т ое приглашение,, а значение
false — отклоненное.
Часгг1°
Задаваемые
БоЦроСь!
Что же такое «объект»? Принадлежит
ли он к какому-нибудь типу данных?
к сожалению, в настоящий момент
JavaScript не позволяет полностью
защитить свойства объекта от доступа
! Объект представляет собой
именованный набор свойств и методов.
Собственно говоря, объект — это
и есть тип данных. Уже знакомые вам
типы включают в себя числа, тексты
и логические значения. Они называются
примитивными. Объекты же считаются
составными типами данных, так
как состоят из набора фрагментов
информации. Соответственно, вы можете
добавить к уже известным вам трем типам
извне. Кроме того, иногда возникают
ситуации,когда к ним требуется
данных еще и тип «object». Именно этому
типу будут принадлежать созданные вами
или встроенные объекты JavaScript.
Я уже несколько раз видел запись
с оператором «точка». Неужели я все
это время пользовался объектами?
свободно расположенный где-то
в сценарии (глобальная переменная).
Q ; Да, Скоро вы поймете, что сложно
писать сценарии на JavaScript, не
прибегая к объектам. Ведь этот язык —
сам по себе лишь один большой набор
S Можно. Но проблема в том, что
доступ к глобальным переменным
возможен из любой части кода. А как
объектов. Например, функция alert
по сути является методом объекта
мы уже упоминали, лучше оставлять
доступ только тем фрагментам сценария,
которым он действительно нужен. Это
написать
416
глава 9
alert().
непосредственный доступ. Впрочем,
основная идея состоит в том, что
помещенные в объект данные логически
связываются с ним. А связанный
с объектом фрагмент информации
является более контекстным, чем
Нельзя ли вместо свойств
и методов объекта просто использовать
глобальные переменные и функции?
позволяет предотвратить случайное
редактирование данных.
вы можете работать только с функцией
3 ' Я совсем запутался. Вы пытаетесь
сказать мне, что функции это на самом
деле методы?
; Да, хотя думать о функциях
подобным образом вам пока непривычно.
Как вы знаете, функция — это фрагмент
кода, который можно вызвать по имени.
1\Летод представляет собой функцию,
помещенную внутрь объекта. Другое депо,
что с объектами связаны все функции.
Например,
alert
{) — это
одновременно функция и метод, что
объясняет возможность вызвать ее
двумя способами. В данном случае, как
и в ряде других, в качестве объекта
выступает окно браузера. Так как этот
()
window, то есть для ее вызова можно
window . alert () . Объект
window представляет собой окно
браузера и в явном виде ссылаться на
него необязательно. Собственно, поэтому
объект по умолчанию используется при
вызове методов, если в явном виде не
указано иное, можно считать, что метод
alert
() является функцией.
оживляем данные
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
ь
Объектами называют особые структуры, объеди­
няющие данные и обрабатывающий их код.
Помещенные в объект переменные превращаются
в свойства, а функции — в методы.
С практической точки зрения объект — это все­
Для ссылки на свойство или метод достаточно ука­
го лишь переменные и функции, объединенные
в структурную единицу.
зать имя объекта, затем - точку, а затем свойства или метода.
имя
Блог для любителей головоломок
Инициатором вечеринки, для которой м ы создаем приглашения,
является І^би — фанатка головоломки «Кубик Рубика». Она мечтает
о встрече с людьми, разделяюш;ими ее страсть. При этом Руби хотела
бы не только устроить вечеринку для единомышленников. Она решила
завести блог YouCube, посвяш;енный головоломкам.
Я слышала, что объекты позволят
упростить редактирование моего
кода. Значит, у меня останется боль­
ше времени на головоломки!
Руби слышала, что вJavaScript поддерживаются специаль­
ные объекты, так как это позволяет создавать более устой­
чивый и управляемый код. Еще она слышала, что многие
блоги устаревают, потому что пользователи прекращают
ими заниматься. Поэтому Руби решила с самого начала
создать объектно-ориентированный сценарий блога
YouCube, который обеспечит ее прекрасное будущее.
О бъ ектноор иен тир ов анн ы й
YouCube
Больш е вр ем ени
на головолом ки!
далее >
417
по-старинке
Анализ блога YouCube
Руби ведет обычный рукописный дневник. Читая чужие блоги, она
узнала, что записи состоят из даты и текста, но ей пока непонятно,
как сохранить эти данные при помощи JavaScript. А ведь Руби так
устала писать на бумаге!
YouCube, н а ­
писанный
вручную.
0 8 /1 4 /2 0 0 8
Q ot th e n e w си б е I o r d e re d . I t s a reaC
jje a r C
0 8 /1 9 /2 0 0 8
S o C v e d th e n e w cuB e B u t o f co u rs e , n o w I ’m
B o r e d a n d s fio p p in g f o r a n e w one.
Aam a
записи'
•
0 8 /1 6 /2 0 0 8
^ M a n a g e d t o g e t a h e a d a c h e toiCing o v e r
th e n e w cuBe.
Текст записи.
g o t t a najy.
0 8 /2 1 /2 0 0 8
f o u n d a 7x 7^7 cuBe f o r saCe onCme. y ik e s!
T h a t one couCd Be a Beast.
Руби отчсшнно нужен непосредственный механизм сохранения
набора данных в форме (дата + текст) с последующим доступом
к нему. В ы уже слышали подобные слова, когда м ы говорили об
объектах JavaScript, ведь именно объекты позволяют соединить
различные фрагменты информации в целостную структуру.
Дата зап и си + Тело запи си = Объект Blog
418
глава 9
Специальный объект
объединяет в общую
структуру два фрагмен­
та блога.
оживляем данные
Специальные объекты
в JavaScript достаточно стандартных объектов, с частью которых м ы
познакомимся в этой главе. Но, хотя эти объекты несомненно полезны,
бывают случаи, когда их функциональности недостаточно. Примером
такого случая является наш блог YouCube. Ведь проблема сохранения
данных в нем не может быть решена при помощи встроенных объек­
тов JavaScript. А значит, нам не обойтись без специальных объектов.
Строки — эт о
тоже объекты!
И массивы
тоже объекты.
Если бы не было _
объект ов, можно
было бы сохранят ь
з а т е и блога в виде
двумерного массиба.
О бъект В!од служ ит
сост авным т и п о м дан­
ных, объединяя два ф р а г­
м ент а информации.
Специальные объекты позволяют добавлять к JavaScript функции,
удовлетворяющие вашим потребностям. В случае Руби специальный
объект моделирует записи блога, представляя дату и тело записи
в виде своих свойств. Методы предоставят возможность смоделиро­
вать поведение записей блога, сделав процесс их создания и редак­
тирования более понятным.
Н о перед тем, как воспользоваться таким специальным объектом,
нужно понять механизм его создания...
далее >
419
осторожно: идет ст роит ельст во
Конструктор
Так как с объектами связаны данные, процесс их создания дол­
жен сопровождаться присвоением начальных значений. Для
этого используется метод, называемый конструктором. Для
каждого специального объекта существует свой собственный
конструктор, имя которого совпадает с именем объекта. Имен­
но этот метод отвечает за присвоение начальных значений.
Поэтому при создании специального объекта так важно напи­
сать корректный конструктор.
За создание объекта
отвечает конструк­
тор.
свойст ву
ц /методы-
С озданы
function displayO
function deliver О
{
I„»itatl.n(w ho, w b a t, w hen, w here);
. Имя конст рукт ора
совпадает с им енем
объекта.
С войст ва и ни ц ш
Iлизированы.
Н о вш обьект гот ов
к использование^
Invitation
.....
who = "Somebody";
what = "Something";
when = "Sometime";
where = "Somewhere";
var who = "Somebody";
var what = "Something ,
var when = "Sometime ,
var where = "Somewhere
Объект с конструктором создается при помощи оператора new.
Этот процесс напоминает вызов метода. Собственно говоря,
процедура создания объекта осуществляется через вызов его
конструктора. Н о нельзя сделать это непосредственно, обяза­
тельно следует пользоваться оператором new.
■Оператор n ew создает
новый объект.
v a r i n v i t a t i o n = new Invitation("Somebody", "Som ething", "Sometime", "Somewhere");
^
420
глава 9
Новый объект со краняет ся в эт ой
переменной.
конст рукт ора
совпадает с им енем
метода.
^
Свойства задаю т ся п у т е м
— передачи аргцм ент ов ко нст рукт ору.
оживляєм данные
Структура конструктора
Конструктор задает свойства объекта вместе с их начальными значения­
ми. Для этого используется ключевое слово this. Оно связывает свойство
с объектом и одновременно задает его начальное значение. С английского
слово переводится как «это» и полностью оправдывает свое значение — вы
создаете свойство, принадлежащее «этому» объекту, а не просто локальную
переменную внутри конструктора.
Клю чевое слово this function Invitation (who. what, when, where) {
от личает свойство
объект а о т обычной
this.who = who;
переменной.
Л
this.what = what;
this.when = when;
this.where = where;
}
Имена конст рукт оров,
как и имена объек­
т ов. всегда пиш ут ся
с большой буквы.
А р гу м ен т ы к о н ст р ук­
т ора назначаются
новым свойствам.
Тело конст рукт ора за
клю чает ся в ф игурные
скобки, как и у любой д р у ­
гой функции.
Свойства объекта создаются и инициализируются конструктором
при помощи оператора «точка» и ключевого слова this. Это
ключевое слово дает конструктору понять, что он создает свой­
ства определенного объекта. В нашем случае результатом работы
конструктора стало создание четырех свойств, которым были
назначены значения, переданные в качестве аргументов.
Свойства объекта
в конструкторе
созданугся при
помонщ ключевого
слова this.
заставим это работзть
Возьми в руку карандаш
Решение
Вот как выглядит конструктор для объекта Blog, создающий
и инициализирующий дату и текст каждой записи.
И мя кон­
ст рукт ора
совпадает
.function B!og(bodij, date.) {
с им енем о 5 ъ - ......................
...... ч
,, . , ,
, ,
^
Т
е
к
с
т
записи и дата
екта.
...Р.у.‘.^.'..Р.^У..7..У.9.4!^....
.
~~~~—- — передаю т ся в каче-
^
Клю чевое
слово this
от сы лает
к свойст вам
объекта.
................
tkis.dau =
}
Д л я инициализации свойст в
использую т ся переданные
о конст рукт ор аргум ент ы .
Создание объектов blog
Объект Blog постепенно принимает некую форму, хотя он еще не
создан. В теории все прекрасно, но его существование пока только
гипотеза, которую нам предстоит доказать. Конструктор форми­
рует модель объекта, но физически у нас ничего нет, пока м ы не
воспользуемся оператором new, который создаст объект, вызвав
его конструктор. Ра^мотрим эту процедуру на практике
О бъект
ßlog.
Продолжим на прим ерах,
которые можно скачат ь на
n tt p : / / w w w .headfirstlabs.com /
books/hfjs/.
0 8 /1 4 /2 0 0 8
g o t the n e w cu b e I o rd e re d . I t s
a reatpe^dT^'
v a r b lo g E n try = new BlogC'G ot th e new cube I o r d e r e d . . . " ,
Д л я создания о б ьект а вызывается
конст рукт ор ßlog().
422
глава 9
Рукописная
запись 6 блог.
" 0 8 /1 4 /2 0 0 8 " );
оживляем данны е
Часто
Ч аД аБ аеМ ы е
БоІїросГьі
Я не понимаю, объект создается
оператором n e w или конструктором?
; И тем и другим! Оператор n e w
инициирует процедуру создания объекта
и отвечает за вызов конструктора. При
этом простой вызов конструктора как
обычной функции без оператора n e w не
приведет к созданию объекта. Точно так
же бессмыспенно использовать оператор
n e w без конструктора.
Всем ли специальным объектам
требуется конструктор?
Исключением является случай создания
чисто организационного объекта,
Б
• Что такое t h i s ?
состоящего из набора методов, не
влияющих на свойства. Такой объект
технически можно получить и без
Q l Это ключевое слово, используемое
для ссылки на объект. Точнее, это ссылка
на объект изнутри самого объекта. Да,
конструктора. Другое депо, что подобные
структуры нельзя считать хорошей
практикой объектно-ориентированного
звучит несколько странно. Но представьте,
что вы потеряли часы в переполненной
комнате, а кто-то их нашел. Когда их вам
покажут, вы закричите «Это мои часы!»
Словом «мои» вы ссылаетесь на себя.
Более того, это слово указывает, что
именно вы являетесь собственником
программирования, ведь они
представляют собой не более чем набор
связанных друт с другом функций. Но
даже при таких условиях иауаЗспр! сам
использует организационные объекты для
группировки математически связанных
задач, как вы увидите в этой главе.
часов. Ключевое слово t h i s
аналогичным образом подразумевает
собственность объекта. В результате
запись t h i s . d a t e означает, что
SДа. Ведь именно конструктор
отвечает за задание свойств объекта,
свойство d a t e принадлежит тому
объекту, в коде которого оно появилось.
соответственно, без него объект не
получит никаких свойств. А значит, его
существование будет бессмысленным.
Возьми в руку карандаш
08/14/2008
^
^ r*v
Создайте массив объ ектов B l o g в пе рем енной b l o g , котор ой
в качестве н ачального значения были присвоены записи блога
YouCube. Записи полностью переписы вать не н уж но, достаточно
огр ан и чи ться первы м и словами.
tfie new cuBe. I ordered. I t s
a reaCpearC.
got
08/19/2008
SoCved the new cube but ot
course, now I ’m bored and
sfiofrping f o r a new one.
08/16/2008
ManagecC to get a fieacCache
toiCing o v e r Ше new cube,
gotta nap.
08/21/2008
fo u n d a
f o r sale
onCtne. yi^es! That one could be
a 0east.
7 x 7 x 7
далее *
423
решение упражнения
Возьми в руку карандаш
^В о зь м і
rv
Решение
Вот процедура создания массива объектов Blog в переменной
blog, которой в качестве начального значения были присвоены
записи блога YouCube.
08/14/2008
^
got the new cube I ordered. It
a reaCpearC.
va r blog =
^
^ ordered...", "OS/X4-/ZOOS"),
08/19/2008
SoCvedthe new сиве h u t o f
course, now I Ш vored and
shopping f o r a new one.
BlogC'Solved the new cube b u t of course...", " 0 8 /1 9 /Z 0 0 8 " ) ,
^
new B io g f Managed to g e t a headache toiiing...", " 0 S /1 & /Z 0 0 8 " ),
new BlogC'Found a 7x7x7 cube for sale...", " 0 8 / Z t /Z 0 0 8 " )
* 08/16/2008
M a n a a e d to get a headache
toiCing o v e r the new cube,
gotta nap.
............................ ]i..............
Каждая запись созда■ется как объект Blog,
содержащий т екст
и дату.
08/21/2008
f o u n d a 7X 7X 7^u6e f o r sale
,
onCine. yike s! That one could be
a beast.
Д анны е, хранящиеся
в каждом объект е
Blog, аккурат но о т о ­
бражаются на с т р а ­
нице YouCube.
Версия YouCube 1.0
Скомбинировав массив объектов Blog с кодом JavaScript,
отображающим данные, м ы получим первую версию страни­
ц ы YouCube. Руби знает, что работа еще далека от заверше­
ния, но первые результаты ее радуют.
^ ^
YeuCabe - The
fe*" Cube Pi
YouCube - The Blog for Cube Putilers
Мне нравится, как объ­
ект Blog скомбинировал
дату и текст на странице
УоиСиЬе.
» b e I o r i e t e d .I t 's a таlpe^lй•
&
S
new cube
bu. coursenow
of
.
Г»
ь о ш і and Л оррш в tor a
M w
get a headaehe toBtag over «1» new cube. G o » nap.
f t * ^ x 7x 7 cube tor sale o n ta e . Ylkesl That one couM be a beast.
_ 5h w A ! l« o g E n tfi« 1
Посмотрим, какой же код вдохнул жизнь в объекты Blog
и сделал страницу YouCube 1.0 реальностью...
424
глава 9
one
оживляем данные
Цодроёно HJ>o
<html>
<head>
<title>Y ouC ube - The Blog f o r Cube P u z z l e r s < / t i t l e >
< s c rip t ty p e = "te x t/ja v a sc rip t">
11 Конструктор объекта Blog
f u n c t i o n B log(body, d a te ) {
/ / A ssign t h e p r o p e r t i e s ^
t h i s . b o d y = body;
t h i s . d a t e = d ate;
}
К онст рукт ор В1од() соз■дает два свойст ва блога.
Массив обьект ов
■ßlog.
/ / Глобальный массив записей в блог
v a r b lo g = [ new BlogC'G ot t h e new cube I o r d e r e d . . " , " 0 8 /1 4 /2 0 0 8 " ),
new B lo g ("S o lv ed t h e new cube b u t o f c o u r s e . . . " , " 0 8 /1 9 /2 0 0 8 " ),
Ф ункция show BlogQ
new Blog("Managed t o g e t a headache t o i l i n g . . . " , " 0 8 /1 6 /2 0 0 8 " ),
вы водит за п и си блога
new B log("Found a 7x7x7 cube f o r s a l e o n l i n e . . . " , "08/21/2008")
под ат р и б ут о м , div.^
];
список записей в блог
func;b<^n showBlog (numEntries) {
При необходимости редактируем количество записей для показа в сего блога
f ( ! num Entries)
num Entries = b l o g . l e n g t h ;
Если количест во выводимых за
~~
—--------- один раз записей не передано
/ / Показать записи блога
в качест ве аргум ент а, выводим
v a r 1 = 0 , b lo g T ex t = "";
все записи.
w h ile (1 < b l o g . l e n g t h && i < num Entries) {
/ / Используйте серый фон для всех остальных записей блога
i f ( i % 2 == 0)
----- b lo g T ex t += "<р s t y l e = 'b a c k g r o u n d - c o l o r :#ЕЕЕЕЕЕ'>";
e lse
__________ Изменим фоновый цвет записеи
b lo g T ex t += "<р>";
блога, чтобы облегчит ь их чтение.
/ / Генерируем и форматируем HTML-код блога
b lo g T ex t += " < strong > " + b l o g [ i ] . d a t e + " < / s t r o n g X b r />" + b l o g [ i ] . b o d y + "</p>'
І++;
}
11 Располагаем HTML-код блога на страніdocum ent.getElem entB yld("blog")-innerH TM L = b lo g T e x t;
П о м ес т и м код
■ф о р м а т и р о ва н н о й
записи блога под
а т р и б у т о м div.
< /scrip t>
</head>
Изначально пуст ой ат р и б ут
div заполняет ся о т ф о р м а ­
<body onload="show B log(5) ; ">
<h3>YouCube - The Blog f o r Cube P u z z le rs < /h 3 >
т ированны ми записями.
<img s rc = "c u b e .p n g " alt="YouCube" />
■
4 Q1V ii d
a=
<div
= "iJ-LUy
b l o g ^" Vx//Ud- Li vV x>'
< in p u t ty p e = " b u tto n " id = " sh o w a ll" value="Show A l l Blog E n t r i e s " o nclick = "sh o w B lo g ( ) ; " />
</body>
^
</htm l>
При щелчке на эт ой
кнопке ст ановят ся ~
видимыми все записи
блога.
далее р
425
бесконечны е «почему»
_
Ч асто
^аД аБ аеМ ы е
B o T lp o C j, !
Зачем блогу YouCube кнопка Show
АН Blog Entries?
Почему для показа записей блога
используется свойство innerHTML
вместо методов DOM?
Почему объект B l o g не имеет
методов?
0 1 Хотя методы DOM и являются пред­
почтительными с точки зрения совме­
стимости с веб-стандартам, реализация
что есть более первоочередные задачи,
которые следует реализовать, поэтому до
Q ; в текущем состоянии блога эта
кнопка действительно не нужна. Ведь
у нас всего четыре записи. Но по мере
заполнения блога потребуется ограничить
количество записей, отображаемых
на главной странице. В противном
случае загрузка будет занимать слишком
много времени. Поэтому по умолчанию
показываются только первые пять записей.
Кнопка Show АН Blog Entries позволяет
вывести все записи на одной странице.
Q ; Их нет на данном этапе. Дело в том,
динамически генерируемого отформати­
рованного HTML-кода с их помощью будет
методов объекта B lo g мы просто пока
не добрались. Но не волнуйтесь. Методы
являются существенной частью любого
слишком громозкой. Ведь каждый тег < р >
хорошо сконструированного объекта,
или < s t r o n g > должен быть родитель­
ским по отношению к узлам с содержимым.
и объект B lo g в этом отношении не
исключение.
Свойство же innerHTML позволяет
значительно упростить код блога YouCube.
Беспорядочный блог
Б л о г Y o u C u b e 1.0 вы гл яд и т х о р о ш о , н о это го н е л ьзя сказать о п о ­
р я д к е его зап и сей . Руби зам ети л а, ч т о в н а с т о я щ и й м о м ен т о н и
о т о б р а ж аю т ся в то м п о р я д к е , в к о т о р о м б ы ли с о х р ан е н ы , в то
в р ем я как с х р о н о л о г и ч е с к о й т о ч к и зр е н и я п ер в ы м и д олж н ы
б ы ть п о к азан ы сам ы е н о в ы е зап и си .
я только что осознала,
что не всегда соблюда­
ла хронологию записей.
И теперь у нас проблема!
Самые свежие записи
ДОЛЖНЫ показываться
первыми.
^
for Cub,
viCube - The Blog for Cube Pu^alers
^
‘ »'140008
Got t e new cube I ordered. Its a rca} peail.
П ользоват ели
п ри вы кли в и ­
д е т ь н а вер х у
са м ы е свеж ие
записи.
s/imom
8 /21/2008
Found a 7x7x7 cube for sale oniine
Show A» 3loaEnM»c I
Done
426
глава 9
xu
That one could be a beast.
оживляем данны е
Необходимость сортировки
П р о б лем у с п о р я д к о м за п и с ей м о ж н о р е ш и т ь путем с о р т и р о в к и
м асси ва b l o g п о д ате. Т ак как Jav aS crip t п о д д е р ж и в ае т ц и кл ы и ср ав­
н ен и я , м ы м о ж ет п р о с м о т р е т ь в ц и кл е все зап и си , с р а в н и в и х даты ,
и о т с о р т и р о в а т ь в о б р ат н о м х р о н о л о ги ч е с к о м п о р яд ке.
М еняем м е с т а м и
Blog
э т и две за п и си ,
т а к как вт о р а я
оолее свежая.
Э т а зап и сь должна
о к а з а т ь с я на п е р во м
м е с т е , ка к сам ая
О
П р о с м о тр и м
м ассив в ци кле.
©
С р авн и м дату каж дого о б 'ь е к 1’а
B lo g со следую щ им о б ъекто м .
е
Е сли следую щ ая за п и с ь я в л яется б о лее
с веж ей , м ен я ем за п и с и м естам и.
П о д о б н а я с о р т и р о в к а и м е е т с в о и д о ст о и н с тв а и, к аж ется,
д о л ж н а н е п л о х о р а б о т а т ь , есл и м ы как следует продум аем п р о
цедуру с р а в н е н и я дат.
Подождите! Как нам понять, какая
дата более поздняя, если они со­
хранены в виде строк?
------
Сохраненная в виде строки дата перестает быть датой.
И та к , п р и ду м ан н ая н ам и с т р а т е г и я с о р т и р о в к и столкнулась
с се р ь е зн ы м п р е п ят с т в и е м . Н е в о зм о ж н о с р а в н и т ь с т р о к и
« 0 8 / 1 4 / 2 0 0 8 » и « 0 8 / 1 9 / 2 0 0 8 » и п о н я т ь , какая д ата б олее
р ан н я я . Н е т , м ето д и к а с р а в н е н и я с т р о к сущ ествует, н о о н а н е
п о м о ж ет нам со п о с т а в и т ь д н и , м есяц ы и годы , с о о т в ет с т в е н н о ,
в н аш ем случае о н а б ессм ы сленна.
З н ач и т , п р еж д е ч ем думать о с о р т и р о в к е , нуж но и зм е н и т ь спо­
соб х р а н е н и я д ат в блоге.
как вам наши даты?
Объект для gam
Руби тр еб у ется т а к о й сп о со б с о х р а н е н и я дат, к о т о р ы й д аст в о зм о ж ­
н о с т ь их д ал ьн ей ш его с р а в н е н и я. Д р у ги м и словам и , д ата д о л ж н а
в ес ти себя как дата. А ведь а н а л о ги ч н ы е сл о ва м ы го в о р и л и в отнош е- Д а т а п ервой
НИИ объекта! И д ей с тв и те л ь н о , в Jav aS crip t сущ;ествует в с т р о е н н ы й
Записи в 5лог.
о б ъ е к т D a te , в п о л н е п о д х о дящ и й д ля н аш и х нужд.
Д а та
^
Л
Г
М ет оды з а ­
дания даты.
і М ет оды
У п олучения
дат ы .
Встроенный объект Date
представляет некий
момент времени.
О б ъ е к т D a te п р е д с та в л я е т о п р е д е л ен н ы й м о м е н т в р ем ен и ,
в ы р а ж е н н ы й в м иллисекундах, и я в л я е т с я с т ан д а р т н о й ч астью
Jav aS cript. Х отя с в о й с т в а это го о б ъ е к т а и исп ользую тся, вам о н и
н е видны . П о это м у р а б о т а с о б ъ ек то м D a te осущ ествл яется и с­
к л ю ч и те л ьн о ч е р е з его м етоды .
О б ъ е к т D a te , к ак и р а н е е о б ъ е к т B lo g , со зд ается п р и пом ощ и
о п е р а т о р а new. В от п р и м е р с о зд ан и я об ъ екта, п р ед ставл яю щ его
текущ унздату и врем я.
С охранение — -
о б ъ ект а p a te
в перем енно й .
var
С оздание о б ъ е к т а
P a te п ри п ом о щ и
Время внутри объекта
Date выражено
в миллисекундах.
глава 9
=
new
DateO;
Новый о б ъ ек т P a te
. предст авляет т е к у '
щуьо д а т у /в р е м я .
о п ер а т о р а new .
Д а т а пер ед а ет ся
к о н с т р у к т о р у jв виде т екст о во й
ст р о ки .
428
now
Э то т о б ъ ек т D a te со зд ан и и н и ц и а л и зи р о в а н с текущ им и д ат о й
и врем енем . О б р ат и т е вн и м ан и е н а то, ч то син такси с н ап ом и н а­
е т вы зов м етод а и л и ф ункц ии, так как вам п ри ход и тся вы зы вать
ко н структор об ъ ек та D a te . К онструктору в кач естве аргум ента
м о ж н о п е р е д а ть строку с д ато й , о т л и ч н о й о т текущ ей. С каж ем ,
в о т о б ъ е к т D a te с д ат о й п е р в о й зап и си в блоге Y ouC ube:
v a r blo gD ate = new D a t e ( " 0 8 /1 4 /2 0 0 8 " ) ;
оживляєм данны е
Вычисление времени
О д н и м и з сам ы х б о льш и х д о ст о и н с тв о б ъ е к т о в я в л я е т с я и х с п о со б н о сть
у п р ав л я ть сво и м со с то я н и е м . Н а п р и м е р , п р е д став ьте , как сл о ж н о бы ло
бы вручную в ы ч и с л я т ь к о л и ч е с т в о д н е й меж ду двумя датам и. П о т р е б о ­
валось бы п р е о б р а зо в а т ь дату в д н и с и зв е с т н о й т о ч к о й о т с ч ет а , а такж е
учесть, ч т о с н ач ал о м года н а ч и н а е т с я н о в ы й ц и к л о тсч ета. П оэтом у
мы отдад и м эту задачу н а откуп о б ъекту D a te . П о с м о т р и т е , к ак л егко он
П р е о б р а зо в а с н е й сп р ав л яется:
Э т а ф ун кц и я п р и н и м а е т
в к а ч е с т ве а р г у м е н т о в
два о б ъ е к т а D a te.
function getDaysBetween(datel,
date2)
var daysBetween = <date2 - datel)
ние м и л л и се к у н д
о секун ды , з а т е м
о м и н у т ы , часы
и наконец в дни!
{
/ (1000 * 60 * 60 * 24);
return Math, round (daysBetween) ;
}
В е р н е м р е з у л ь т а т п о сле
округл ен и я ... М е т о д ro u n d Q
п ринадлеж и т о б ъ е к т у Ма±!л,
с к о т о р ы м м ы ещ е п о зн а к о ­
м и м с я в э т о й гл а ве.
getDaysBetween(datel, date2);
аж нш е
Э т о т п р о с т о й , но
м ощ ны й код д е л а е т
всю р а б о т у!
Д а н н а я ф ун кц и я д ем о н с тр и р у ет нам , н аск о л ьк о м ощ ны м
я в л я е т с я о б ъ ек т D a te , н а п р о с т о м ф р а гм е н т е код а —в ы ч и ­
та н и и . С л о ж н ы е в ы ч и с л ен и я р а зн и ц ы меж ду двумя д атам и
ск р ы т ы вн утри о б ъ ек та. Н ам в ы д ается р езул ьтат в ы ч и ­
т а н и я , п р ед с та в л я ю щ и й с о б о й к о л и ч е ст в о м иллисекунд
между указан н ы м и датам и. Д о с т а т о ч н о п р е о б р а зо в а т ь м ил­
лисекун ды в д н и и о кругл и ть резу л ьтат —и у нас под рукой
п о л е зн ей ш а я ф у н к ц и я , которую м ож н о вы зы в а ть в ся к и й
р а з в п о д о б н ы х случаях.
Создайте два объекта D a te для первых двух записей блога YouCube.
Затем при помощи функции g e t D a y s B e t w e e n () вычислите, с каким
промежутком они написаны, и выведите результат в отдельном окне.
далее >
429
реш ение упражнения
Jjfe«V
Вот как при помощи функции g e t D a y s B e t w e e n () вычислить промежуток
ТП ТраЖ Н бН И б
первыми записями в блоге, которые представлены при помощи
?еш ш е
Создание о б ъ е к т а
P a te для двух зап и сеи ■
блога.
Щ Г Ы 9 3 Р .Ш .^ ..Т .
К
var^ bJoßP ateZ ,~ n ew _ P a t e ( " 0 8 / 1 <R/Z008");
.^.y..t. 0 f :'tp ^ y s ß e tw e e n (h lo g P a te l, blogP ateZ ) + " days.");
Ф ункция
( в о з в р а щ aа eе m
т
разн иц у-
I
J
The dates are separated by S days.
А б а о б ъ е к т а P a te
п ер ед а н ы ф ун кци и
о к а ч е ст ве
аргум ен т ов.
f~ 0 iT 3
Пересмотр gam В блоге
Х отя м ы и п о зн а к о м и л и с ь с о б ъ ек то м D a te , п о зво л яю щ и м
л е гк о у п р ав л ять датам и , д аты в наш ем о б ъ е к т е B l o g п о к а ещ е
со х р а н е н ы в ви д е стр о к. А зн а ч и т , в о с п о л ьзо в а ться п реи м ущ е­
ствам и , к о т о р ы е нам д ае т о б ъ е к т D a te , м ы м ож ем т о л ь к о п осл е
п р е о б р а зо в а н и я дат.
Дата
Блог
Got the new
cube I ordered.
It’s a real pearl."
С во й ст во d a te о б ъ ­
е к т а Blog нужно
п р е о б р а зо в а т ь из
ст роки в объект
P a te .
"08/ 14/ 2008"
В о п р о с в том , м ож н о л и в св о й ств е d a t e о б ъ е к т а B lo g х р а н и т ь
о б ъ е к т D a te вм есто строки ?
430
глава 9
оживляем данные
Объект Внутри другого объекта
Н а п р и м е р е н аш его бло га м ы увидим , как о д н и о б ъ е к т ы м огут
с т ан о в и т ь с я к о н т е й н е р а м и для других. У о б ъ е к т а B lo g есть два
сво й ств а, к о т о р ы е , в свою о ч ер е д ь , я в л я ю т ся о б ъ е к там и S t r i n g .
О н и н е в ы гл яд ят к ак о б ъ ек ты , п отом у ч т о со зд аю тся как л и т е р а ­
л ы , п р о с т ы м ц и т и р о в а н и е м с т р о к и тек ста. О б ъ ек т ы D a te н е столь
ги б ки и потом у со зд аю тся п р и п о м о щ и о п е р а т о р а new.
С т р о ко вы й л и т е р а л
авт ом ат ически со зда ­
е т о б ъ е к т S trin g .
Ч т о б ы со зд ать св о й с тв о б л о га d a te в ви д е о б ъ е к т а D a te , нам то ж е
п о тр еб у ется о п е р а т о р new, к о т о р ы й сф о р м и р у е т н о в ы й о б ъ е к т
О б ъ е к т Blog создает ся
в п р о ц е с с е со зд ан и я о б ъ е к т а B lo g . Э то о п и с ан и е м о ж ет звучать
о п е р а т о р о м n ew .
пугаю щ е, н о код в ы гл яд и т д о ст а т о ч н о п р о сто .
iiC.------
v a r b lo g E n try = new Blog("N othing going on b u t t h e w e a t h e r . " .
new D a t e ;
1 0 /3 1 /2 ,0 0 8 "));
V
Э то т код п о к а зы в а ет, каким о б р азо м зап и сь в б л о ге Y o u C u b e
со зд ается в виде о б ъ екта, со дер ж ащ его два други х о б ъ ек т а
( S t r i n g и D a te ). Р азум еется, для п о л н о й и м и та ц и и б ло га нам
п о тр еб у ется м ассив о б ъ е к т о в B lo g .
Блог
Строка
С во й ст во b o d y.
О б ъ е к т D a te со зда ет ся
и п ередает ся кон ст рукт о
' р у вЪ дО т акж е п р и п о м о ­
щи о п е р а т о р а n ew .
Оператор new создает
объекты с помощью
конструктора.
С войст во d ate.
Возьми в руку карандаш
Перепишите код создания массива объектов B lo g с учетом
того, что каждая дата теперь является объектом D a te . Текст
записей давайте в сокращенном виде.
далее ►
431
реш ение упражнения
Возьми в руку карандаш
'ешение
Вот ка к вы глядит код создания массива объ ектов B l o g с уч е ­
том того, что каждая дата теперь является объ е ктом D a te .
Все записи до сих
п о р со зд аю т ся как
о б ъект ы Blog.
. К‘?.^Г.к{93.г.. .
[
Blp.e(,“. 9 p . t . t h f . 9.4'^р.. !
.
. ne w i ^ a t e ( " 0 8 / ^ 4 / 2 0 0 8")),
b u t o f co u rse...“, n e w D a te ( " O S /l я /Z O O 8")),
^ h e a d a c h e toiling...", n e w D a te ( " 0 8 / 1 6 /Z 0 0 8 " ) ) ,
n e w BlogC’Found a 7 x 7 x 7 cu be fo r sale...", n e w D a te ( " 0 8 /Z X /Z 0 0 8 " ) ) ]■
......................................... ........................
С т роковы е л и т е р а л ы
п р екр а сн о подходят для
п р е д с т а вле н и я т е к с т а
зап и сей блога.
J
А а т а для каждого об ъект а
-B lo g т е п е р ь создает ся как
о б ъ ект Date.
/
_
ча а в о
■ ^аД аБ аеМ ы е
‘
Б о г ц р 'о с ь !
Почему даты в объекте D a t e сохраняются
в миллисекундах?
! Ну, во-первых, объект D a t e представляет некоторый
момент. Если бы для вселенной можно было нажать кнопку
Pause, мы получили бы такой момент. Но чтобы объяснить
другим людям, когда случился этот момент, требуется некая
точка отсчета. В качестве такой точки выбрано 1 января
1970 года. Теперь нужно показать сдвиг относительно этой точки
Пусть он будет равен 38 годам, 8 месяцам, 14 дням, 3 часам,
29 минутам и 11 секундам. Но это слишком громоздкий способ
представления данных. Проще выбрать единицу измерения,
которая в состоянии представить самую маленькую долю.
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
ш
■
Именно поэтому мы пользуемся миллисекундами,
и вместо набора различных единиц у нас появляется
1,218,702,551,000 миллисекунд. Да, это много, но иауаЗспр!
умеет работать с большими числами.
Должен ли я вручную преобразовывать миллисекунды
при работе с объектом D a te ?
Q ; Зависит от ситуации. Объект D a t e снабжен набором
методов, умеющих извлекать значимые части, что избавляет вас
от необходимости иметь дело с миллисекундами. Но, если нужно
определить разницу между датами, от миллисекунд вам никуда
не деться.
*їч
Стандартный объект D a t e представляет момент
Объект D a t e умеет совершать математические
времени, выраженный в миллисекундах.
операции с датами и даже сравнивать их друг
Объект D a t e снабжен методами доступа к различ­
ным фрагментам даты и времени.
с другом.
В отличие от объекта s t r i n g объект D a t e созда­
ется при помощи оператора ne w .
432
глава 9
оживляем данные
Бесполезные даты
П р е о б р а зо в а в св о й с тв о d a t e о б ъ е к т а B lo g в о б ъ ек т D a te , Руби
п р и го т о в и л а с ь вплотную за н я т ьс я с о р т и р о в к о й зап и сей . Н о
о н а столкнулась с н о в о й п р о б л е м о й —д аты вы гл яд я т ч е р е с ­
чур сл о ж н о . Руби п о д о зр е в а е т, ч т о ч и т ат е л я м б л о га н е важ н а
и н ф о р м а ц и я о в р е м е н н о й зо н е , в к о т о р о й о н а н ах о д и тся, и это
будет о т в л е к а ть их. И так, нам нуж но б о л ее д етал ьн о р ассм о­
т р е т ь проц едуру встав к и в бло г о б ъ е к то в D a te !
Д а т ь / записей
слишком громоздки
и дают избыточную
информацию!
YouCube - The Юоа for C ube ^uzziers
YouCube - The Blog for Cube Pim lm
----Thu Aeg 14 7 Ш
Got Ле new cttbe I orfcKd. It s a ю й peari.
« I «РРІ.Ї
Ввод объекта Date имел
смысл, но результат выгля­
дит ужасно. Не помню, чтобы
я программировала подобное
форматирование.
Found a
Show All
BtoaEntries
Done
Д ело не только
в ужасно выглядящ их дат ах. З ап и си
блога все еш,е не
упорядочены!
Руби о за д ач е н а с тр ан н ы м ви д о м дат в бло ге Y o u C u b e, ведь
о н а н е п и сал а ко д а д ля о т о б р а ж е н и я и х в п о д о б н о м виде.
О н а всего л и ш ь п р е о б р а зо в а л а с т р о к и с д атам и в о б ъ ек ты
D a te . Н еу ж ел и эт о за го в о р зл ы х сил JavaS cript?
далее >
433
должен быть другой способ
Преобразование объектов 8 т е к с т
к счастью , эт о н е зл ы е си л ы нуж но о б в и н я т ь в б езо б р азн о м ви д е дат.
Б о л е е то го , эт о о б ы ч н о е п о в е д е н и е о б ъ е к то в Jav aS crip t, о т в еч аю щ и х за
ф о р м а т и р о в а н и е дат, - т о е с ть даты ф о р м ат и р у ю т ся автом ати ч ески !
Э то р а б о т а е т следую щ им об разом : все о б ъ е к т ы Jav aS crip t обладаю т
м ето д о м t o S t r i n g ( ) , о б есп еч и в аю щ и м и х те к с т о в о е п р ед ставл ен и е.
И н аш и д аты я в л яю тся р езу л ьтато м д е й с тв и я м етод а t o S t r i n g () о б ъ ­
ек та D a te .
v a r blogD ate = new D a t e (" 0 8 /1 4 /2 0 0 8 " );
a lert(b lo g D ate.to S tr in g {
П р о б л е м а в том , ч то м етод t o S t r i n g () ав т о м а т и ч е ск и ср аб а­
т ы в ае т , когда о б ъ е к т и сп о льзу ется в м есто стр о к и . Н а п р и м е р ,
код в ы зо в а всп л ы ваю щ его о к н а с д ат о й за п и си м о ж н о н а п и с ать
в о т так, получив т о т ж е сам ы й результат:
Thu Atig 14 2008 00-00:00 CMT-0500 <COT)
М ет од to S trin q O
п о ка зы ва ет , каким
Образом о б ъ ект
P a te с лед и т за
вр ем ен ем .
a lert(b lo g D ate);
М ет од to S trin g O не
т о ль к о д ает ст рокодое
п р е д с т а влен и е дат ы ,
но п о я вля ет ся и в дру ­
ги х объект ах.
Метод toString ()
обеспечивает строковое
представлепие объекта.
434
глава 9
Т ак как ф у н кц и я a l e r t () п р и н и м а е т в кач естве аргум ента
с т р о к и , о б ъ е к т D a te зн а ет , ч то ему н ео б х о д и м о п р е о б р а зо в а н и е
в д ругой ф о р м ат . Д л я эт о го о н с ам о сто я т е л ь н о в ы зы в а ет м етод
t o S t r i n g ().
Д е й с т в и е м ето д а t o S t r i n g ( ) н е стал о бы п р о б л ем о й , есл и бы
д аты о т о б р а ж ал и сь в п р о с т о м ф о р м а т е , н а п р и м е р MISl/ Д Д /
ГГГГ. Т о есть н аш блог Y o u C u b e н е м о ж ет в о с п о л ьзо ваться
пр еи м у щ еством зад ан н о го по ум олчан и ю п р е д ста в л ен и я строк.
оживляем данные
Д оступ к ф рагментам даты
Руби нуж ен сп о со б р егу л и р о в к и ф о р м а т а даты . Д л я эт о го нам
п о тр еб у ется доступ к о тд ел ьн ы м ф р а гм е н та м , а и м е н н о к м еся­
цам , д н ям и годам . П о сл е ч его м ы см ож ем с о б р а т ь дату нуж ны м
нам о б р азо м . К счастью , о б ъ е к т D a te о б л ад ает всем и н ео б х о д и ­
м ы м и д ля эт о го м етодам и.
М есяц п р е д с т а в л я е т с я
о биде числа о т о до ц .
Дене> — э т о число
о т 3- до 3 1 .
J
Год в полной ф о р лле (6 виде 4 с и м ­
волов).
Обратите внимание
на значения, возвра|Ды»е
I щаемые методами
осшо]зожНь1! объекта Date.
О б ъ е к т D a te о б л ад ает н е т о л ь к о т р е м я в ы ­
ш еуказанны м и , н о и други м и м ето д ам и , обеспечиваю ш ;им и р а зл и ч н ы е сп о со б ы д оступа
к д ат е и в р ем ен и . О д н ако д ля н аш и х ц е л е й
вп о л н е д о с т а т о ч н о эт и х тр ех .
Метод getMonthQ
возвращает месяц в виде чисел от
О (январь) до 11 (декабрь), в то время
как метод getDateQ возвращает число
в диапазоне от 1 до 31.
возьми в руку карандаш
Устраните проблему с записью дат в блоге YouCube, пере­
писав код, форматирующий запись блога и сохраняющий его
в переменной b lo g T e x t . Убедитесь, что даты имеют формат
ММ/ДД/ГГГГ. Вот исходная версия кода:
blogText
+=
"<strong>"
+ blog[i].date
+
"</strongXbr
/>"
+ blog[i].body
+
"</p>";
далее >
435
реш ение упражнения
- ^ з ь м и В руку карандаш
Решение
Вот как выглядит в результате переписанный код, форма­
тирующий запись блога и сохраняющий его в переменной
Ы o g T e x t.
b lo g T e x t + - "< s tro n g > " + b l o g [ i ] . d a t e
.
+ " < / s t r o n g X b r /> " + b l o g [ i] . b o d y + "< /p > "
.t.T. "M r.o n e? ". r.
.t. i .) .+
+-
h logliJ.date.getF u llY earQ + " < /s tr o n g x b r /> "
Д л я получения
нуж ного ф о р м а -
b lo g [ i] .b o a y + "< /p y "-,
т а произведем
ф орм ат ирование
о б ш к т а D a te
бручную .
К а ж д ы й ф р а г м е н т дат ы
и зв л е к а е т с я из о б ъ е к т а
D a te п р и п о м о щ и с о о т -
Д а т а т еперь от оС раж ает ся в п ри вы чф орм ат е М М /
вет ст вую щ его м ет о д а.
А Д /Г Г Г Г .
Д а т ы упроцаю т сортировку
Т еп е р ь , когда д аты в бло ге п р е д с та в л е н ы в ви д е о б ъ е к т о в D a te ,
ч то лучш е о т в е ч а е т н аш им целям , в е р н е м с я к воп р о су о п о р я д ­
ке за п и с ей . В настояш ,ее в р е м я о н и о т о б р а ж аю т ся в том п о р я д ­
ке, в к о т о р о м о к азал и сь с о х р а н е н ы в м асси ве Ы о д , в то в р ем я
как нам тр еб у ется, ч то б ы сам ы е св еж и е за п и с и б ы ли наверху.
Р ассм о тр и м еш;е р а з п р оц едуру с о р т и р о в к и :
Д ата
Т е п е р ь у нас е с т ь ,
О б ъ е кт ы D a t e , к о ^поры е м о ж н о с р а в ­
н ит ь друг с другом .
О
П росм отрим массив в цикле.
©
С р авн и м дату каж до го о б ъ е к т а B l o g со следую щ им.
е
Е сли следую щ ая за п и с ь я в л я е т с я б о л ее св еж ей , м ен яем зап и си м естам и.
Х о тя б л аго д ар я об ъ екту D a te т а ч асть с т р а т е г и и , к о т о р а я о т н о с и т ­
ся к с р а в н е н и ю дат, стал а вы гл яд еть м ен ее устраш аю щ ей, о стал ьн ая
ч ас т ь п л ан а все ещ е т р еб у ет н а п и с а н и я и зр я д н ы х ф р а гм е н т о в кода.
С д ругой с т о р о н ы , н е в о зм о ж н о п о в е р и ть , ч то б ы т а к а я п р о б л ем а,
как с о р т и р о в к а н а б о р о в д ан н ы х , н е р еш ал ась м н о го р а з до этого.
А зн а ч и т , и зо б р е т а т ь в ел о си п ед л и ч н о вам н е потребуется...
436
глава 9
оживляем данные
А здорово было,бы если бы
в JavaScгipt была встроенная
функция для выполнения рутинной
работы по сортировке данных...
далее *
437
сорт ировка своими силами
Массивы как объекты
К ак вы дум аете, м о ж е т л и м ассив сам себ я с о р т и р о в ать ? Э то п р е д п о ­
л о ж е н и е не л и ш е н о см ы сла, в к о н ц е ко н ц о в , д ан н ы е ж е ум ею т сам о­
с т о я т е л ь н о о сущ ествлять п р е о б р а зо в а н и е в с т р о к о в ы й ф о р м ат . Н о
ч то б ы т а к о е стал о в о зм о ж н ы м , м ассив д о л ж ен б ы ть о б ъ ек то м и об ла­
д ать соответству ю щ и м и м етод ам и. С ам ое и н т е р е с н о е , ч т о т а к о н о и
есть. П о м н и те код и з с ц е н а р и я M an d an g o ?
Массив это всего
лип1ь объект
f o r (var i = 0; i < s e a t s . l e n g t h ; 1++) {
le n g th — э т о с в о й ст в о м а сси ва
п редост авляю щ ее и н ф о р м а ц и ю '
о к о л и ч е ст в е э л е м е н т о в в нем .
Переменная
se a ts я вляет ся
м ассивом .
И та к , м ассивы я в л яю тся о б ъ ектам и . О зн а ч а е т л и это , ч то о н и
м огут с о р т и р о в а т ь себя сами? М ассивы о б лад аю т н е т о л ь к о с во й ­
ством l e n g t h , н о ещ е и м ето д ам и о б р а б о т к и св о и х д ан ны х. В том
чи сл е и м ето д о м s o r t ( ) , к о т о р ы й нам нуж ен. П о см о тр и м , как
и м е н н о о н р аб о тает.
nums
(С о р т и р о в к а
по в о зр а с т а н и ю .
М етод s o r t () м е н я е т п о р я д о к эл е м е н то в вн утри м ассива. П о
ум олчани ю с о р т и р о в к а осу щ ествл яется п о в о зр астан и ю , п о э т о ­
му м ассив nums п р и о б р е т е т в о т т а к о й вид:
438
оживляем данные
Пользовательская copmupoBka
З а д а н н о го п о ум олчан и ю п о в е д е н и я м ето д а s o r t () о б ъ е к та
A r r a y ч ас т о н е д о с та т о ч н о . Н о н а п о м о щ ь п р и х о д и т т о т ф акт,
ч т о п р о ц ед у р а с о р т и р о в к и о п р е д е л я е т с я ф у н к ц и ей с р а в н ен и я ,
котор у ю в ы зы в а е т м ето д s o r t ( ) . З н а ч и т , вы м о ж ете п о в л и я т ь
н а с о р ти р о в ку , н ап и сав св о й в а р и а н т э т о й ф у н кц и и . В от как
о н а о б ы ч н о вы гляд ит:
в
f u n c t i o n compare (X, у) {
r e t u r n X - у;
ка чест ве
а р гум ен т о в
в ы с т у п а ю т два э л е м е н М ассива, к о т о р ы е
сю а вн и ва ю т ся с целью
с о р т и р о в ки .
В о зв р а щ а е м о е значение
оп ределяет , ост анут ся
ли к и у на свои х м е с т а х
или же п о м е н я ю т с я д р у г
с д р у го м .
Ф ункция c o m p a re () в о зв р а щ ае т ч и сл о , о п р ед ел яю щ ее
р езульти рую щ ее п о л о ж ен и е X и у.
< О
П о ст ав и м X п е р е д
Сортировка не нужна,
оставим элементы на
местах.
__ > 0
П о ст ав и м у п е р е д н.
Н а п и с а н н а я ф у н кц и я c o m p a re () в став л я ется в ур авн ен и е
с о р т и р о в к и м асси ва п р и в ы зо в е м ето д а s o r t () —д о ста то ч н о
п е р е д а ть ссы лку н а н е е этом у методу.
nums. s o r t (compare) ;
С о р т и р о в к а м асси оа
т еперь у п р ав л я е т -
„дЯмсйННОМ ва м и
ф ун кц и ей со т р а геО -
Возьми В руку карандаш
Напишите код для функции c o m p a re ( ) , располагающей
массив записей блога YouCube в обратном хронологическом
порядке. Подсказка: вычитание объектов B lo g друг из друга
осуществляется при помощи обычного знака минус.
далее >
439
реш ение упражнения
Возьми в руку карандаш
Решение
Вот как выглядит код функции c o m p a re ( ) , располагающей
массив записей блога YouCube в обратном хронологическом
порядке.
.f u n c t i o n c p m p a r e j^ h iq g x
r e t u r n h lo g Z .d a t e - b lo g t . d a t e ;
являю т ся
о б ъ е к т ы B lo g ,
в е д ь и л 1\е и н о и з
HWX с о с т о и т
}
........
(
^
В ы чит ание первой дат ы
рт и ровке в обрат ном
хр о н о л о ги ч еск о м п орядке.
.
(м и лли секин ды )
с-^^кунш).
Упрощение сортировки
Н а п и с а н н а я н ам и ф у н кц и я с р а в н е н и я эл е м е н т о в м асси ва и с­
пол ьзу ется и с к л ю ч и те л ь н о в м ето д е s o r t (). А зн а ч и т , и м ен о ­
в ан н ая ф у н кц и я нам в д ан н о м случае н е тр ебуется.
П о м н и т е л и т е р а л ы ф у н кц и и д ля т е р м о с т а т а , с к о т о р ы м мы
р а б о т а л и в гл аве 6? Ф ункция c o m p a re () т ак ж е я в л я е т с я п р е в о с ­
х од н ы м кан ди дато м н а эту ро л ь. Б о л е е т о го , с о р т и р о в к а за п и ­
се й б ло га у п р о сти тся , есл и эту ф ункц ию п р е в р а т и т ь в л и т ер а л ,
н е п о ср е д с тв е н н о п е р е д а в ае м ы й м етоду s o r t ().
Ы о д . s o r t ( f u n c t io n ( b l o g l , Ыод2)
r e tu r n b lo g 2 .d a te - b lo g l.d a te ;
{
'п осредст венн о м е т о д у s o r tQ
м а сси ва .
}) ;
К ак л ю б и т е л ь го л о во ло м о к . Руби н а п е р в о е м есто ста­
в и т эф ф е к т и в н о с т ь . А у д ал ен и е н ен у ж н о й и м ен о в а н н о й
ф у н кц и и у в ел и ч и в ает эф ф е к т и в н о с т ь м ето д а s o r t ().
К р о м е то го . Руби н е п о н и м а е т, зач ем ф у н кц и и с р ав н е­
н и я ц ел ы х т р и с т р о ч к и кода. Н аш л и т е р а л д о ст а т о ч н о
п р о с т , ч то б ы о б о й т и с ь всего о д н о й с т р о ч к о й .
Л и т е р а л ф ун кци и
со к р а т и л с я до одной
ст р о ч к и кода.
-
b l o g . s o r t ( f u n c t i o n ( b l o g l , Ы од2)
440
глава 9
'
J
{ r e tu r n b lo g 2 .d a te - b lo g l.d a te ;
оживляем данные
Ч а с зц о
<аДаБаеМые
БоЦ РоС ь!
Любой ли объект обладает
методом t o S t r i n g () ?
Каким образом функция сравнения
работает с объектами D a te objects?
; Да. Даже если вы создадите
специальный объект, не снабдив его
; Функция сравнения возвращает
число, значение которого отвечает
методом t o S t r i n g ( ) , JavaScript по
крайней мере укажет на существование
такого объекта при попытке использовать
за сортировку двух аргументов. При
сравнении дат нужно, чтобы более
поздняя дата шла впереди. Более
его там, где требуется строка.
В некоторых случаях строки не имеют
особого значения, но вы можете по
своему желанию добавить объекту
поздняя дата больше, поэтому
определить порядок следования можно
метод
при помощи обычного вычитания. Вторая
дата оказывается перед первой только
при условии, что она больше (результат
t o S t r i n g ( ) , чтобы получить
вычитания больше 0).
возможность читать его значение.
3» Как метод A r r a y . s o r t ( )
определяет, использовать ему
пользовательскую функцию сравнения
или функцию по умолчанию?
; Это решение зависит от того,
был ли функции s o r t ( ) передан
аргумент. Отсутствие аргумента означает
сортировку по умолчанию. Его наличие
интерпретируется как ссылка на функцию
и используется как основа для сравнения
сортируемых элементов. То есть
ссылка на функцию сравнения является
необязательным аргументом.
Счастье Руби
Б л о г Y o u C u b e п о с т е п е н н о п р и б л и ж а е тс я к п р ед ставл ен и ям
Руби об и д еал ьн о м м есте о б щ е н и я с други м и п о к л о н н и к а м и
гол ово ло м о к.
Й 0 0
С b ^ h e jlo g
^
_______ _____
Я люблю свой
блог почти так же,
как головоломки!
T o u C u b c - The Btog for Cube P u lle rs
m io m ^
Found a 7x7x7 cube for sate
YikesS That one could be a beast.
8Solved
/19/2008
fee new cube but of couise
get a headacte »ilfflg over
I’m bored and shopping for a new one.
new cubc. Gotta nap.
Got (he new cube I oidcnd. It's a red pearl.
Show Ail Й 09 Entries
Done
________
-Д д ть / им ею т
п о н я т н ы й вид.
П оследние з а п и ­
си в ы в о д я т с я на
с а м о м верху.
далее *
441
головоломка «п оиск слова»
Поиск
БлогУ ои С иЬ е п р е к р а с н о р а б о т а е т , н о н е к о т о р ы е п о л ьзо в а т е л и
заго в о р и л и о т а к о й ф у н кц и и , как п о и с к п о всем зап и сям . Т ак
как Руби п л ан и ру ет п и сать туда ч асто и м н о го , о н а согласн а,
ч т о эт о к р а й н е п о л е зн а я ф у н кц и я, о с о б е н н о в д о л го с р о ч н о й
п ер сп ек ти в е.
Search the Мод j 7x7x7
в в ед ен н а я с т р о к а и с ­
п о л ь з у е т с я для п о и с ­
ка п о в с е м у т е к с т у
Руби нуж ен п лан п о р е а л и за ц и и п о и ск а в блоге
Y ouC ube... Н е п ом огут ли ей в это м объекты ?
442
глава 9
оживляем данные
Поиск по АлассиВу
Ф ункция п о и с к а в блоге Y o u C u b e вкл ю ч ает в себя ц и к л и ч е с к и й п р о с м о т р
м асси ва всех за п и с ей и п о и с к совп ад аю щ и х си м вол ов в каж дой и з них.
Ц иклический
просмотр всех
записей.
Эта конструкция имеет смысл, но как найти
слово в тексте записи? Я озадачена... но,
кажется, выход есть!
О
Выход и з цикла
в случае совпадения.
Ш Т У РМ
Как бы вы реализовали поиск среди записей
блога YouCube совпадающей строки текста?
далее *
443
свяжем их вместе
Как вы уже знаете, строка — это
объект. Так может быть, строка сама
может осуществлять поиск?
Строка как объект, доступны й для поиска.
В озм ож н о, вы уже п о н ял и , ч т о о б ъ ек ты в Jav aS crip t
везде. И с т р о к и т о ж е я в л я ю т ся о б ъ ек там и и снаб ж е­
н ы м н о го ч и с л ен н ы м и м ето д ам и для в заи м о д ей стви я
с т е к ст о в ы м и д ан н ы м и . О д и н и з эт и х м етод ов д ей ­
с т в и т ел ь н о п о зв о л я е т и ск ать в с т р о к е ф р агм ен т ы
текста.
Поиск в с т р о к е п о ­
сл ед о в а т ел ь н о с т и
си м вол ов.
“G o t th e n e w
c u b e 1 o rd e re d .
It ’s a re a l
p e a rl."
Ч исло си м во л о в
в ст р о к е.
444
глава 9
О п р е д е л ен и е
м ест а в с т р о ­
ке ук а за н н о го
си м во л а .
П реобразовани е
с т р о к и 8 нижний
и верхн ий р е г и ­
ст ры со о т вет ­
ст вен н о.
оживляем данные
М етод indexOfO
М етод in d e x O f () п о зв о л я е т и ск ать в о б ъ е к т е S t r i n g ф р а гм е н т ы
текста. П о и с к о в ы й за п р о с п е р е д а ет с я м етоду как аргум ен т —так
как м ето д п р и н а д л е ж и т об ъ екту S t r i n g , других аргум ен тов п е р е ­
д авать н е нуж но. М етод i n d e x O f ( ) в о зв р а щ ает и н д ек с, указы ваю ­
щ и й н а м е с то п о л о ж е н и е о б н ар у ж ен н ы х си м вол ов, и л и -1 , если
п о и ск о к азал ся безуспеш ны м .
v a r s t r = "Got th e new cube I o r d e r e d . I t ' s a r e a l p e a r l . " ;
a l e r t ( s t r . i n d e x O f ( " n e w " ) );
Ч т о б ы п о н я т ь , откуда п о я в и л а с ь ц и ф р а 8, р а с с м о тр и м строку
как м ассив о тд ел ь н ы х сим волов.
10
, , , , , , , , , I Ml
20
1111 м m
30
40
i l l м I i l l i l l 11111 i 11 i I I I
"Got the new сгдЬе I ordered. It's a real pearl."
К аж дому с и м в о л у в с т р о ке с о о т в е т с т в у е т у н и
к а л ш ы й индекс. О т с ч е т
П о и с к о в ы й за п р о с n e w n o я в л я е т с я в с т р о к е под и н ~
д е кс о м 8.
Если нуж ной п о с л е д о в ат е л ь н о с т и с и м в о л о в в с т р о к е н е существует, м етод in d e x O f () в о з в р а щ а е т -1 .
начинает ся с О, ч т о
началу
ст р о ки .
соот вет ст вует
В р е з у л ь т а т е п о л у ч а е м —I ,
v a r s e a r c h ln d e x = s t r . i n d e x O f ( " u s e d " ) ;
аВаЖ еН Ие
^
^ |Ь а ж н (
/^ < ^ ^ J < KaK с т р о к а п о и с ка не
Нйм^енй 6 о б ъ е кт е S t r in g .
показана любимая загадка Руби. Определите индекс каждого вхождения подстроки «cube» в строку загадки.
«Кубистка возводила в куб два куба и получила восемь. Была ли она
кубинкой?»
далее *■
445
реш ение упражнения
__
13Ж Н2НИ2
Вот индексы вхождения подстроки « c u b e» в любимую загадку Руби. «Кубистка возводила
^
получила восемь. Была ли она кубинкой?».
деке о .
"A cubist cubed two cubes and ended up with eight. Was she Cuban?"
И н д е к с вхоукдения^
подст роки
Я.
V _ И ндекс вхождения
подст роки
Поиск по блогу
Б л а го д а р я м етоду in d e x O f () п о и ск п о с тр о к ам в ы п о л н я е т ся
д о с т а т о ч н о п р о с т о , н о у Руби для п о и с к а и м ее т с я ц ел ы й блог.
О н а с о б и р а е тс я в ц и кл е п р о с м а т р и в а т ь все за п и с и и н а каж дой
и т е р а ц и и и с п о л ь зо в ат ь м ето д i n d e x O f ( ) . О б н ар у ж ен н ы е со­
в п а д е н и я д о лж н ы в ы в о д и ть ся в о тд ел ьн о м окн е.
П е р е д тем как п р и сту п и ть к н а п и сан и ю ф у н кц и и п о и с к а по
блогу, нам п о тр еб у ется со зд ать т е к с т о в о е пол е, в к о т о р о е будут
в во д и ться п о и с к о в ы е за п р о с ы , и кнопку, запускаю щ ую пои ск.
< i n p u t t y p e = " b u t to n " i d = " s e a r c h " v a l u e = " S e a r c h t h e B log" o n c l i c k = " s e a r c h B l o g ( ) />
< i n p u t t y p e = " t e x t " i d = " s e a r c h t e x t " n a m e = " s e a r c h te x t" v a lu e = " " />
Д о с т у п к п о и ско во м у
за п р о су о с у щ е ст в ля е т с я
через IP se a rc h te x t.
Поисковый запрос!
Э т а кнопка вы зы вает
ф ун к ц и ю $еагскВ Ь д()
и т е м са м ы м и нициирце т п о иск по блогу.
Search the Blog ||7x7x7
Т е п е р ь , когд а п о и ск о в ы е Н Т М Ь -элем ен ты н а м есте, остал о сь
н а п и с ать код ф у н к ц и и з е а г с Ь Ы о д ( ) . Т ак как д ля о т о б р а ж ен и я
р езу л ьтато в п о и с к а эт а ф ун кц и я и сп ользует в сп л ы ваю щ ее окн о,
о н а н е в о зв р ащ ае т н и к а к о й и н ф о р м а ц и и . А т а к как п о и ск о в ы й
за п р о с с ч и ты в а е т с я и з т е к с т о в о го п ол я, в к о т о р о е его ввел п о л ь­
зо в ател ь, нам н е п отреб ую тся и н и к ак и е аргум енты .
446
глава 9
оживляем данные
Магниты JavaScript
Функция зе а г с Ь В 1 о д () отвечает за циклический просмотр
записей блога и поиск текста, совпадающего с поисковым запро­
сом. Помогите Руби закончить код, поместив магниты на пустые
места. Подсказка: совпадающие результаты поиска должны ото­
бражаться вместе с датой записи в виде ММ/ДД/ГГГГ, выводимой
в квадратных скобках после текста блога.
function
searchBlogO
=
{
" ) .value;
d o c u m e n t . g e t E l e m e n t B y l d ("
var
for
(var
1 = 0 ;
//
Проверяем,
if
(blog[i].
a l e r t e ["
; i ++)
i <
содержит
ли
запись
{
поисковый
текст
.toLowerCase 0
+
(blog[i] •
Ы о , 1 1 Ь .....................*
blog[i] .
"l
" ^
) '■
break;
}
}
//
if
Если
поисковый
текст
не
найден,
сообщим
об
этом
(i = =
containing
alert("Sorry,
there
are
no
blog
the
search
text.
),
entries
date
searchText
searchtext
getMonthQ
далее >
447
реш ение задачи с магнитами
Решение задачи с магнитами
Вот как выглядит функция зеагсЬ В Х о д ( ) , отвечающая за
циклический просмотр записей блога и поиск в них указанного
пользователем текста.
В озьм ем т ек ст п о ­
и скового за п р о с а из
т е к с т о в о го поля.
function
searchBlogO
searchText
var
for
(var
i =
0;
//
Проверяем,
if
(b lo g [i].
a l e r t (" ["
{
blog.length
X <
содержит
body
+
ли
запись
i ++)
').value;
{
поисковый
текст
l . t o L o w e r C a s e O .i n d e x O f ( s e a r c h T e x t .t o L o w e r C a s e ())
(blog[i] .
date 1
blog[i].date.getDate0
blog[i] .
searchtext
Г- d o c u m e n t . g e t E l e m e n t B y l d ('
bodi
+
'7-
getMonthO
+ blog[i].
1
+
jJ "
date
*
getFullYearO
+
"]
I I;
break;
}
}
//
if
Если
(i = =
поисковый
текст
не
найден,
there
are
no
Если i р а вн о св о й с т в у le n g th
о б ъ е к т а Ыод, зн а ч и т , все з а ' писи уж е были п р о с м о т р е н ы
и совп адени й не обнаруж ено.
глава 9
об
этом
blog.length
'IWtC'Sorry,
448
сообщим
blog
entries
containing
the
search
text.");
^ о с л е со вп а д а ю щ его т е к с т а
оы бодит ся д а т а зап иси в квад р а т н ы х скобках в ф о р м а т е
М М /ДД/ГГГГ,
!=-l)
^
" +
{
оживляем данные
Поиск заработал!
И так, г о то в а в е р с и я Y o u C u b e 2.0 с ф у н к ц и ей п ои ска, р аб о таю щ ей
б л аго д ар я св о й ствам о б ъ е к т а S t r i n g . В ы в и д и те, каки м о б р азо м
о б ъ е к т ы д ел аю т д ан н ы е акти вн ы м и . В д ан н о м случае с т р о к а т е к с т а
(о б ы ч н ы е д ан н ы е) п р е в р а т и л а с ь в структуру с п о в ед ен и ем (о н а ум еет
осущ ествлять п о и ск). С ам ое гл авн о е, ч т о Руби н е п р и ш л о с ь и зо б р е ­
т а ть с о б с т в е н н ы й п о и с к о в ы й м ех ан и зм , а о св о б о д и вш ееся таки м
о б р азо м в р е м я о н а п о т р а т и л а н а в ед ен и е блога.
в О 0
18/29/2008] Met yp with some fellow cubers to diseass
the prospect of a 7x7x7 cube. Mixed feelings.
Search
Поиск no бло- L
ry — это золлечаj
тельно!
feelings.
Show ДІІ 8І09 E ^ t r i e s J
............ ..............
Руби в в о с т о р ге о т н о в о й ф у н к ц и о н а л ьн о ст и блога,
но о н а н е и з тех, к то п о ч и в а е т н а лаврах. И уже п о ­
дум ы вает о в е р с и и Y o u C u b e 3.0...
далее >
449
на самом деле они вовсе глупые
Часагю
З ад аваем ы е
B o iij= > o c : b i
3 * Неужели каждая строка это дей­
ствительно объект?
! Да. Все строки в JavaScript являются
объектами. Если в коде JavaScript вы по­
местите свое имя в кавычки, например
«Ruby»,
вы создадите объект. Такой под­
ход может казаться излишеством, но его
преимущество в том, что каждая строка
умеет делать много полезного, напри­
мер: она знает свою длину, умеет искать
заданные последовательности символов
и многое другое.
3 * Но строка так похожа на массив,
даже все ее символы имеют свои
индексы. Неужели она — массив?
Q ; Нет. Строка определенно не являет­
ся массивом. Однако и в самом деле мно­
гие методы объекта S t r i n g производят
операции над данными таким образом,
как будто перед нами массив, состав­
ленный из набора символов. Например,
первый символ строки имеет индекс О,
и этот индекс инкрементно увеличивается.
Но доступ к любому элементу массива
можно получить, указав его индекс в ква­
дратных скобках ( [ ]). Со строками такое
невозможно. Считайте для простоты,
что вы работаете с массивом символов,
учитывайте разницу между работой с объ­
ектами
S trin g
Можно ли в функции поиска
s e a r c h B l o g () использовать метод
c h a r A t () вместо i n d e x O f () ?
Q ; Нет. 1\Летод
charA t ()
ищет еди­
ничные символы, в то время как в блоге
обычно хотят найти слово или даже
фразу. 1/1менно поэтому для данной цели
больше подходит метод i n d e x O f о ,
умеющий искать произвольные наборы
символов.
Можно ли найти все вхождения
поискового запроса в текст блога?
Зачем в функции
s e a r c h B l o g () два раза вызывает­
ся метод to L o w e r C a s e () ?
Q ; Ответ на этот вопрос связан с про­
блемой регистра при поиске по блогу.
Ведь если пользователь ищет, например,
слово «cube», его, скорее всего, интере­
суют все варианты этого слова: «cube»,
«Cube», «CUBE» и т. д. Проще всего эту
проблему можно решить преобразова­
нием как текста блога, так и поискового
запроса к одному регистру. Хотя в нашей
s e a r c h B l o g О использу­
t o L o w e r C a s e ( ) , можно
было взять и метод t o U p p e r C a s e ().
функции
ется метод
! Да. 1\/1етод i n d e x O f () по умол­
чанию ищет только первое вхождение. Но
ему можно передать еще один необя­
зательный аргумент, указывающий, где
следует начать поиск. Предположим, вы
ищете слово «cube» и обнаружили его
под индексом 11. Снова вызвав метод
Главное, выполнить поиск без учета
регистра букв.
in d ex O f
() со вторым аргументом 11,
вы инициируете новый поиск, начинаю­
щийся с индекса 12. Таким образом, для
продолжения поиска вам нужно только
передать индекс найденной строки методу
i n d e x O f {).
и A rr a y .
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
■
Метод t o S t r i n g () обеспечивает текстовое пред­
ставление объектов.
Метод s o r t {) объекта A r r a y сортирует массив
в нужном вам порядке.
■
Как массивы, так и строки являются объектами
и получают способ хранения данных и методы
от стандартных объектов A r r a y и s t r i n g .
Метод i n d e x O f () объекта s t r i n g ищет строку
текста в другой строке, возвращая индекс обнару­
женного совпадающего текста.
450
глава 9
оживляем данны е
Случайный Выбор
в б еск о н е ч н о м с т р ем л е н и и п о д д ер ж ать и н т е р е с п о л ь зо в ат ел е й
к своем у блогу Руби р е ш и л а д о б а в и т ь к нем у ф ункц ию , к о т о р а я ,
как ей к аж ется, д о л ж н а п о н р а в и т ь с я п о с е ти те л я м . Э то кн о п к а
R a n d o m , п о зв о л я ю щ ая в ы в е с ти случайную запи сь.
ooObe,‘jo tth e . і^ с и Ь е - І
__ ____ —
ordered,.
p , o ip e c t o f o .7 > .7 ,o 7 cube,.
c u b e ^ b u t o f co u n e ,. noM> I ’m,
cyv\£'
^ » ^р іг Щ 'ІО г с и п е м ! or\e,.
Возможность выбора слу­
чайной записи сделает блог
УоиСиЬе еще более забавным
и загадочным.
Руби — ф а ­
н а т к а го л о во ­
лом ок и т а ­
и нст вен на я
женщина.
Ш ТУРМ
Как вы реализовали бы случайный
выбор записи из блога?
далее ►
451
есе на своем мест е
Объект Math
Ч т о б ы д о б а в и т ь к блогу Y o u C u b e в о зм о ж н о с ть п ер е х о д а к случай н ой
зап и си , нам п о тр еб у ется сп о со б г е н е р а ц и и сл учай н ы х ч и сел . В это м нам
п о м о ж ет в с т р о е н н ы й о б ъ е к т Jav aS crip t, к о т о р ы й н е я в л я е т с я н асто л ь­
ко «ж ивы м », как о с тал ь н ы е зн ак о м ы е вам о б ъ екты . Э то ст ан д ар т н ы й
о б ъ е к т Math, в н у тр и к о т о р о г о г е н е р я т с я случай н ы е чи сл а. П р и это м он
н е м е н я е т н и к а к и х д ан н ы х и н е и м е е т возд ействую щ их н а в н у тр ен н и е
д ан н ы е м ето д о в.
О к р у г л я е т число с п л а —баю щ ей т очкой до целого.
В о звр а щ а ет целое
о к р у гл е н и е м числа
в м еньилую с т о ­
рону.
Возвраицает целое
.о к р у гл е н и е м числа
в Ьбльш ую ст орону.
М а т е м а т и ч ес к а я
к о н с т а н т а , 3 ,1 4 .
Г е н ер и р у е т случайное
число о т о до 1 .
О б ъ е к т M ath я в л я е т с я н а б о р о м м а те м а т и ч е ск и х м етод ов и к о н ­
стан т. У н его н е т п е р е м е н н ы х , с о о т в ет с т в е н н о , о н н е и м еет
со с то я н и я — вы н е м о ж ете и с п о л ь зо в ат ь его д ля х р а н е н и я
и н ф о р м а ц и и . Е д и н ств ен н ы м и д ан н ы м и эт о го о б ъ е к т а яв л я ю т ­
ся н еск о л ьк о к о н с та н т, в т о м ч и сл е P I (3 ,1 4 ). Н о о н об лад ает
весьм а п о л е зн ы м и м етодам и. О д и н и з н и х , м етод ra n d o m (),
со зд ае т ч и с л а с д е с я т и ч н о й т о ч к о й в п р о м еж утк е о т О до 1.
ажншб
Напишите результаты вызова методов объекта
Объект Math состоит из
набора математических
методов и констант.
Math.
Ma±h.round(Math.PI)
Math.ceiling(Math.PI)
.......
Math.random()
.......
Q u iB e i» н а Cinj=>. 4 5 4 -
452
глава 9
оживляем данные
а в ъ Ш
^
. 'т
- Ы
А 'Ш
-
Ö СЁБЁ
Интервью недели:
К о гд а м а т е м а т и ч е с к и е ф у н к ц и и с т а л к и в а ю т с я
Head First: Я совсем запутался. Вы о б ъ ект, но
с о д е р ж и т е в себе всего л и ш ь н а б о р м атем ати ­
ч ес к и х м ето д о в и н еск о л ьк о ко н стан т. Я ж е
думал, ч то о б ъ е к т ы д о лж н ы д ел ать дан н ы е
а кти в н ы м и . Т о есть б р а т ь д ан н ы е и п р и п о ­
м ощ и м ето д о в д ел ать с н и м и в ся ки е удиви­
т е л ь н ы е вещ и.
Math: Д а, т а к т р а д и ц и о н н о п р и н я т о думать,
н о н е все о б ъ е к т ы п р е д н а зн а ч е н ы д ля э т о й
ц ел и . Н е к о т о р ы е и з н и х могут и гр а т ь р о л ь
о р г а н и за т о р о в , как я, н а п р и м е р .
Head First: Н о р азв е все эт и м атем ати ч еск и е
м ето д ы н ел ь зя со зд ать в ви д е с тан д ар тн ы х
ф ункций?
IVIath: Р азум еется, м о ж н о , н о вы заб ы в аете,
ч т о я зы к Jav aS crip t п о с т р о е н и з о б ъ екто в.
Т а к ч т о по сути т а к о й вещ и , как « стан дарт­
ная» ф у н кц и я, н е сущ ествует.
Head First: Н о я создавал ф у н кц и и вн е о б ъ ­
ек то в , и о н и п р е к р а сн о р аб о тал и .
IVIath: Н а сам ом дел е все ф у н кц и и яв л яю тся
м етод ам и, т а к как о н и п р и н а д л е ж ат какомул и б о объекту, и н о гд а скры том у.
Head First: З н а ч и т , в о т почем у вы с о д ер ж и те
э т и м а те м а ти ч е ск и е м етоды ...
IVIath: И н е дум айте, ч то отсу тстви е д ан н ы х,
к о т о р ы м и я могу уп р авл ять, и ск л ю ч ает м ен я
и з со сл о в и я о б ъ екто в.
Head First: Ч т о вы и м е е т е в виду?
Math: Ну, п р ед став ьте л ю д ей с о б щ и м и и н т е ­
р есам и . Ч а с то о н и о б ъ е д и н я ю тс я в группы по
и н тер есам . М а тем ати ч еск и е м ето д ы , к о н еч ­
н о , н е т а к со ц и ал ьн о а к ти в н ы , как лю ди, но
и о н и и м ею т вы году о т о р г а н и за ц и и , к о т о ­
рую я им п р ед о ставл яю .
Head First: Вы х о т и т е сказать, ч т о у н и х м н о­
го общ его?
Math: Да! Все о н и р еш аю т м ате м ати ч е ск и е
зад ач и , н а п р и м е р округл яя ч и сл а, в ы п о л н я я
т р и г о н о м е т р и ч е с к и е о п е р а ц и и и ген ер и р у я
случай н ы е числа.
Head First: В ы упом янули г е н е р а т о р случай­
н ы х ч и сел . Я слы ш ал, ч т о н а сам ом дел е он и
н е случайны . Э то правда?
Math: Д о л ж е н п р и зн ат ь с я , ч то да. О н и д ей ­
с т в и т ел ь н о н е совсем случайн ы , как и б оль­
ш и н ство случайн ы х ч и сел , ген ер и р у ем ы х
ком п ью тер о м . О н и «псевдослучайны », н о для
б о л ьш и н ства задач эт о го д о стато ч н о .
Head First: П севд осл уч ай н ость — эт о как
псевдонаука... и л и псевдокод?
Math: И да, и нет. Н е т , н и ч его п о д о б н о го
псевдонауке. И да, п о х о ж и н а п севд окод , ведь
он п р е д н а зн а ч е н д ля п о к аза о с н о в н о й и д еи
кода, н е я в л я я с ь им п о сути. Т ак и псевдослу­
ч ай н ы е ч и с л а и м и ти р у ю т хаос, н е будучи по
сво ей п р и р о д е случайны м и.
Head First: Т о есть и х м ож н о с ч и тат ь до ста­
т о ч н о случайн ы м и для б о л ьш и н ств а п р и л о ­
ж е н и й JavaScript?
Math: Д а. И эт о х о р о ш ее в ы р аж ен и е: «доста­
т о ч н о случайны е». В ряд л и с т о и т и сп о л ьзо ­
вать и х для задач, св я за н н ы х с н ац и о н а л ь н о й
б езо п асн о стью , н о д ля о б ы ч н ы х сц ен ар и ев
о н и в п о л н е подходят.
Head First: П о н я т н о . С п аси бо за вашу о т к р о ­
в е н н о с т ь п о поводу сл учайн ы х чисел.
Math: Рад бы л побеседовать... как вы зн аете,
я н е умею врать.
далее *■
453
реш ение упражнения
Вот результат вызова методов объекта Math.
З Д 4 о кр угл е н о до 3.
решение
5 Л 4 окр углено
ooepXj до 4.
Math.round(Math.PI)
3
Math.ceiling(Math.PI)
4 ^ 7 7 3 7 ----------------
Math.random()
?
/K
П р о с т и т е , но
э т о был во пр о с
с п о дв о хо м !
О т в е т о м на
него являет ся
сл учайное число.
к о н с т а н т а Р1
значение
Генерация случайных чисел
Все числа
Не важно, псевдослучайные или нет числа генерируются методом
в диапазоне
rando m () объекта Math, они полезны в нашем случае, когда нужно за­
о т о до 1 .
ставить приложение YouCube сделать случайный выбор из набора дан­
ных. Проблема в том, что метод ran dom () возвращает число в диапазо­
не от Одо 1, в то время как Руби требуется число от Одо конца массива
записей. Другими словами, нам нужно создать случайный индекс.
0.?8990286m85206
f -'o k --З
a l e r t ( M a t h .r a n d o m ());
0-436133S831S1724
a l e r t ( M a t h .r a n d o m ()); ■
a l e r t ( M a t h .r a n d o m { ) ) ; •
0.962859892?91690S
Для получения случайного числа в диапазоне, отличном от О
до 1, вам потребуется еще один метод объекта Math. Метод
f l o o r () округляет число до ближайшего целого, отбрасывая
дробную часть. Именно он наилучшим образом подходит для
наших целей.
f '- ; о к ^ З
0 - 5
Г
Ф
var
V
ttt
f
454
глава 9
oneToSix
= Math.floor(Math.random(
1-6
6)
1;
оживляем данные
Часзцо
чаДаБаеМые
БоЦ РоС Ь!
Почему не требуется создавать
объект Math?
Q ; Этот вопрос касается крайне важного
понятия, связанного с объектами. Так
как объекг
M ath
В чем разница между методами
и f l o o r О объекта
ro u n d О
Math?
не содержит данных,
которые может изменять, его не
требуется создавать. Как вы помните,
этот объект представляет собой всего
лишь набор статических методов
и констант, так что все его составные
части уже существуют — и вам просто
нечего создавать. Впрочем, все это станет
понятнее в главе 10, когда мы приступим
к изучению классов и реализаций
объектов.
Что еще умеет объект Math?
Q ; Многое. Например, два полезных
метода, которые нам пока не
Q ; Метод r o u n d ( ) округляет
в зависимости от значения
десятичной части. Например,
требовались — m in () и max (),
анализируют два числа и возвращают
M a th , r o u n d (1 1, 37 5)
a b s O возвращает положительное
число вне зависимости от переданного
даст
в результате 11, в то время как M a t h .
r o u n d (11 , 625) - 12. Метод
же f l o o r ( ) всегда округляет путем
отбрасывания десятичной части, не важно,
насколько она велика.
меньшее или большее из них. Метод
ему аргумента.
реш ение упражнения
Возьми В руку карандаш
'ешение
Вот код функции гапс1отВ1од ( ) , случайным образом вы­
бирающий запись из блога и отображающий ее в отдельном
окне.
И с п о л ь зу й т е сл у'члйн об число для
вы бора зап и си .
Г е н е р и р у е т сл уч а й н о е число
о ди ап азон е о т о до числа на
единицу м е н ь ш е го , чем к о л и ­
ч е ст во за п и сей в блоге.
fu n c tio n ra n d o m B lo g Q {
/ / В ы б ер и т е случай н ое, число о т О до числа за п и с ей - i
v a r i = M a th .flo o r(M a th .r a n d o m () * h log.ien gth);
4 ------ —
----- -
a le r t( “[" 4- (b lo g li].d a te .g e tM o n tk () + i ) + " / " + h lo g [i].d a te .g e tP a te Q + " /“
blogliJ.date.getF u liY earQ +■ "] " + b lo g [i].b o d y);
}
О т ф орм ат и руй т е резул ьт а т т аким об­
р а з о м , чт обы п о сл е т е к с т а зап и си вы во ди лась ее д а т а в виде М М / Д Д / Г Г Г Г .
Хотелось бы чего-нибудь ещ е...
Б л о г Руби т е п е р ь п о д д е р ж и в а е т ф ункц ию п о и с к а случайн ы х
со о б щ ен и й , и о н а счастл и ва. Т е п е р ь п о л ь зо в а т ел и п р и п р о ­
см о тр е за р а н е е за и н тр и го в а н ы , ведь о н и н е зн аю т, какая из
за п и с е й будет им по казан а.
;.Mixed
С лучайны м о б р а зо м
оы оранная за п и сь
олога.
feelings
^^ x 7 x 7 c u b e fo r*a le o n lin e ,Y ik « > .T h a t
{8/16/2008) Managed to get a headache tolling over the
|^ S n e w c » b e b u to r c o u m .n o w T m b « «
o 'o S w c u b e lo r ie s d . t f s a ^ a ! pearl,
яио» АН goa
456
глава 9
Н е с м о т р я н а в о сх и щ ен и е н о в о й ф ун кц и ей ,
Р^би н е м о ж е т отд ел аться о т чувства, ч то
блогу все ещ е чего-то н е хватает. Ее об ъ ­
ек т B lo g в н а сто я щ е е в р е м я п р е д став л я ет
с о б о й всего пару сво й ств, в основу р аб о ты
к о т о р ы х п о л о ж ен ы о т д е л ьн ы е ф ункц ии.
Н е сам ая лучш ая к о н стр у к ц и я, н а взгляд
Руби...
оживляем данные
Объект В поисках geucmBuu
Руби обеспокоена. Поведенческая часть объекта совершенно
недостаточна и нуждается в серьезной перестройке, в резуль­
тате которой отдельные задачи начнут решаться при помощи
методов. Руби нужны методы, которые определят поведение
объекта Blog!
А ведь я могла бы
воспользоваться неко­
торыми методами.
— у
------------
Возьми 8 руку карандаш
Изучите код YouCube и обведите код, который, с вашей точки зрения,
можно поместить в методы объекта Blog; присвойте методам имена.
f u n c t i o n showBlog(numEntries) {
/ / Сортируем записи в обратном хронологическом порядке (последние впереди)
b l o g . s o r t ( f u n c t i o n ( b l o g l , Ыод2) { r e t u r n b l o g 2 . d a t e - b l o g l . d a t e ; });
/ / Выбираем число записей, чтобы при необходимости показать блог целиком
i f ('n u m E n trie s)
num Entries = b l o g . l e n g t h ;
/ / Показ записей блога
v a r 1 = 0 , b logT ext =
w h ile ( i < b l o g . l e n g t h && i < num Entries) {
/ / Используем для каждой записи серый фон
i f (i % 2 == 0)
b lo g T e x t += "<р s t y l e = ' b a c k g r o u n d - c o l o r : #ЕЕЕЕЕЕ'>";
else
b lo g T ex t += "<p>";
/ / Генерируем отформатированный HTML-код блога
b lo g T ex t += "< stron g> " + ( b l o g [i ] . d a t e . g etM o n th ()
b lo g [ i] .d a te .g e tD a te 0 + "/" +
b lo g [i] . d a t e . g e t F u l lY e a r O + " < / s t r o n g X b r />"
b l o g [ i ] . b o d y + "</p>";
i++;
/ / Располагаем HTML-код блога на странице
docum ent. g e tE le m e n tB y ld (" b l o g " ) . innerHTML = b lo g T e x t;
}
f u n c t i o n se a rc h B lo g O {
v a r s e a rc h T e x t = d o c u m e n t .g e t E l e m e n t B y I d ( " s e a r c h t e x t " ) .v a lu e ;
f o r (var 1 = 0 ; i < b l o g . l e n g t h ; i++) {
/ / Проверяем, включает ли запись строку поиска
i f ( b l o g [ i ] . b o d y .t o L o w e r C a s e О .in d e x O f(s e a rc h T e x t.to L o w e rC a s e (
!= - 1 )
+ ( b l o g [ i ] . d a t e . g e t M o n t h O + 1) + " / " + b l o g [ i ] . d a t e . g e t D a t e 0 + " / "
ale rt("
b lo g i ] . d a t e . g e t F u l l Y e a r O + "] " + b l o g [ i ] . b o d y ) ;
b re a k ;
}
/ / Если строка поиска не обнаружена, сообщаем об этом
i f (i == b l o g . l e n g t h )
a l e r t ( " S o r r y , t h e r e a r e no b lo g e n t r i e s c o n t a i n i n g t h e s e a r c h t e x t . " ) ;
}
f u n c t i o n randomBlogO {
/ / Выбираем случайное число от О до b l o g . l e n g t h - 1
v a r i = M ath. f l o o r ( M a t h . random О * b l o g . l e n g t h ) ;
a l e r t ( " [ " + ( b l o g [ i ] . d a t e . g e t M o n t h O + 1) + " / " + b l o g [ i ] . d a t e . g e t D a t e () + " / " +
b l o g [ i ] . d a t e . g e t F u l l Y e a r O + "] " + b l o g [ i ] . b o d y ) ;
}
далее >
457
реш ение упражнения
Возьми в руку карандаш
'ешение
Вот код, который можно поместить в методы объекта B lo g .
f u n c t i o n showBlog(numEntries) {
/ / Сортируем записи в обратном хронологическом порядке (последние впереди)
Ы о д . s o r t ( f u n c t i o n ( b l o g l , blog2) { r e t u r n b l o g 2 . d a t e - b l o g l . d a t e ; });
/ / Выбираем число записей, чтобы при необходимости показать блог целиком
ii ff
f( !I num
r m m F .n
1 - г -i
^
.
Entries)
num Entries = b l o g . l e n g t h ;
М е т о д B log.toH TM LO
п р е о б р а з у е т за п и с ь блога
^от ф орм ат ированны й
/ / Показ записей блога
v a r i = О, b lo g T ex t =
w h ile (i < b l o g . l e n g t h && i < num Entries) {
/ Z--i^5nojib3yeM для каждой записи..серый фон
(i % 2 == 0)
b lo g T ex t += "<p s ty le = 'b a c k g ro u n d -c o lo r:# E E E E E E '> " ;
else
b lo g T ex t += "<p>";
n iM L -ф р а г м е н т .
^
/ / Генерируем отформатированный HTML-код блога
b lo g T ex t += "<stron g> " + ( b l o g [i ] . d a t e . g etM on th ()
b lo g [ i] .d a te .g e tD a te 0 + " /" +
\ b l o g [ i ] . d a t e . g e t F u l l Y e a r 0 + " < / s t r o n g x b r />" +
\ W o g [ i ] . b o d y + "</p>";
i++;
}
/ / Располагаем HTML-код блога на странице
document.getElementByld("blog").innerHTML
=
blogText;
}
f u n c t i o n sea rc h B lo g O {
v a r s e a rc h T e x t = docum ent. g e tE le m e n tB y ld (" s e a r c h t e x t " ) .v a l u e ;
f o r (var 1 = 0 ; i < b l o g . l e n g t h ; i++) {
/ / Пр0 ВЁРяам..---В1ашы.а£-Т .пи запись строку поиска_____________
i f Q b l o g [ i ] . body. toLowerCase () . indexOf ( s e a r c h T e x t . to L o w e r C a 's ^ ^
a l g g e - r - r - -b (bTog [ 11-Т^ЭТГ Г?5ТтапГГТ7~ Т - Т Г ^ - "7 " '''~Г-И:одТТ7^
(_ b l o g [ i ] . d a t e . g e t F u l l Y e a r 0 + "] " + b l o g [i 1 . b o d v );
Ь г е а т г г " ----------------- — —------------------------------------------------ -------------------------- --- —
Г^~ГТЗ
........ .....
}
/ / Если строка поиска не обнаружена, сообщаем об этом
i f (1 == b l o g . l e n g t h )
a l e r t ( " S o r r y , t h e r e a r e no b lo g e n t r i e s c o n t a i n i n g th e s e a r c h t e x t . " )
}
f u n c t i o n randomBlogO {
/ / Выбираем случайное число от О до b l o g . l e n g t h - 1
v a r i = M a th .flo o r(M a th .ra n d o m О * b l o g . l e n g t h ) ;
a l e r t (" [" + ( b l o g [i ] . d a t e . g etM o n th () + 1) + " / " + b l o g [ i ] . d a t e . g e t D a t e () + " / " +
b l o g [ i ] . d a t e . g e t F u l l Y e a r 0 + "]
b lo g [i].b o d y );
}
M em дбльилую н а гр у зк и
Должен о т о б р а ж а т ь х орош о
о т ф о р м а т и р о в а н н ы й блог.
458
глава 9
Н ебольш ой по р а з м е ­
р у , но п олезны й м е т о д
Blog■ContalnsTextQ б у ­
д е т о т в е ч а т ь за п ои ск
т е к с т а в блоге.
б ст року^ Е го и м е е т см ы сл
и с п о л ь з о в а т ь в си т у а ц и ях, к о гда д а т а в к в а д р а т ных скобках вы води т ся п о сле
т е к с т а записи.
Часзцо
оживляем данные
^аД аБ аеМ ы е
B o n j> o c ; b i
Как понять, какой код можно
превратить в метод?
0 ; Для начала следует понять, для
чего будет предназначен этот метод
и какие действия он будет совершать над
данными объекта. В некоторой степени
определение методов объекта зависит
от того, что именно делает или должен
будет делать объект. После чего мы
даем объекту возможность выполнять эти
действия.
Например, объекту B lo g целесообразно
иметь способность превращать себя
в строку или в отформатированный HTMLкод, ведь эти действия требуют доступа
к внутренним данным блога. Аналогично,
поиск текста в записях — это внутреннее
действие объекта B lo g , а значит, имеет
смысл превратить его в метод.
I
За пределы возможностей объекта
B lo g выходят такие действия, как поиск
или отображение списка записей. Ведь
этот объект представляет единственную
запись. Именно поэтому массив Ы о д
состоит из набора отдельных объектов
B lo g . И каждый такой объект никак не
должен касаться действий, производимых
со всем набором.
3 * А как насчет примера действия,
которое объект B lo g не сможет
выполнить?
Превращение функции В метод
Т еп ер ь , когда м ы р еш и л и , к ак и е и м е н н о ф р а гм е н т ы кода блога
Y o u C u b e д о ст о й н ы превраш ;ения в м ето д ы о б ъ ек т а B lo g , п о см о тр и м
н а саму проц едуру п р е о б р а зо в а н и я . В ка ч е с тв е п р и м е р а возьм ем м е­
тод c o n t a i n s T e x t ( ) , о тв е ч а ю щ и й за п о и с к в т ел е зап и си указан н ого
п о л ь зо в ател ем н а б о р а сим волов. П е р е м е щ е н и е ко д а в м етод п р о в о ­
д и т о п е р а ц и ю н е п о ср е д с тв е н н о над сво й ств о м b o d y о б ъ е к т а B lo g ,
в о т л и ч и е о т л о к а л ь н о й п е р е м е н н о й в ф у н кц и и s e a r c h B lo g ( ) . В от ^ Ц О Г
п о ш аго в о е о п и с ан и е про ц есса:
О б ъ яв и м м етод, со стави м сп и со к
аргум ентов, н а п р и м е р , для м ето д а
c o n t a i n s T e x t () эт о с т р о к а пои ска.
О
О
П о м ести м код в н о в ы й м етод.
З астав и м код и с п о л ьзо в ат ь с в о й ств а о б ъ екта,
в наш ем случае св о й с тв о t h i s . b o d y .
to S tr in g О
^
І І И up w ith eoifcWP*®
fe llo w c u b e rs
p
to d iscu ss th e
і tcHT-MLO
X —,
p r o s p e c t..."
I
d a te
lA u g u st 1 4 th ,
--------— —
é
c o n t a in s T e x t( )
««ИМ Я
з
Возьми в руку карандаш
Напишите код для метода c o n t a i n s T e x t ( ) , создавае­
мого в конструкторе B lo g () путем назначения литерала
функции ссылке t h i s . c o n t a in s T e x t .
далее ►
459
бы ст ры е изменения
Возьми в руку карандаш
Решение
Вот код для метода c o n t a i n s T e x t ( ) , создаваемого
в конструкторе B l o g () путем назначения литерала функции
ссылке t h i s . c o n t a i n s T e x t .
М ето Э с о зд м ш с я
назначением л и т е раАй ф ункц и и ссы лки
на него.
.7. f . ’^ n c t i p n { t e x t ) {
r e t u r n (tkis.bodij.toL ow erC aseQ .m dexO f(teK t.toLow erC aseQ ) != - 1 );
V
и с п о л ь зу е т с я для со зд а \ _ т я м ет о д а т е м же способом , к о т о р ы м
с его п о м о щ ь ю создавались сво й ст ва
м ет о д а и м е е т непосредст венны й
к сво й ст ва м о б ъ ект а пр и п о м ощ и клю чевого слова this.
Восхитительный новый объект blog
Эй,теперь
я в хорошей
форме!
Еще два метода соединились с методом c o n t a i n s T e x t () в новой
версии объекта B lo g , который теперь обладает и свойствами и по­
ведением.
f u n c t i o n B l o g (body, d a t e )
// н а з н а ч а е м с в о й с т в а
~ СоъЪание
и и н и ц и а л и за ­
ция свойст в.
{
t h i s . body = body;
t h i s . date = date;
М ет о д to S trin g Q в о з ­
вр а щ а е т за п и сь блога
of
the b l o g
+ 1)
Г ° оиде т ек с т о во й
W
ст р о ки .
entry
+ "/"
t h i s .d a t e .g e t D a t e
this.body;
};
// Возвращаем форматированное HTML-представление
th is .to H T M L = f u n c t i o n ( h i g h l i g h t )
{
// И с п о л ь з у е м д л я в ы д е л е н и я с е р ы й ф о н
?
"<Р
записи
М ет од toH TM L() в о з ­
в р а щ а е т за п и сь блога
как о т ф о р м а т и р о ­
ванный Н ТМ и-код.
s ty le - b a c k g r o u n d - c o lo r T # E E E E E E '> "
" <р>";
// Г е н е р и р у е м о т ф о р м а т и р о в а н н ы й H T M L к о д б л о г а
Ы о д Н Т М Ь + = " < s t r o n g > " + ( t h i s .d a t e . g e t M o n t h () + 1) + " / " +
' r t h i s ’d a t e . g e t F u l l Y e a r O + " < / s t r o n g X b r
this.date.getDateО +
t h i s . b o d y + "</p>";
return blogHTML;
-
};
460
глава 9
/>"
М ет о д containsT extQ
во звр
, а щ а ет значение
tr u e , если т е к с т с о д ер ­
ж ит п о и ско вую ст р о ку.
// П р о в е р я е м , с о д е р ж и т л и б л о г с т р о к у т е к с т а
t h i s containsText = f u n c t i o n ( t e x t ) {
r e t u r n ( ( t h i s . b o d y . t o L o w e r C a s e 0 . i n d e x O f ( t e x t .t o L o w e r C a s e
};
<
J
‘^ ' ^ ф о р м а т и р о в а н н у ю '
// R e t u r n a s t r i n g r e p r e s e n t a t i o n
t h i s . toString = f u n c t i o n 0
{
r e t u r n "[" + ( t h i s . d a t e . g e t M o n t h
t h i s . d a t e . g e t F u l l Y e a r O + "]
b lo g H T M f™ \lg h lig h t
^
0 ) != -1);
оживляем данные
Ч то дают объекты блогу YouCube?
Думаю, вы поняли преимущества объектно-ориентированного програм­
мирования еще до появления новой версии объекта B log (она доступна
по адресу http://www.headfirstlabs.com/boohs/hjjs/). Теперь, когда решение
ряда важных задач отдано на откуп методам объекта B log, код сценария
стал намного проще.
Новый объект Blog
упрощает сценарий
блога YouCube.
/ / Show t h e l i s t o f b lo g e n t r i e s
f u n c t i o n showBlog(numEntries) {
/ / Сортируем записи в обратном хронологическом порядке (последние впереди)
Ы о д . s o r t ( f u n c t io n ( b l o g l , Ыод2) { r e t u r n b l o g 2 . d a t e - b l o g l . d a t e ; ) ) ;
/ / Выбираем число записей, чтобы при необходимости показать блог целиком
i f ( [n u m E n tries)
num Entries = Ы о д . l e n g t h ;
/ / Цикл пока записей блога
v a r 1 = 0 , blogListHTML =
w h ile (i < b l o g . l e n g t h && i < num Entries) {
blogListHTML += Ы о д [i] . toHTML ( i % 2 == 0) ;
i+-i-;
}
М ето Э toHTMLQ
sAOAHOcmbH) о т ­
ве ч а е т за HTM Lih op м а т и р о ва н и е
записей блога.
/ / Располагаем HTML-код блога на странице
d ocum ent.getE lem entB yld("blog").innerH T M L = blogListHTML;
}
Ищем фрагмент тек ста в записях блога
f u n c t i o n sea rc h B lo g O {
v a r s e a rc h T e x t = d o c u m e n t .g e t E l e m e n t B y I d ( " s e a r c h t e x t " ) .v a lu e ;
f o r (var 1 = 0 ; i < b l o g . l e n g t h ; i++) {
М ет о д containsT extQ
/ / Проверяем, включает ли запись строку поиска
и щ е т 6 записи у к а за н н у ю
i f (b lo g [i].co n ta in sT ex t(sea rch T ex t)) {
п о л ь зо в а т е л е м ст р о ку.
a l e r t ( b l o g l i ] );
М ет од to S trin g O
break;
а вт о м а т и ч е с к и в ы ­
II
зы вает ся в случаях^
когда за пись и с п о л ь ­
зу е т с я т а м , где
нужнй ст рока.
}
/ / Если строка поиска не обнаружена, сообщаем об этом
i f ( i == b l o g . l e n g t h )
a l e r t ( " S o r r y , t h e r e a r e no b lo g e n t r i e s c o n t a i n i n g t h e s e a r c h t e x t . " ) ;
}
/ / Отображаем случайно выбранную запись
f u n c t i o n randomBlogO {
/ / Выбираем случайное число от О до Ы о д . l e n g t h - 1
v a r i = M a th .flo o r(M a th .ra n d o m О * b l o g . l e n g t h ) ;
a l e r t ( b l o g t i ] );
}
~
~
--------- — ------------------ -
далее >
461
гот овност ь к большим делам
YouCube 3 .0 !
Руби о ф и ц и а л ь н о о б ъ яв и л а, ч то о н а д о в о л ь н а в е р с и е й блога
Y o u C u b e 3.0 и п р е д п о ч и т а е т вер н у ться к го л оволом к ам и к п о д го то в ­
ке в е ч е р и н к и для т а к и х ж е, как она, ф ан ато в...
За п и си блога p m c o p m u p o t o «
хо р о ш о о т ф о р м а т и р о в а н н ь ...
...возмож ен поиск
по блогу...
г
й
YouCube - Tht
100
Blog for Cube Piwzlers
СрягсН the ffloa i|7x7x7
feelings.
18/29/20081 Met up with some fellow cubers to discuss
the prospect o f a 7x7x7 cube. Mixed feelings.
..возмож ен п р о с м о т р
случайно вы дранной
ізаписи...
^
^
lo lS e new OTbebut of
M ^ t o g e t a h c a d a c h e t o f f in g o v e it f iiW »
шЪе 1ofdcied. It's a гей pearl.
Show A jij£ i£ ! ! l! £ L j
Blog
462
глава 9
-б л а го д а р я с п е ­
ц и а ль н о м у о З ь е к т у Blogl
оживляем данные
Вкладка
Согните страницу
по вертикали, чтобы
совместить два мозга
и реш ить задачу.
^
Что моїуг сделать с данными объекты
JavaScript?
'V М хороШо, а ДВа лучше!
Ищите, что хотите, но вряд ли вы
найдете что-то лучше, чем
о^ к ты Дауа8спр1 для сортировки
и анажза данных. Они умеют даже
генерить случайные числа.
^ п е Ц и а Л ь Н ы е
о ^ ь е К ш ы
%
Работа со специальными
Ф
объектами
Если бы все было так легко, мы бы, конечно, так и сделали.
иауа8спр1 не гарантирует возврат денег, но вы действительно можете делать
с ним все, что захотите. Специальные объекты — это эквивалент тройного
эспрессо с сахаром и корицей. Вот такая специальная чашка кофе! Точно так
же в специальных объектах вы можете смешивать код, добиваясь именно
того результата, который вам нужен, и пользуясь преимуществами свойств
и методов. 1/1 в конце получается объектно-ориентированный код, расширяю­
щий язык иауаЗспр1... только для вас!
мет оды блога
Снова о методах блога YouCube
Блог YouCube работает,
но его нельзя причислить
к самым удачным образцам
о^ектно-ориентированного
программирования.
Н е с м о т р я н а т о ч т о в п р о ш л о й главе Руби п р о д ел а л а больш ую
раб о ту п о со зд ан и ю о б ъ е к т а B lo g д ля у п р ав л ен и я своим блогом
Y ou C u b e, н еск о л ьк о к л ю чевы х для о б ъ е к т н о -о р и е н т и р о в а н н о го
п р о гр а м м и р о в а н и я в о зм о ж н о с те й о с тал и сь за кадром . О н а н е
удели ла д о л ж н о го в н и м ан и я э ф ф е к т и в н о с т и о б ъ е к т а B lo g , его
структуре и, сл ед о ватель н о , в о зм о ж н о с ти р е д а к ти р о в а ть его
в будуш;ем.
О с т ан о в и л и с ь м ы , как вы п о м н и те, н а с о зд ан и и т р е х м етод ов
для в ы п о л н е н и я св я за н н ы х с блогом задач.
' Последняя версия данных ф а й ­
л о в д о ст уп н а для скачивания по
Блог
адресу h ttp ://w w w .k e a d fir s t!a b s .
с о т / b o o k s/h fjs/.
Три метода объекта Blog
предназначены для задач,
выполняемых внутри за­
писей блога.
Blog (body, date)
,назначаем свойства
.body - body;
ite - date;
Мне так нравятся
методы объекта
Blog.
(
'звратаем строковое представление записи блога
:l.toString = functionO
+ 1) + ”/" + this.date.getDateО
{
+ ”/" +
r^i-urn -■[" + (this.date.getMonthO + 1) + /
thS.dlte.getEullYearO . " 1 ■■ ^ this.body;
};
// возвращаем форматированное HTML-представление записи
t h i s.toHTML - function(highlight)
//
И спол ьзуе м
b S g ^ i "
(
для вьшеления серый фон
i^bligbt , "<Р style=.bac.g.ound-colot:«EEEEE.>.. :
// генерируем отформатированный HTML-код блога ^
’^ " t r r t : . ; : r t : r V ^ V " " ' t h t r d r t e . g e t P u l l y e a t O
^
t ..</.ttongXb. />" .
this.body + ■'</?>";
return blogHTML;
};
// проверяем, содержит ли блог отроку текста
Н а п е р в ы й взгляд м его д ы , и сп ользуем ы е в блоге
Y o u C u b e, вы гл яд ят п р е к р а сн о , н о ес ть од н а проб лем а...
466
глава 10
специальны е объекты
Перегрузка методоВ
Т о ч н о т а к ж е, как и сво й ства, м ето д ы о б ъ е к т а B lo g созд ан ы
вн утр и к о н с тр у к то р а п р и п о м о щ и кл ю ч ев о го сл о в а t h i s . П р и
таком п од ходе д ля каж дого в н о в ь со зд ан н о го о б ъ ек т а B lo g
созд аю тся и т р и к о п и и м ето д о в. Т ак ч то , н а п р и м е р , для блога
и з ш ести за п и с ей м ы получим ш есть и х ко п и й .
Texto
!^лждый из
созданны х о б ъ ­
е к т о в Blog
получает
contalnsTextO
собст вен ную
Копию т р е х
методов.
О бъект B log ненам еренно создает больш е м етодов, чем это необходим о,
что крайне н еэф ф ек тивн о.
Н икуда о т это го н е д еться, ко н стр у к то р B lo g () со зд ает п о т р и м етод а п р и
каж дом с о зд ан и и н о в о го о б ъ ек та, и в р езу л ьтате каж ды й о б ъ е к т B l o g п о ­
лучает собственн ую к о п и ю каж до го и з м етодов. Н о есл и св о й ст в а каж дого
о б ъ е к т а с о х р а н я ю т у н и кал ьн ы е д ан н ы е , м ето д ы в п о л н е м о ж н о о тд ать о б ъ ­
ектам в со в м е с тн о е п о л ьзо в ан и е. Н аск о л ьк о э ф ф е к т и в н е й б ы ло бы , если
бы все о б ъ е к т ы B l o g и с п о л ьзо в ал и одну и ту ж е к о п и ю каж дого и з м етодов.
Э то п р е д о т в р а т и л о бы и зл и ш н ее у в е л и ч ен и е о б ъ ем а с ц е н а р и я из-за п о я в л е­
н и я и зб ы т о ч н ы х м ето д о в по м е р е н е и зб е ж н о го р о с т а ч и сл а зап и сей .
м озговой
Ш Т У РМ
Что нужно сделать с объектом B log , чтобы код методов не дублировался при создании
каждой следующей копии?
далее >
467
а теперь класс... в этой реализации
Классы и реализации
П р о б л е м а с д у б л и р о ван и ем м ето д о в за т р а ги в а е т к р а й н е
важ ную к о н ц еп ц и ю , связанную с о б ъ ектам и : р азн и ц у между
классом и реализацией об ъекта. К л ассо м н а зы в ае т ся о п и са­
н и е о б ъ екта, ш аб лон , д аю щ и й п р е д с та в л е н и е о том , и з ч его
со с то и т о б ъект. Р е а л и за ц и я ж е это сам о б ъ ект, со зд ан н ы й
и з класса. В т е р м и н а х р е а л ь н о го м и р а м о ж н о сказать, ч то
класс — это п р о е к т дом а, в т о в р ем я как р е а л и за ц и я — сам
дом. В зяв за о сн ову о д и н ч е р т е ж , м о ж н о п о с т р о и т ь м ного
дом ов.
Класс объекта
Блог
468
глава 10
Реализации объекта
специальны е объекты
Класс объекта — ^
шаблон, в то время как
реализация — созданный
по этому шаблон^^ объект.
Реализации
Класс описывает свойства и методы объекта, в то время как
реализация присваивает свойствам реальные данные и за­
ставляет их действовать. Все реализации имеют собственные
копии свойств, что позволяет им уникальным образом отли­
чаться друг от друга.
body/ "Managed to get a
date'' August 16th, 2008
Значения сво й ст в за ча ст ую
р а зл и ч а ю т с я у разны х
реализаций, п о э т о м у т а к
важно, чт обы каждая р е а лиза ц и я обладала собст вен­
toString
toHTML
containsText
ной копией.
Свойства.
(
Л "Found а 7x7x7 cube.
toString
М ет оды .
-—
body^
date
X ^ J ^ s t 21st, 2008
/FunctionO
functionO
'
У
{ ...
{ ... }
.^functi^iTo^^
..—
—
.
body "Met up with some..."
A в о т дуб ли р о ва т ь
м ет о д ы для каждой
р еа ли за ц и и вовсе не
т ребует ся
date
.
toString
toHTML
August 29th, 2008
f functionO
{
- N
function() { ... }
containsText V functionO
{
- J
далее >
469
два раза отмерь, один отрежь
Ключевое слово this
Д о си х п о р м ы и м е л и дел о в о сн о в н о м со свойствами реализаций.
П р и это м каж дая р е а л и за ц и я об лад ала их с о б ст в е н н о й к о п и ей .
Т а к и е с в о й ств а л егко и д е н т и ф и ц и р о в а т ь , т а к как и м ен н о о н и за­
д аю тся в к о н стр у к то р е п р и п о м о щ и к л ю чевого сл о ва t h i s .
f u n c t i o n B log(body, d a te )
Ключевое слово this
задает свойства и ме­
тоды реализаций.
{
t h i s . b od y = body;
t h i s . d a te = date ;
Э т о свойства реализации,
т ак как на них ссы л а ю т -
-------- --------
СЯ
при помощ и ключевого
слова this.
Сущ ествую т и м ето д ы р е а л и за ц и й , н о с н и м и все го р азд о сл о ж н ее,
та к как о н и м огут н ах о д и ться в с о б с т в е н н о ст и как р е ал и за ц и и , так
и класса. Д о эт о го м о м ен та м ы и м ел и д ел о с м етод ам и , зад ан н ы м и
п р и по м о щ и к л ю чево го сло ва t h i s , т о е с ть с м етод ам и р е ал и за ц и й .
И м е н н о п оэтом у м ето д ы д у бл и р о вал и сь о т эк зе м п л я р а к экзем пляру.
f u n c t i o n B log(body, d a te )
t h i s . toString = f u n c t i o n O
Все эт о мет оды
{
реализаций, т ак
как они задаю т ся
В се реализации обь
ект а Blog получаю т
собственные копии
эт и х методов-
о кон ст р укт ор е
клю чевым словом
this.
th is .to H T M L = f u n c t i o n O
{
t h i s . containsText = f u n c t i o n O
{
Х о р о ш ей н о во стью я в л я е т с я т о , ч т о сп е ц и а л ь н ы е о б ъ ек ты
в о все н е о б я зан ы впустую со зд авать дублирую щ ийся код
м етод ов с п о я в л е н и ем каж дой н о в о й р е а л и за ц и и . Д о с тат о ч н о
со зд ать м етод таки м о б р азо м , ч то б ы все р е а л и за ц и и см огли
и с п о л ь зо в ат ь одну и ту ж е к о п и ю его кода.
470
глава 10
специальны е объекты
Методы классов
Сущ ествует и д ругой вид м ето д о в, п р и н а д л е ж ащ и й со б с т в е н н о
классам , ч то о зн а ч а е т в о зм о ж н о сть доступа в с е х р е а л и за ц и и
й
к ед и н с т в е н н о й ко п и и . Т а к о й подход н ам н о го э ф ф е к т и в н е й т о го ,
ч то м ы и с п о л ьзо в ал и р ан ьш е.
Э т о т м ет од принадле­
ж ит классу Blog, п о эт а м и
Данные эт и
р еали за ц и и х р а ­
н я т в своих с во й ­
с т в а х . но д о ст уп
к «X м е т о д а м
о с ущ е ст в ля е т с я
через класс Blog-
Е с ли м ето д п р и н а д л е ж и т классу, к нем у и м ею т доступ все
р еа л и за ц и и , и по это м у и х со б с тв е н н ы е к о п и и им уже н е т р е ­
бую тся. Т а к о й по д х о д н ам н о го б о л ее э ф ф е к т и в е н , о с о б е н н о
есл и уч есть, ско л ьк о л и ш н и х м ето д о в в и т о г е п о я в л я е тся
в п р и л о ж е н и я х , п о с т о я н н о создаю щ их н о в ы е р е а л и за ц и и об ъ ­
ектов. В блоге Y o u C u b e т р и м ето д а ( t o S t r i n g ( ) , toHTML ()
и c o n t a i n s T e x t ( ) ) д у бл и р о вал и сь бы вм есте с каж дой н о в о й
запи сью .
Хранение метода в классе
позволяет всем реализациям
пользоваться одной копией.
Т е п е р ь о стал о сь п о н я т ь , как сд ел ать та к , ч то б ы м ето д стал п р и ­
н ад л еж ать классу...
далее ►
471
у каждого объекта е с т ь ...
Прототипы
П о я в л е н и е т о го , ч т о м ы н азв а л и классам и, стало возм ож н ы м
в Jav aS crip t б лаго д ар я скр ы то м у об ъекту p r o t o t y p e , сущ еству­
ю щ ем у как св о й с тв о лю б о го о б ъ екта. И м е н н о о н п о зв о л я е т за­
д ав ать с в о й ств а и м етод ы , принадлежащие классам. Д ав ай те
п о см о тр и м , как эт о д ел ается.
яв­
ля е т с я л и т е р а л .
B l o g .p r o t o t y p e . toHTML = f u n c t i o n O
{
Л
И м я класса.
О б ъ е к т p r o to ty p e
д о ст уп ен как с во й ­
ст во класса.
В д ан н о м п р и м е р е м ето д toHTML () д о б а в л я е тся к классу B lo g ,
а н е к какой-либо р е а л и за ц и и это го класса. Н е в а ж н о , сколько
о б ъ е к т о в B lo g м ы создадим , к о п и я м ето д а toHTML () все р ав н о
будет то л ь к о одна.
Т ак как м ето д toHTML () п р и н а д л е ж и т классу B lo g , в это м ж е
классе р а с п о л о ж е н и код, запускаем ы й п р и вы зо ве м етода. Н о
т е х н и ч е с к и эт о все р а в н о м ето д р е а л и за ц и и , т ак как он м ож ет
б ы ть вы зван н а у р о в н е о б ъ е к т а и и м е е т доступ к свой ствам
эт о го о бъ екта.
v a r b l o g E n t r y l = new B log("N ot much go ing o n ." ,
b l o g E n t r y l . toHTML () ;
К од, за п уска ем ы й
пр и вызове м ет о д а
toH TM LQ , р а б о т а е т
в н у т р и класса.
П р и со зд ан и и следую щ его о б ъ е к та B lo g и в ы зо в е для н его м етод а
toHTML () запускается т о т ж е сам ы й код в н у три класса. В ид ите, как
вы го д н о , —с о х р а н и л о д и н р а з, а исп ользуеш ь, скол ьк о нужно!
v a r b lo g E n try 2 = new B l o g ( " S t i l l j u s t hanging a r o u n d ." .
b l o g E n t r y 2 . toHTML {)
472
глава 10
О ст а льн ы е объект ы
использую т т о т же
сам ы й м е т о д класса.
Блог
специальны е объекты
Классы, прототипы и YouCube
Руби н ем н о го о ш ел о м л ен а с в ед ен и я м и о классах и п р о т о ­
т и п ах , н о о н а чувствует, ч т о б лог Y o u C u b e м о ж н о вы год­
н о м о д е р н и зи р о в а т ь , связав м ето д ы о б ъ е к т а B lo g с о б ъ ­
екто м p r o t o t y p e .
Использование объекта
prototype для хранения
методов блога увеличит эф­
фективность кода YouCube.
containsTextO
Возьми В руку карандаш
Для хранения методов, которые теперь принадлежат классу,
в новой версии кода используется объект p r o t o t y p e . Вставь­
те ваши примечания и объясните, что именно происходит.
f u n c t i o n B l o g ( b o d y , d ate)
// Н а з н а ч а е м с в о й с т в а
t h i s . b o d y = body;
t h i s . d a t e = date;
{
}
// В о з в р а щ а е м с т р о к о в о е п р е д с т а в л е н и е з а п и с и б л о г а
B l o g . p r o t o t y p e .t o S t r i n g = f u n c t i o n O
{
r e t u r n "[" + ( t h i s .d a t e .g e t M o n t h () + 1) + "/" + t h i s .d a t e .g e t D a t e () +
t h i s . d a t e . g e t F u l l Y e a r 0 + "] " + t h i s . b o d y ;
"/"
+
};
// В о з в р а щ а е м о т ф о р м а т и р о в а н н о е H T M L - п р е д с т а в л е н и е з а п и с и б л о г а
B l o g . p r o t o t y p e .t o H T M L = f u n c t i o n ( h i g h l i g h t )
{
// И с п о л ь з у е м д л я в ы д е л е н и я с е р ы й ф о н
var blogHTML =
b l o g H T M L + = h i g h l i g h t ? " < p s t y l e = 'b a c k g r o u n d - c o l o r :# E E E E E E '>"
// Г е н е р и р у е м о т ф о р м а т и р о в а н н ы й H T M L - к о д б л о г а
b l o g H T M L + = " < s t r o n g > " + ( t h i s .d a t e .g e t M o n t h () + 1) + "/"
t h i s . d a t e . g e t F u l l Y e a r 0 + " < / s t r o n g X b r />" + t h i s . b o d y
return blogHTML;
: " <p>";
+ t h i s .d a t e .g e t D a t e () +
+ "</p>";
"/"
+
};
// П р о в е р я е м , с о д е р ж и т л и б л о г с т р о к у т е к с т а
B l o g . p r o t o t y p e .c o n t a i n s T e x t = f u n c t i o n ( t e x t ) {
r e t u r n ( t h i s . b o d y .t o L o w e r C a s e ().i n d e x O f ( t e x t .t o L o w e r C a s e {))
!= -1);
далее *
473
реш ение упражнения
Возьми в руку карандаш
'ешение
f u n c t i o n B l o g ( b o d y , d a te) {
// Н а з н а ч а е м с в о й с т в а
t h i s . b o d y = body;
______
t h i s . d a t e = date;
Итак, для хранения методов, которые теперь принадлежат клас­
су, в новой версии кода используется объект p r o t o t y p e .
Т еп ер ь в задачу к о н с т р у к т о р а
оходит т о ль к о создание и и н и ­
ц иа лизация свойст в.
/ / Возвращаем строковое представление записи блога
B lo g .p r o to ty p e .to S tr in g = fu n c tio n O {
re tu r n "[" + ^ (th is .d a te .g e tM o n th O + 1) + " /" + t h i s . d a t e . g e tD a te ()
t h i s . d a t e . f e t F u l l Y e a r 0 + "] " + th is .b o d y^;
1
Т ак ка к м ет о д ы ^на— ■—■ "
~ — ~— ----------— значаю т ся не о 5 ъ -
11 Возвращаем от^^матированное HTML-представление записи блога е к т у В Іод, НОЗНйЧІBlog.prototype.toHTMb = fu n c tio n (h ig h lig h t) {
н и е
п р о и с х о д и т Ьне
/ / Используем для выделения серый фон
конст рукт ора.
var blogHTML =
blogHTML += h ig h lig h t ? "<p sty le = 'b a c k g ro u n d -c o lo r: #EEEEEE'>" : "<p>";
/ / Генерируем отформатированный HTML-код блога
blogHTML += "<strong>" + ( t h i s . d a t e . getMonth() + 1) + "/" + t h i s . d a t e . g e tD a te () + V" +
t h i s . d a t e . g e t F u l l Y e a r О + " < /s tr o n g X b r />" + th is .b o d y + "</p>";
^ о г о , чт обы во спо льзова т ься клю чевы м словом th is
/ / Проверяем, содержит ли блог строку текста ^ К о н ст р укт о р е BlogQ.
B lo g .p ro to ty p e.co n tain sT ex t = fun ctio n (text) {
re tu r n ( th is .b o d y . toLowerCase0 . in d e x O f(te x t. toLowerCase0 ) != -1 );
};
Более эффективный YouCube
Т е п е р ь блог Y ou C ub e исп ользует методы классов и и зб ав и л ся о т
дублирую щ егося кода. И все это — б лагод аря п р о то ти п ам . Н е важ ­
но , сколько эк зем п л я р о в о б ъ ек та B lo g вы создадите, для всех н и х
сущ ествует всего од н а к о п и я м етода. И сам ое зам еч ател ьн о е, ч то
с т о ч к и зр е н и я сц е н а р и я блога Y o uC ub e н и ч е го н е изм ен и л ось.
2^т=>екты Blog
вы зы ваю т м і-1^ о д ы класса.
alert ( Ы о д [Ор ;
К л а сс Blog.
Ы о д [2] .toHTMLО ;
Ыод[3] .containsText("сглЬе") ;
474
глава 10
специальны е объекты
КЛЮ ЧЕВЫЕ
МОМЕНТЫ
Класс — это описание объекта, в то время как
реализация — это сам объект, созданный по этому
описанию.
Класс состоит из свойств и методов объекта, в то
время как сами объекты помещают в свойства дан­
ные и дают работу методам.
_
■
Ключевое слово t h i s используется для доступа
к объекту из его собственного кода.
■
Объекг p r o t o t y p e позволяет сохранять методы
в класс, предотвращая ненужное дублирование
кода.
Часзцо
З ад аваем ы е
B o T ^ o C jjI
3 * Я до сих пор не совсем понимаю,
зачем нужны классы и реализации.
данное свойство объекта; более того, он
вам возможность делать потрясающие
может принять X за переменную. Именно
поэтому в конструкторе при создании
Q ; Классы введены, чтобы облегчить
создание и повторное использование объ­
ектов. Единичные объекты можно созда­
вать в виде литералов, но при этом много
ресурсов тратится зря. Ведь этот процесс
сопровождается созданием дублирующе­
гося кода. Вы, как архитектор, который
требует перед постройкой очередного
типового дома заново чертить ему план.
и инициализации свойств требуется
вещи, ведь некоторые члены сценария
требуется поместить на уровень объектов,
в то время как для других нужен уровень
ключевое слово t h i s .
Совершенно другая природа объекта
классов. 1Мы подробнее поговорим об
этом позднее в этой главе.
p rototype.
Он обеспечивает нас
механизмом для создания классов. В от­
личие от таких языков, как C++ и Java,
в JavaScript классы не поддерживаются.
Они эмулируются при помощи прототи­
пов. Вы получаете похожий конечный
результат, но с применением объекта
А ведь можно создать шаблон и уже по
p rototyp e,
нему получить нужное количество объ­
емов, сэкономив усилия. Здесь нам на
помощь приходят классы — мы исполь­
JavaScript. Сохранив свойство или метод
который относится
к «скрытым» свойствам всех объектов
зуем один класс для создания нужного
количества объектов.
в объекте p r o t o t y p e , вы, тем самым,
делаете его принадлежащим к классу,
а не к реализации объекта.
Хорошо, классы помогают создать
копии объектов. А зачем при этом
нужны ключевое слово t h i s и объект
А каким образом в картину клас­
сов вписываются конструкторы?
prototype?
Чаще всего оно используется для до­
ступа к свойствам. Скажем, для доступа
к свойству X из метода нужно написать
th is
. X . Если написать просто
х, сце­
нарий не будет знать, где именно искать
Q ; Имена классов пишутся с большой
буквы, в то время как для записи имен
объектов используется СтильВерблюда.
Ведь реализация объекта является не
более чем переменной, а имена пере­
менных у нас записываются именно так.
Некоторая непоследовательность связана
с весьма вольным поначалу использо­
ванием термина «объект». Если быть
точным, то имена классов, например
Q ; Как вы уже знаете, за создание
объектов в JavaScript отвечают именно
^ ! Ключевое слово t h i s дает доступ
к объекту из его собственных методов.
3 * Я немного не понимаю стандарты
именования. Иногда имена объектов
начинаются с большой буквы, иногда
используется нижний СтильВерблюда.
Почему так?
конструкторы. Вместе с прототипами они
представляют два основных фрагмента
головоломки с классами в JavaScript.
Конструкторы задают все параметры объ­
ектов, в то время как прототипы делают
то же самое на уровне классов. Оба
механизма работают в паре, давая
Blog,
надо писать с большой буквы, а
имена объектов, например
или
Ы о д [ О]
b lo g E n t r y
стилемВерблюда.
Вспомните стандартные объекты, с кото­
рыми мы работали. Текущую дату/время
можно было сохранить в переменную
(реализацию) с именем
создавалась из объекта
now, которая
Date (класса).
далее *
475
подпишите здесь... и зд е с ь ... и зд е с ь ...
Подпись В блоге
Руби и щ ет и н ф о р м а ц и ю об у в е л и ч ен и и э ф ф е к т и в н о с т и и улучш ении струк­
туры , к о т о р ы х м о ж н о д о ст и ч ь ср ед ств ам и о б ъ е к т н о -о р и е н т и р о в а н н о го
п р о гр а м м и р о в а н и я . В п р о ч ем , ее и н те р е с у е т н е т о л ь к о у со вер ш ен ство ван и е
вн у тр ен н его кода, ещ е о н а р е ш и л а д о б а в и т ь к блогу новую ф ункцию .
#3^
Вот бы еще под каж­
дой записью появля­
лась моя подпись... вот
тут вот!
YouCube
- The Blog for Cube Puzzlers^
ube - The Blog for Cube Pimlers
Search
the ttiofl j |
some feUow cubers to discuss ihe piospwt of a 7x7x7 cube. Mixed
' jings.
F m i^ * ^ x 7 x 7 cube for sale online. Yikes! That one could be a Iwast.
S o l v e s aew cube but of cmrsa, now Tin bored and shopping for a new one.
M ^ ^ t o get a headache toiling over toe new cube. Gotta nap.
8/ 14/2008
GoE * c new cube I oKiered. Irs a real pearl.
Show All 8;og Ensfies j Iview a RandomJ l o a ,f n ^
Done
---------
Руби думает, ч т о эту задачу м ож н о р еш и ть , д обави в классу B lo g
с в о й ство s i g n a t u r e . З ат е м п а р а м е т р ы это го св о й ства зад аю т­
ся в к о н стр у к то р е и н а ч и н а ю т о то б р аж ат ь ся в каж дой запи си ...
и п р о б л е м а реш ен а!
Ш ТУРМ
А может быть, подпись следует сделать свойством реализации? Как вы думаете, почему
это не самая хорошая идея?
476
глава 10
специальны е объекты
_
част°
ЧаДаБаеМые
В опросы
3 * Что означает постоянно появ­
ляющееся словосочетание «объектноориентированный»?
это построение программ из объектов.
Вот, скажем, свойство d a t e , используе­
мое в записях блога, получено из объекта
D a te .
0 ! Термин объектно-ориентированный
часто используется в программистских
кругах, и порой им обозначают разные
вещи. В общем случае объектноориентированное программирование —„
Большинство программистов связывают
ООП с интенсивным использованием объ­
ектов в программах. В теории действи­
тельно объектно-ориентированная
программа может быть разбита на набор
взаимодействующих друг с другом объ­
ектов. Некоторые пуристы даже считают,
что иауаЗсг1р1 не относится к языкам
ООП. Как сторонники, так и противники
такой точки зрения имеют свои весомые
аргументы, но пока ни один из них не взял
верх.
°S/l4/2oo8
*Яе пеу,
ТТодождите. Разве у Руби не
одна и та же подпись? Зачем
нам свойство signature для
всех объектов?
OS/,g/2oos
S o fv e tf tfie п ё
одна и та
же п о д п и с ь во
веек записях-
‘^^Sfioyyptn
^ ru z z C e ri
°S /ie/2008
I
A
M anagecC to a e t n
S o tta nap.
^ Т^ггСаг Жибу
0S/2I/200S
OS/2g/2ooS
^ ^ ^z C e r Живу
■
Н аверное, одной подписи достаточно.
Зная, что подпись в блоге будет одна и та же у всех
объектов, легко сделать вывод, что нам в данном слу­
чае требуется свойство класса.
6ПОГ
далее ►
477
единожды сохранив
Свойства общего доступа
С во й ств а классов п о х о ж и н а м ето д ы кл ассов в том , ч то
к е д и н с т в е н н о й к о п и и с в о й с т в а и м ею т доступ все р е а л и за ­
ц и и об ъ екта. С т о ч к и з р е н и я д ан н ы х с в о й с т в а д аж е б о л ее
важ н ы , т а к как п о зв о л я ю т всем о б ъ ектам п о л ьзо ваться
о д н и м и тем ж е зн а ч е н и е м . И м е н н о такую ф у н к ц и о н ал ь­
н о с т ь и скала Руби, думая о с в о й ств е s i g n a t u r e , ведь в блоге
Y o u C u b e то л ь к о о д н а подпи сь.
Блог
Каждый о б ъ ект
сож дняеил свои
собст венны е
свойст ва.
И зм енени е свойст ва
В Ь д .signature^ сразу
и з м е н и т свойст ва
всех объект ов.
Блог
И зм енени е свойст ва
body эт о й записи не
окаж ет влияния на
С войст во sig n a tu re '
вид д р уги х записей.
сохранено в Классе.
Сохраненное один раз
свойство оасса доступно
затем всем реализациям
объекта.
■ . кг.-»'; »;____
I^Met up with some!
•fellow cube'iV?
И зм енени е свойст ва
d a te эт о й записи п о ­
в л и я е т т о ль к о на ее
собст венны й вид.
Н е с м о т р я н а т о ч т о сво й с тв о s i g n a t u r e с о х р а н е н о в классе
B lo g , доступ к нем у и м ею т все р е а л и за ц и и о б ъ ек та, к о т о р ы м
тр еб у ется п о д п и сь а в т о р а блога.
Как вы думаете, каким способом создаются свойства класса?
478
глава 10
»August 29th,”2008 !
специальны е объекты
Создание сВойстВ класса
За всеми этими разговорами о том, где сохраняется свойство
класса и какое значение оно имеет, процесс его создания
оказывается на удивление обыденным. Это всего лишь одна
__ _
строчка кода:
-
Д л я д о ст уп а к т а к о м у
. сво й ст ву нужно у к а за т ь
его название п о сле им ени
об ъ ект а и т очки.
Blog, p r o t o t y p e . S i g n a t u r e = " P u z z le r Ruby";
Сначала у к а зы в а е м с я
а ,„ м т н о
С войст ва к л а с ­
са не нуж даю т ся
. ° и н и ц и а лизации, но
о данном случае эт о
и м е е т см ы с л, т а к
как м ы уже зн а ем
а вт о р а блога.
чж е Ьогада-
p ro to ty p e -
По виду этого кода не понятна его самая интересная
особенность —в отличие от кода, создаюш;его свойства
объектов, его не нужно помеш;ать внутрь конструктора.
Ведь конструктор используется для создания объектов
и, следовательно, не умеет создавать свойства классов.
Свойства объекта
f u n c t i o n Blog(body,
date)
{
Свойство класса
t his. b o d y = body;
Blog.prototype.
sig n atu re =
С войст ва классов
созд а ю т ся вне к о н ­
ст рукт ора с п о ­
м о щ ь ю скр ы т о го
об ъ ект а p r o to ty p e .
" P u z z l e r Ruby";
Е динст венная
копия подписи
на все записи
блога.
/7
this.d
ate
= date;
T
Возьми В руку карандаш
Напишите код, отображающий значение свойства s i g n a t u r e в от­
дельном окне. Подсказка: мы предполагаем, что код располагается
внутри метода B lo g .
далее >
479
реш ение упражнения
, Возьми Вруку карандаш
V
'ешение
Вот ка к вы глядит код, отображ аю щ ий значение свойства
s i g n a t u r e в отдельном окне.
а Iв r t ( t h i s . s i g n a t u re );
Puzzler Ruby
r ~ w
Д ост уп к с в о й с т в а м кл а с с о в ,
как и к с в о й с т в а м объектов,
осущ ест вляет ся п р и п ом ощ и
)
к л ю ч е в о г о с л о в а t h is !
Часзро
^аД аБ аеМ ы е
Б о Ц |Э о С Ь 1
А зачем вообще в блоге YouCube
сохранять подпись в виде свойства?
Почему нельзя сделать ее частью
текста записи?
; Разумеется, подпись можно включить
в текст каждой записи, но это потребует
лишнего времени и усилий, при том что
в блог пишет всего один человек. Да
и зачем Руби подписывать вручную
каждый пост, если есть более простой
способ это сделать. Кроме того, это
исключает вероятность опечаток.
Есть и другая возможность —
использовать для подписи строковый
литерал в процессе HTMLформатирования текста записи.
Такой подход хорошо работает, но
в результате важный фрагмент данных —
подпись — оказывается зарыт где-то
внутри кода форматирования. И при
необходимости его не так-то просто найти
и отредактировать. Поместив подпись
в свойство класса, вы делаете ее легко
доступной и, следовательно, легко
обнаруживаемой и редактируемой.
3 * Как бы изменилось создание
записи, если бы подпись была
свойством объекта?
480
глава 10
Q ; Каждая реализация объекта
имеет свой собственный набор свойств,
инициализированный в конструкторе.
Если бы подпись была свойством объекта,
конструктору B l o g () пришлось бы
задавать ее каждый раз заново. Это
несложная задача, так как конструктор
просто присваивает свойству строку
с подписью. Но при этом создается
множество копий, и вы получаете
возможность менять содержимое каждой
подписи, независимо от остальных.
То есть если я захочу
отредактировать блог YouCube таким
образом, чтобы туда писали разные
люди, стоит ли сделать подпись
свойством объекта?
! Именно это и следует сделать, по­
тому что при таком сценарии свойство
s i g n a t u r e должно будет иметь
разные значения для разных объектов.
Лучше всего решить такую задачу, до­
бавив к конструктору B l o g {) аргумент,
позволяющий передавать в конструктор
строку с подписью. Эту строку вы будете
использовать для инициализации свой­
ства s i g n a t u r e каждого из объектов.
Другими словами, вы будете работать со
свойством s i g n a t u r e точно так же, как
и с другими свойствами объекта B lo g .
Свойства классов напоминают
глобальные переменные. Чем они
различаются?
Q ; Свойства классов действительно
напоминают глобальные переменные,
ведь доступ к ним возможен из любой
части сценария. Они даже создаются
похожим образом — на уровне главного
сценария, вне другого кода. Различие
же заключается в том, что эти свойства
связаны с классами, а следовательно,
и с реализациями объектов. Это означает,
что доступ к такому свойству всегда будет
осуществляться относительно объекта.
Подождите. Доступ к свойствам
классов должен быть выполнен через
объекты?
Q ; Да, несмотря на то что свойства
класса созданы при помощи объекта
p r o t o t y p e , доступ к ним
осуществляется через конкретные
реализации. Для этого используется
ключевое слово t h i s , после которого
стоит точка и имя объекта. Вся разница
только в том, где именно хранится то
или иное свойство — в классе или
в отдельной реализации.
специальны е объекты
Подписан и доставлен
М ет од toH TM LQ
ф о р м а т и р у ет ,
подпись ка к ч аст ь
записи блога.
С оздав св о й с тв о s i g n a t u r e у р о в н я кл асса и п р и с в о и в ему
з н а ч е н и е , Руби х о ч е т п о с м о т р е ть , как все р а б о т а ет . В згля­
нув н а код, ф о р м ати р у ю щ и й зап и сь б ло га для о т о б р а ж ен и я
в б р ау зер е, мы обн ар у ж и м код п о д п и си в м ето д е toHTML ().
Blog.prototype.toHTML
= function(highlight)
{
11 используем для выделения серый фон
var blogHTML =
ЫодНТМЬ
hrghiight , "<Р style^'bao.groun.-color:
" —
■—
this.date.getFuliyearO
^
. "</strongXbr />
=
"<p>"
. .. .................................... ^
. thrs.bo у
^
"</emX/p>";
return blogHTML;
Подпись Руби
поя вля ет ся
в каждой з а ­
писи.
Теперь сразу видно,
кто автор всех запи­
сей в блоге.
9 /1 д т
Ссылка на свойстлво
sig n a tu re уровня класса
ничем не о т л и ч а е т с я
о т ссы лки на обычное
свойст во объект а.
S^9/20ee
h'P uziier Ruby
«liscusstei
prospect o f a 7x7x7
Ш Ш Ш
8/ 19/2008
Руби в о с п о л ь зо в ал ась п р и е м о м и з о б ъ е к т н о -о р и е н т и р о в а н н о го
п р о гр а м м и р о в а н и я , ч то б ы р а с ш и р и т ь я зы к Jav aS crip t, доба­
ви в св о й с тв о s i g n a t u r e к классу B log . Э ти м о н а сделала блог
Y o u C u b e ещ е б о л е е л и ч н о й т е р р и т о р и е й .
далее >
481
свойство объекта против свойства иласса
Беседа у камина
Свойства объектов и классов говорят об обладании данными и се­
кретных клубах.
Свойство объекта:
Т ак э т о о те б е я все в р е м я слышу. Д о л ж ен
сказать, ч то я н е п о н и м аю , зач ем т ы нуж ен.
Я о т л и ч н о в ы п о л н я ю свою работу, о б ес п е ­
ч и в а я ун и кал ьн о сть о б ъ е к т о в и о тсл еж и в ая
зн а ч е н и я и х свой ств.
Свойство класса;
К о н е ч н о , ты эт о д елаеш ь, и это д о ст о й н о
во сх и щ ен и я. Н о ты задум ы вался, ч то и н огд а
о б ъ ектам н е требую тся и х л и ч н ы е данны е?
С л о ж н о п о в е р и т ь в тако е. П р о д о л ж ай ...
Ну, б ы ваю т ситуац и и , когд а ф р а гм е н т ы
д ан н ы х яв л я ю т ся об щ и м и для всех о б ъ ектов.
К ак с е к р е т н ы й о п о зн а в а те л ь н ы й зн а к в се­
к р е т н о м клубе. Его зн аю т все ч л е н ы клуба.
И есл и кто-то и з н и х и зо б р е т е т с во й о п о зн а­
в а т ел ь н ы й зн ак , вся с и стем а рухнет. П отом у
ч т о кто-то за х о ч ет ему п о сл ед овать, и вско р е
н и к т о н е см о ж ет о п о зн а ть друг друга, так
как зн ак о в с т а н е т слиш ком м ного.
Т о е с ть ты утверж даеш ь, ч то я н е подхож у
для х р а н е н и я и н ф о р м а ц и и о с е к р е т н ы х о п о ­
зн а в а т е л ь н ы х знаках?
И м е н н о так. Н е о б и ж ай ся, н о все ч л ен ы
клуба д о л ж н ы зн ат ь т о л ь к о од и н знак.
А могу л и я х р а н и т ь с е к р е т н ы й пароль?
В озм ож н о. Если п ар о л ь у каж дого свой , п е р ­
со н ал ьн ы й , т о да, т ы п р е к р а с н о п од ходи ш ь
д ля его х р ан ен и я .
П р ев о сх о д н о ! Т о гд а я ор ган и зу ю с е к р е т н ы й
клуб, и у каж дого и з пас будет с в о й пар о л ь.
Н о ведь т ы н е зн аеш ь се к р е т н о го о п о зн а в а ­
т е л ь н о го знака!
П р ек р асн о ! А ч т о это вообш;е такое? Н ет,
д ей с тв и те л ьн о . Я с е р ь е зн о спраш иваю ...
482
глава 10
специальны е объекты
Hem дублирующемуся коду!
Руби не знает отдыха, она решила продолжить ра­
боту над эффективностью кода YouCube. Она заме­
тила повторения в форматирующем коде и счита­
ет, что от них тоже неплохо было бы избавиться,
воспользовавшись преимуществами объектноориентированного программирования.
< html>
< head>
'<Йа.>їо.сиь.
- Т Ь , BIO,
и.
cube
« c t l p t iyp..-t=Kt/3avasciipt->
// К о н с т р у к т о р о б ъ е к т а B i o g
f u n c t i o n B l o g (body, date) {
l;;i” ! r o r y ^ r b r y " r " N o t h . n g
g o i n g on today.
t h i s . d a t e = date
}
возвращаем строковое представление
,g.p r o t o t y p e .t o & t ^ A . ^ - f-u n c t . ,^^.a a
//
-etL?n---“4-"
■d a t e . g e tM o n ;^
( m s ■date ■getFullYear_0
Э т о т код, ф о р ­
м ат ирую щ ий
наш и данные, п о ­
вт о р я ет ся.
записи блога
//
/ / ■ ^ п о л ь з у е м для выделения серый фон
var blogHTML - " ;
"<p
style='b a c k g r o u n d - c o l o r :
"<p>";
#EEEEEE'>"
blogHTML += highlight
this. d a t e . g e t D a t e 0
■ < iil
+ LUio.iJ-g
"< 7 ^
r e t u r n b logHTML;
^ ГТ ТТТ/Г ТЧ finore с т р о к а п о и с к а
// п р о веряем,
= f u n c t i o n (text) (
Blog.prototype.containsText
_
_
r e t u r n (this.body. i n d e x O f (text) .
);
// З а д а е м п о д п и с ь
B l o g .p r o t o t y p e .si g n a t u r e
"by P u z z l e r R u b y ’’
Ш ТУРМ
Каким образом избавиться от
дубликата форматирующего
кода в блоге YouCube?
далее *■
483
место форматирования
М ето д форматирования данных
Руби с ч и та е т, ч т о д ля и зб а в л е н и я о т дубликатов ф о р м ати р у ю щ его ко д а нуж но
д о б а в и т ь к об ъ екту B lo g ещ е о д и н м етод. В едь ч т о б ы и с п о л ь зо в ат ь о д и н и т о т
ж е ф р а гм е н т ко д а м н о го к р ат н о , его нуж но п р е в р а т и т ь в м ето д и л и ф ункцию .
А и м е н н о о б ъ е к т B lo g о т в е ч а е т за ф о р м а т и р о в а н и е д ан н ы х как ч асть ф о р м а т и ­
р о в а н и я зап и си блога. И л и нуж но д ей с тв о в ат ь по-другому?
Вернемся к объекту prototype
Ч т о м о ж ет б ы ть лучш е, ч ем в зя т ь и м ею щ и й ся о б ъ е к т и усо­
в е р ш е н с тв о в а т ь его? В едь сущ ествует в о зм о ж н о сть р ед ак­
т и р о в а т ь ст ан д а р т н ы е о б ъ е к т ы , р а с ш и р я я , тем сам ы м ,
я зы к JavaS crip t. Э то осу щ ествл яется п р и п о м о щ и о б ъ ек т а
p r o t o t y p e . М ы уже и сп о л ьзо в ал и его д ля р а с ш и р е н и я класса
B lo g путем д о б а в л е н и я к этом у классу м ето д о в и свой ств. Н и ­
ч т о н е м еш ает н ам п р о д е л а ть ан алоги ч н ую проц едуру с други­
ми в с т р о ен н ы м и классам и JavaS crip t.
p r o to ty fje ^ ;;" ^
Каждый о ё ь е к т облада­
е т о б ъ е к т о м p r o to ty p e ,
п о зво л я ю щ и м дооавлйт(?
к нем у сво й ст ва и м е т о ­
ды уровня класса.
484
глава 10
Л ю бой из об ъ ект о в
J a v a S crip t.
специальны е объекты
Расширение стандартны х объектов
Расш и рен и е стан дартны х объектов осуш,ествляется п р и пом ощ и объ­
екта p r o t o t y p e . Д ля этого д остаточн о добавить к прототипу нуж ные
свойства и методы . В случае в стр о ен н ы х объектов JavaScript резуль­
татом будет доступ к добавленны м свойствам и методам всех новы х
экзем пляров объекта.
Объект prototype позволя­
ет расширять встроенные
о^екты JavaScript.
Строка
Строка
/М етод, д обавл ен н ы й
к прототипу встрое н н о­
го объекта, окажется на
уровне класса.
Э тот метод см огут и с­
п о л ь зо в ать все н овы е
объекты, созд анны е на
S t r i n g . p r o t o t y p e s c am ble = f u n c t i o n
осн ове этого класса.
/ / Возвращение зашифрованной строки
J.
Строка
М е т о Э создает ся как
член п р о т о т и п а о д ь е к т а S tr in g -
Чтобы в о с п о л ь зо в а тьс я н о в ы м м ето д о м о б ъ е к т а S t r i n g , д о ста­
т о ч н о вы зв ать его д ля это го об ъекта.
a l e r t ( t h i s . s i g n a t u r e . scrcimble () );
■ luzPrb uzyRe
Возьми в руку карандаш
Напишите код метода s h o r t F o r m a t () , который является
расширением стандартного объекта D a te и форматирует
дату в виде ММ/ДД/ГГГГ.
далее *
485
реш ение упражнения
Возьми в руку карандаш
’ешение
Вот как выглядит код метода shortFormat ( ) , который
является расширением стандартного объекта Date и форма­
тирует дату в виде ММ/ДД/ГГГГ.
М ет о д добавлен y p a te .p r o to tu p e .s h o r tF o r m a t = functiorJ) {
к прот от ипу ^
.......................
о б ъ ект а P a te.
.................................................... ..............................................................................
r e tu r n
i) +
+ this.getPateQ ^ + "/" +- this.getFu!lYear();
ь
Улучшенный блог YouCube
Р е д ак т и р о в а н и е о б ъ е к т а Date у в е л и ч и в а е т э ф ф е к т и в н о с т ь
сц е н а р и я Y o u C u b e. У п р о щ ается его р е д а к ти р о в а н и е , ведь ф о р ­
м а ти р о в а н и е д ан н ы х т е п е р ь в ы п о л н я е т с я в од н ом м есте, а его
д ей с тв и е р а с п р о с т р а н я е т с я н а все за п и с и блога. Р езультаты
та к о го р е д а к т и р о в а н и я д ал ек о н е всегда за м е тн ы визуальн о, но
о н и улучш аю т код с т о ч к и з р е н и я его д о л го с р о ч н о го и сп о л ь зо ­
ван и я.
S a « n y o „ < s id e o f a U > o a l» y s « .« S - s « n .p e d c » y in g c u b c p » z z te s .
Power to ft© puslersl
by Pmder Ruby
9 /1 /M 0 8
„ ,n ^ 'J i c i c u h e
S t a r t i n g
W e ^ e a d and oidered the scary 7x7x7 cube. :.tarui g
a m e n ta l e x e rc ise
regiiM sn to prepare.
by
Puzzler Ruby
c u b « s » d i , c » s s m e p . » t « c . o , a 7 x 7 x 7 cu b e. M ixed
fe e lin g s .
by
Puuler Ruby
8 /21Ш Ю 8
Found а 7x7x7
cube fo r sate on lin e. Y ik e s ! T h a t one could be abeasi.
b y P u z z le r
Ф орм ат ирование
д а т т е п е р ь вы ­
полняет ся п о л ь ­
зоват ельским
м ет о д о м объ ект а
P a te .
486
глава 10
e c n c w c u b e b u .o ,c o u n e ,n o w
by Puzzler Ruby
I 'm
bo№d anti shopping for a new one.
специальны е объекты
Методы классов
Методы класса имеют
доступ только к свойствам
этого же класса.
М етод shortFormat {) о б ъ е к т а Date я в л я е т с я принадлежащим
классу методом объекта. И м е н н о это д ае т ему в о зм о ж н о сть ф о р ­
м а ти р о в а ть с о х р а н е н н ы е в о тд е л ь н ы х о б ъ е к тах даты . Н о м ож н о
со зд ать и метод класса, к о т о р ы й не будет и м е т ь доступа к с во й ­
ствам о б ъ екто в . Д о сту п н ы м и для н и х окаж утся т о л ь к о св о й ства
классов, т а к и е как, н а п р и м е р , св о й с тв о signature класса Blog.
Блог
Блог
fviewc>3b! классов
ы м е н зт д о с т у п
К c6oiXcwSo.M
М ет оды классов не иллр.т1лл
д о ст уп а к сво й с т ва м и м е ­
т о д а м объект ов.
Реализация
Д л я со зд ан и я м ето д а класса о б ъ е к т prototype н е нуж ен —д о ­
с т ат о ч н о н а зн а ч и т ь м ето д классу, указав и м ен а класса и о б ъ ек ­
та, как п о к азан о ни ж е.
Biog.showSignature =
functionO
Д л я д о ст уп а к сво й ст ву
класса т а к о м у м е т о д у
понадобит ся свойст во
о б ъ ект а p r o to ty p e .
{
alertC'This blog created by " + Blog.prototype.signature +
};
\
Т ак к ак м ето д ы классов н е и м ею т св я зи с о тд ел ьн ы м и об ъ ектам и ,
для и х в ы зо в а д о ст а т о ч н о со сл аться н а и м я класса. Т а к о й м етод
м о ж е т б ы ть в ы зв ан и о б ъ екто м , но д ля эт о го п о тр еб у ется указать
и м я класса.
Так как sig n a tu re —
э т о свойст во класса
оно дост уп но для
наш его м ет ода.
B l o g .showSignature
Д л я вызова м ет о д а
класса нужно у к а за т ь
и м я эт о го класса.
Ш ТУРМ
Существует ли код блога YouCube, который
имеет смысл сделать методом класса Blog?
далее >
487
и снова о классе Blog
А нельзя ли использовать
метод класса для сорти­
ровки записей блога?
Пересмотр процедуры сортировки
Я
И д ея п е р е с м о т р а с о р т и р о в к и н е л и ш ен а и н те р е с а , потом у ч то
ф у н кц и я, осущ ествляю ш ;ая проц едуру с р а в н е н и я , и г р а е т нем а­
лую р о л ь, связанную с о б ъ екто м Blog. В н а сто я щ ее в р е м я о н а
п р е д с та в л я е т с о б о й л и т е р а л вн у тр и ф у н кц и и showBlog ().
C O 'P '^S б»*'«
function ShowBlog(numEntries)
l3io3-
-—
{
// Сортируем записи блога в обратном хронологическом порядке
Ыод. sort (function{blogl, Ыод2) { return Ыод2.date - blogl.date; });
}
В п олн е возмож но п е р е м е с т и т ь
код сравнения 8 м е т о д класса.
О д н и м и з ф у н д ам ен тал ьн ы х п р и н ц и п о в о б ъ е к т н о -о р и е н т и р о в а н н о го
п р о г р а м м и р о в а н и я я в л я е т с я с в я зь ф у н к ц и о н а л ьн о ст и о б ъ ек та с сам им
о б ъ екто м . Д ругим и словам и , н е следует о с т ав л я т ь н а откуп внеш нем у
коду д ей с тв и я , к о т о р ы е о б ъ е к т м о ж ет в ы п о л н и ть сам о сто я тел ь н о ,
в д ан н о м случае с о р т и р о в к а за п и с ей в п о л н е м о ж ет вм есто ф у н кц и и
showBlog () в ы п о л н я т ь с я с р ед ствам и сам ого об ъ екта. Н о н ел ьзя л и
п о м е с т и т ь о сущ ествляю щ ий эту проц едуру м етод в класс Blog? Д л я о т­
в е т а н а д ан н ы й в о п р о с нуж но п о н я т ь , тр еб у ется л и этом у методу доступ
к д ан н ы м и л и м етод ам о тд ел ьн ы х о б ъ ектов.
488
глава 10
специальные объекты
Функция сравнения
Е д и н ств ен н ы м сп о со б о м о т в е т и т ь н а зад ан н ы й в к о н ц е преды дущ его р азд ел а
во п р о с я в л я е т с я а н а л и з ф у н к ц и и с р а в н е н и я . В от соответству ю щ и й л и тер ал :
_Дбй о б ъ ект а Ыод п е р е ' д а ю т ся ф ун кц и и в к а ч е ­
с т ве а р гу м ен т о в.
function(blogl, blog2)
{
return blog2.date - blogl.date;
П роцедура сравнения
сводит ся к вы чит анию
а р гу м ен т о в.
■ Ч _________
}
Х о тя ф у н кц и я и и м е е т д ел о н е п о с р е д с тв е н н о с о б ъ ек там и , о н и
п ер ед а ю т с я ей в к ач еств е аргум ентов. Э то совсем н е т о ж е
сам ое, ч т о п о п ы тк а д оступа к св о й ствам и л и м етод ам о б ъ е к т а
п о ср ед ств о м кл ю ч ев о го сл о в а t h i s , н е в о зм о ж н ая и з м етод а
класса. С о о т в е тс т в е н н о , м ы видим , ч т о ф у н кц и и с р а в н е н и я н е
нуж ен доступ к о б ъ ектам , и э т о д ел а е т е е п р е к р а сн ы м кан ди да­
том н а п р е в р а щ е н и е в м ето д класса.
О б ъ ект .
Б о л е е т о го , э т о й ф у н кц и и н е тр еб у ю тся д аж е с в о й ст в а класса,
х о т я о н а и и м е е т к н и м доступ.
М ет од класса п р и необ­
хо
д и м о ст и и м е е т д о XOOUMU!.-vvw
с т у п к сво й ст ву класса.
f
/
^ —“ —— —
п уункции
н к ц и и со р т и р о вки
Ф
а&-Юлрс6.у&шг.я д о с т у п
к данны м о б ъ ект а или
класса.
function (blogl, Ыод2) {
return blog2.date - blogl.date;
К ласс,
Если бы ф ун кц и и с о р т и ­
ровки т ребовался д о ст у п
к о б ъ е к т а м , создание
м ет о д а класса ст а л о бы
невозмож ным.
Возьми в руку карандаш
Перепишите код функции сравнения, превратив ее в метод
класса B lo g и присвоив ей имя b l o g S o r t e r {).
далее >
489
мет од класса? вот он!
Возьми в руку карандаш
Решение
Вот как выглядит функция сравнения записей блога YouCube
после превращения ее в метод класса Blog.
J M o g M q g S g rte r ,-,
£.
...r ^ t'^ fn bJogZ.date, - blogi-.date;
};
^ о ^ р о в к а т е п е р ь вы п о лн яет ся
м е т о д о м класса Blog, ко т о р ы й
на зы вает ся blogSorterQ .
ВызоВ метода класса
П р еи м у щ ества п р е о б р а зо в а н и я ф у н кц и и с о р т и р о в к и зап и сей
б л о га в м етод Blog ст ан о в я тс я б о л ее я сн ы м и , есл и п о с м о т р е ть
н а код в ы зо в а эт о го м етода.
function showBlog(numEntries) {
// Сортировка записей блога
Ы о д . sort (Blog.blogSorter)
Д ет али сорт иров­
ки за писей т е п е р ь
■от даны на о т к ц п
м е т о д у blogSorterQ
класса Blog.
}
П р е л е с т ь это го ко д а о т к р ы в а е тс я н е сразу. Д ел о в том , ч т о т е п е р ь
с о р т и р о в к а за п и с е й б л о га в ы п о л н я е т с я н е в н еш н ей ф у н к ц и ей
showBlog О , а внутри класса Blog, к ко то р о м у эт а п р о ц ед у р а л о ги ­
ч еск и п р и н ад л еж и т.
П р и м е ч а т е л е н т о т ф акт, ч т о с о р т и р о в к а по-п реж нем у и н и ц и и р у е т ­
ся в н е класса Blog ф у н к ц и ей showBlog ( ) , и эт о и м е ет см ы сл, так
как д ан н а я п р о ц ед у р а в л и я е т н а все за п и с и блога. Н о о с о б ен н о с т и
с о р т и р о в к и о тд ел ьн ы х за п и с ей бло га тако в ы , ч т о эту задачу м ож н о
р е ш и т ь ср ед ств ам и класса Blog. Х о р о ш и й О О П -д и зай н зачастую
акк у р атн о с о ч е т а е т о б ъ е к т ы и окр у ж аю щ и й и х код.
Блог
showBlogO
490
глава 10
специальные объекты
В
Картинка с т о и т тысячи слоВ
Руби п р о д о л ж а е т в о с т о р га т ь с я у с о в е р ш е н ств о в ан и ям и
св о его бло га Y o u C u b e, н о п о д о зр е в а е т, ч то ч и т ат е л и вряд
л и см огут р а зд ел и ть ее энтузиазм . Ведь п о к а ч то все в н е ­
се н н ы е и зм е н ен и я н и как н е п о в л и я л и н а в н е ш н и й вид
блога. П о это м у Руби р еш и л а, ч то п р и ш л о в р е м я д о б ав и ть
ч то-то б о л ее за м е тн о е н ев о о р у ж ен н ы м глазом!
Руби х о ч ет сдел ать так, ч то б ы каж дая о тд ел ьн ая зап и сь
п о д д ер ж и в ал а в о зм о ж н о сть вставк и и зо б р а ж е н и й , к о т о р ы е
будут д ем о н с т р и р о в ат ь с я вм есте с те к с т о м и д ато й . Т ак
как к а р т и н к и тр еб у ется в ставл я ть д алеко н е всегда, д ан н ая
ф у н кц и я д о л ж н а б ы ть н е о б я за тел ь н о й . Э то т ак ж е п о зв о л и т
с о х р а н и т ь п е р в о н ач а л ь н ы й вид уже имею ш ,ихся зап и сей .
Ш ТУРМ
Каким образом включить поддержку
изображений для объекта B l o g ?
далее
491
карт инки — это всё
Bcmaßka изобра)кений
Ч т о б ы д о б а в и т ь в о зм о ж н о с ть встав к и и зо б р а ж е н и й в за п и с и
б ло га Y o u C u b e, н ам надо п о п ять, каки м о б р азо м в н е д р и т ь н о ­
вую структуру в о б ъ е к т Blog, н е и зм е н и в с п о со б а его ф у н кц и о ­
н и р о в а н и я . П о этом у поводу в о зн и к а е т д ва воп роса:
Каким образом лучше всего
сохранить изображение
в объекте Blog?
Как добавить к блогу
необязательную воз­
можность вставки изо­
бражений?
Н е за в и с и м о о т т о го , каким о б р азо м будет с о х р а н е н о и зо б р а ж е н и е ,
о н о о т о б р а ж а е т с я н а с т р а н и ц е п р и п о м о щ и т е га < 1 тд > .
Д о с т а т о ч н о у к а з а т ь им я
■ф а й ла с изображ ением.
'
<img src="cube777.png” />
Э то т ко д п о к а зы в а ет нам , ч т о с т о ч к и зр е н и я блога и зо б р а ж е н и е —
эт о т о л ь к о стр о ка. Р азум еется, о н а ссы л ается н а ф а й л с к а р т и н к о й ,
х р а н я щ и й с я где-то н а с е р в е р е , н о д ля о б ъ е к т а Blog о н а все р ав н о
о с т ае т с я с тр о к о й .
io o tli
UiOlOC
o oi ö lo
toiom
П о этом у и зо б р а ж е н и я к об ъекту Blog м ож н о д о б ав и т ь как
св о й ство , х р а н я щ е е строку, а н а л о ги ч н о е свойству body.
cube777.png
Г
Изображ ение
кубика р а зм е р о м
^Р'^^^итлся
о ф а й ле с и м е н е м
сиЬ е7 7 7 .р п д.
492
глава 10
Для объекта Blog
изображение — это
не более чем строка.
С войст ва body
и im age кра н ят ся в о б ъ ект е
S lo g , как ст р о ки
Блог
специальные объекты
Необязательное изобра}кение
И та к , в о б ъ е к т е B lo g и зо б р а ж е н и е с о х р а н я е т с я в ви д е с т р о к о в о го свой ­
с тв а im a g e , н о о с т ае т с я в о п р о с , каким о б р азо м сдел ать эту проц едуру
н е о б я за те л ь н о й . Ч т о б ы о т в е т и т ь н а н его , в е р н е м ся к кон струк тору, как
к месту со зд ан и я и и н и ц и а л и за ц и и о б ъ екто в. И м е н н о туда следует п о м е­
ст и т ь о с о б ы й код, указы ваю щ и й н а н е о б я за те л ь н о с т ь н о в о го свой ства.
f u n c t i o n Blog(body,
date)
(
А что случится, если
не передавать конструктору
аргумент? Может быть, свойство
просто получит значение null?
// н а з н а ч е н и е с в о й с т в
t h i s . b o d y = body;
t h i s . d a t e = date;
}
О т с у т с т в у ю щ и е аргументы р а в н ы нулю.
Н е п е р е д а н н ы й в ф ункц ию м ето д и л и н е п ер е д а н н ы й к о н ­
структору аргум ент для л ю б о го кода, к о т о р ы й п о п ы тае т с я
его и сп о л ьзо в ать, будет и м е т ь зн а ч е н и е n u l l . В случае с к о н ­
стр у кто р о м эт о о зн а ч а е т п р и р а в н и в а н и е к n u l l св я зан н о го
с аргум ентом сво й ств а, ч т о в о в се н е плохо. Г л авн о е п р и этом
н е заб ы ть п о м е с т и т ь н е о б я за те л ь н ы й аргум ен т в сам ы й к о н ец
спи ска, ч то б ы н е в о зн и к а л о путан и ц ы . Э та те х н и к а р а б о т а е т
д ля лю б ы х ф у н кц и й и м ето д о в, н о о с о б ен н о о н а п о л е зн а для
ар гу м ен та im a g e в к о н с тр у к то р е B lo g () .
Возьми В руку карандаш
Перепишите конструктор B lo g ()
таким образом, чтобы он начал
поддерживать необязательное
свойство image.
далее >
493
реш ение упражнения
в руку карандаш,
'ешение
Вот ка к вы глядит ко н с т р у кто р B l o g ( ) , поддерж иваю щ ий
необязательное свойство image.
.
і .........
.
.
.
,, . ;
с в о й с т в о image,,
и е м у при сво ен а р ­
г у м е н т im age.
.
,
.
,
,
J
M , - d . t e =.
.
А ргум ент Ы ааг
добавлен в
J :Z 7 T Z Z Z ?
конец списка
'^^Р^даваем ы х
х ™ < :« г а к т о „ „
............................................
, th is.im age = image;
}
_
Ч асто
^аД аБаеМ ы е
B o iij^ o c b i
Обязательно ли ставить аргумент
im a g e на последнее место в списке
Добавление галереи
Н о в ы й б л и стат ел ь н ы й к о н стр у к то р B l o g ( ) , п о д д ер ж и ваю щ и й
вставку и зо б р а ж е н и й , б есп о л езен , есл и его н е п р и м ен я ть . В от
как в ы гл яд ят этап ы со зд ан и я за п и с и с кар ти н к о й :
передаваемых конструктору B l o g ()
аргументов?
Н а с е р в е р е п о м ес ти те
г р а ф и ч е с к и й ф а й л в ту
ж е папку, ч т о и стр ан и ц у
Y ouC ube.
Q j Да, ведь изображение относится
к необязательному фрагменту записи. Весь
вопрос тут в способе передачи аргументов
функциям. Если функция имеет два аргумен­
та, можно передать ей оба, только первый
или ни один из них. Но невозможно передать
только второй аргумент.
Именно поэтому необязательные аргументы
ставятся в самый конец списка. Также имеет
смысл более важные аргументы ставить
в самое начало. Так как а р гу м е н т іт а д е
©
С о зд ай те новую зап и сь
к ак о б ъ е к т B l o g в коде
с ц е н а р и я Y ouC ube.
является для конструктора B l o g () необя­
зательным, мы ставим его в конец списка,
где им легко пренебречь,
Блог
V\W ow, it tôoi?me;al
09/19/2008
couple of weeks b u t ^
—
—J.
‘Л О Д
ber 191И5'20Щ
494
глава 10
специальные объекты
В р езу л ьтате м ы получим код, к о т о р ы й со зд ает новую запи сь,
п е р ед а в ая с т р о к о в о е с в о й ств о i m a g e в п о с л е д н и й аргум ент
к о н с тр у к то р а B l o g ( ) :
new Blog("Wow, it took me a couple of weeks but the new cube is finally solved!'
new Date("09/19/2008"), "cube177.png")
г.
Изображ ение п е р е д а е т ­
ся в последний а р г у м е н т
к о н с т р у к т о р а BlogQ-
Отобра)кение картинок
Т еп ер ь , когда за п и с и бло га сн аб ж ен ы к а р т и н к а м и , о стал ось
од н о , п о сл ед н ее у со в ер ш ен ств о в ан и е. В есь э т о т р а зг о в о р о к о н ­
стр у кто р ах и н е о б я за те л ь н ы х ар гу м ен тах н е и м е ет осо б о го
зн а ч е н и я , если отображ аю ш ;ий зап и сь код н е у ч и т ы в ает н о в о е
св о й ств о i m a g e .
Э то т код р а с п о л о ж е н в м ето д е t o H T M L ( ) . И м е н н о д ан н ы й
м ето д о т в е ч а е т за H T M L -ф о р м а т и р о в а н и е за п и с ей блога, но
т е п е р ь о н д о лж ен п р и н и м а т ь во в н и м ан и е св о й ств о i m a g e , как
и м ею щ ее зн а ч е н и е , т а к и б ез него. В д ан н ы й м о м е н т п о я в и л о сь
два с п о со б а о т о б р а ж е н и я зап и сей , и и х в ы б о р за в и с и т о т н а­
личия картинки.
Г
Т еперь от ображ ение
за писей блога б удет
о с у щ ест в ля т ь с я
в с о о т в е т с т в и и со
следую щ ей логикой.
If (картинка есть)
Отобразить запись с картинкой
Else
Отобразить запись без картинки
Возьми в руку карандаш
в м е то д е
t o H T M L () о б ъ е к т а B l o g о т с у т с т в у е т ф р а гм е н т
кода, о т в е ч а ю щ и й за о т о б р а ж е н и е к а р т и н о к . В п и ш и т е е го
и с н а б д и те п р и м е ч а н и я м и .
if (
) {
blogHTML += "<strong>" + this.date.shortFormat() +
"</strong><br / X t a b l e X t r X t d X i m g src='" + this, image +
" '/ x / t d x t d
stYle='vertical-align:top'>" + this.body + " < / t d X / t r X / t a b l e X e m > "
this .signature + "</emX/p>";
}
else {
blogHTML += "<strong>" + this.date.shortFormat() + "</strongXbr />" + this.body +
"<br /><em>" + this.signature + "</emx/p>";
}
далее >
495
реш ение упражнения
Возьми в руку карандаш
Решение
if (
tkis.im age
' ................
^
Вот как выглядит метод toHTML () объекта Blog после
вставки в него фрагмента кода, отвечающего за отображение
картинок.
~~
I <
— — -----— - Если свойстВц image присвоена
ссы лка на изображ ение, р е з у л ь -
ы„,нт«ь *=
'
"</strongxbr / X t a b l e X t r X t d X i m g src="' + this.image +
" ' / x / t d x t d style='vertical-align:top'>" + this.body + " < / t d X / t r X / t a b l e X e m > " +
this .signature + "</emX/p>";
else {
^
./^
Ч-
—
В п р о т и в н о м случае
за п и с ь по ка зы ва ет ся
° обычном виде, без
карт инок.
blogHTML += "<strong>" + this.date.shortFormat() + "</strongXbr />" + this.body +
"<br /><em>" + this.signature + "</emx/p>";
Блог на основе объектов
Руби в экстазе. Б л а го д а р я о б ъ ек там е е б лог р а с т е т и со­
вер ш ен ств у ется, а т е п е р ь к нем у ещ е д о б ав л ен а ф ун кц и я
п о к а за к а р т и н о к , к о т о р а я н е с о м н е н н о д о л ж н а п о н р а в и т ь ­
ся п о сети тел я м .
0 f! 0
¥оиСвЬа_- The Sloe fw C ute 1»игг1е « _
YouCube The Blog for Cube Puariers
Search the Biog | |
9ЛЧЙШ®
З а п и с ь с и зо ­
бражением.
Wo«, it шок a® a coaple of w «ks tat the new cubc ^ *
solved!
li
byPuzzkrRuby
G o S n c w 7x7x7 cube. Could be my last blog post for a while...
byPuukrRuby
At»nde<i a raUy outside of a local »>' store Sia stopped carrying cubc puzzles.
Power to aiepffittoi
by Puzder R u b y
496
глава 10
....................
^
специальны е объект ы
I
Согните страницу
по вертикали, ч т о б ы
совместить два мозга
и р е ш и т ь задачу.
Вкладка
Что дают объекты большинству
сценариев
M issing
Image
deliver()
і
/Л - -
1
:
Объекты добавляют к сценариям так
много потрясающих вещей, что сложно
выбрать что-то одно. Некоторые объекты
вьщеляются из общей массы, что
осложняет задачу. Но ответ очевиден!
jJ
0 хо 1л а н а оШ иёки
Когда сценарий не работает
^
(
у
(
V
Никогда не знаешь заранее... Иногда
все работает, и все счастливы... А потом — бах! И все плывет. Главное — чтобы рядом оказался такой парень, кок
я, который все починит.
Даже самые лучшие планы в иауаЗспр1 иногда не реализу­
ются. и когда это происходит, главное — не паниковать. Лучшие програм­
мисты не те, которые никогда не делали ошибок, — на самом деле это про­
сто лгуны. Лучшие — это те, кто может успешно обнаружить и устранить
ошибку Отладчики высокой квалификации нарабатывают хорошую манеру
написания кода, минимизирующую вероятность появления неприятных оши­
бок. Лучше предотвратить, чем потом бороться. Тем не менее ошибки
то и дело встречаются, и вам нужен арсенал средств борьбы с ними...
дефект...
какая гадость!
Устранение дефектов
Ш о ки р у ю щ и й ф а к т и з ж и зн и сл ад о стей — с т ан д ар т ы н а п р о и зв о д с т в о ш о­
к о л ад н ы х б ат о н ч и к о в н е о т н о с я т к б раку о ко л о 60 р а зн о о б р а зн ы х д е ф е к ­
т о в в п л и тк е. А во т б о яться б р ак а в ко д е Jav aS crip t п р и ч и н н ет. Э то т код
к о н тр о л и р у ет с я б о лее тщ а те л ьн о , ч ем о б о р у д о ван и е для п р о и зв о д ст в а
ш околада. С ущ ествует д аж е с п е ц и а л ь н а я р а б о ч а я группа д ля у с т р ан ен и я
д еф е к т о в JavaS cript.
BUG SCENE INVESTIGATORS
К т а к о й группе н ед ав н о п р и с о е д и н и л с я О уэн в ка ч е ств е т е с т и ­
р о в щ и к а JavaS crip t. Ему н е т е р п и т с я п о к а за ть с во и р а б о ч и е
н ав ы к и , у стр ан и в как м о ж н о б ольш е о ш ибок.
О уэн , т е с т и р о в щ и к
J a v a S c n p t и бывший
лю бит .ель ш околада.
^олньШ д е ф ек т о в
Н а пути к успеху Оуэну
п р е д с то и т р е ш и ть н е ­
скол ьк о задач. Ему п р ед ­
с т о и т о в л ад еть н е п р о ст ы м
искусством б о р ь б ы с де­
ф ек т н ы м кодом Jav aS crip t,
и т о л ь к о то гд а о н см о ж ет
д о ст и ч ь н а м е ч ен н ы х вы ­
сот.
500
глава 11
одскаЗК а
продовольственным
стандартам, шоколадный
батончик может иметь около 60 раз­
нообразных дефектов. А вот когда дело
доходит до ошибок в коде JavaScript,
люди в В51 проводят политику абсолют­
ной нетерпимости, и это правильно.
охота на ошибки
Проблемы с калькулятором для Ю
с р е д н и й
П ер в ы м делом О уэну п о р у ч и л и р а зо б р а т ь с я со сц ен ар и е м , вы ч и сл яю щ и м
Щ
н а о с н о в е м асси ва д ан н ы х и со ставл яю щ и м группы и з пользо-
С качат ь ф а й лы , с к о т о р ы -
в а т ел е й со схо дн ы м и р езультатам и. В зяв за о сн ову м ассив ч и сел , эт о т сцен а р и й в ы ч и с л я е т ср е д н е е и у казы вает у р о в е н ь и н т е л л е к т а эт о го ср ед н его .
^
headF4rstla h s.c o m /b o o k s/h fjs/.
Оуэну р ассказал и , ч т о с ц е н а р и й со д е р ж и т м н о ж еств о ош и б ок. К со ж ал е­
н и ю , в о сн о в н о м о н и о п и с ы в а л и сь ф р а з о й , «оно н е р аб отает».
г 11-, 97 86, 75, 92,
І1 4
1 б 5 , '9 6 , 97, 88, 108 1;
Для отладки далеко
не всегда дают грамотно
написанный код.
далее >
501
скажи мне, что у тебя за браузер?
Различные баузеры
Ф - BS! C ase t ; 10. C ^ c u la to r,
О уэн думает, ч т о п о н я т ь пр о б л ем у ему
п о м о ж ет п р о го н с ц е н а р и я в р азл и ч н ы х
браузерах. И н а ч и н а е т с б р ау зер а In te r n e t
E x p lo rer...
I n ^ r n e t & p lo i
In te rn et
Explorer
в
Д в о й н о й щ елчо к на жел~
п^ом значке в ниж нем
ле в о м у г л у браузера 1Е
о т к р ы ва е т окно ош ибок
«■шясиигч
^5Й»fijttse.
■ÖÄÄjte-^с^агщЙтеwaBW4icajdf^^5«di
D §««^<ё№*»'1Ь5шем^ч(ймг!Вйздйсэпийгаи
f. ~0k'"'.1
R e a d v t o c a lc r f a t e th e a \ « - a g e I Q .
|цО«»е;
"iwyo
üfw.53
Oar %
'«js'isiÄ«tefined
в I n te r n e t E x p lo re r со о б щ е н и е об о ш и б ке ПОЯВЛЯС'1 'СЯ при
п е р в о й загрузке с т р ан и ц ы , н о О уэн н е у в ер ен , 'гго ему м ож н о
д о в ер я т ь . Д о с та т о ч н о взглянуть н а код, ч то б ы об н ар у ж и ть
п ер ем ен н у ю i q s , в то в р е м я как б р ау зер г о в о р и т о ее отсут­
стви и . З н ая , ч то б р ау зер ы д ал ек о н е всегда п р ав и л ь н о со о б ­
щ аю т об о ш ибках, О уэн р е ш а е т п о п р о б о в а т ь Safari...
C<Käe:S I
URL Яв:\//^;Л)всыте«8Й20в«й£2Шй0П9»М1Ым^*
-Si
В коде п ер ем ен н а я
оп р ед елен а , п о э т о ­
м у ош ибка каж ет ся
лиш ен ной см ы сла.
Safari
SyntacError - Pars«
ft’sf^#U«fjf»Fnrh*s!/DMum»Wj!'«Eisrfirst/i*»|MTll
Сая’1(tndwiabte:los
Un.- 2i
t®*: 53
Найдя ст р о ч ки ,
Rsady и calculate the average [Q.
J
Б р ау зер Safari п о к а зы в а ет н а ош ибку в совсем д ругой с т р о ч к е,
н о О уэн н а п е р в ы й взгляд н е в и д и т там н и ч е г о к р и м и н ал ь ­
н ого . П о это м у о н р е ш а е т п о п р о б о в а т ь ещ е раз, в б р ау зер е
O p e ra ...
Opera
/
J
При т о м ч т о ном ер
ст р о ки д ает ся уж е д р у гой, код ош ибки совпадает
с показан ны м в Safari.
С(ОаетЫ
)avaS!Spt-Ss,Vfec«#4>ö.A::^S>cumen»%3:«id%2DSetthgsM*ft^%ZW
orreon,-ü^^^
b * i e scnpt canpöfeon
Synax üTor ft+de iaaA^;ine 71 of irAw ж
п
Щ
a t fte:/^.^.ost,'C^Ajocijwsnis%20er>d«,20SeUings/Mid58e»%2Qf^.,
etse>fsv«?ece<50
•;^/"«>ia!ho9t^::Ä>ftM
T)№
t9%20ar«j%2ö^ttngs;'M
ichael%204o<-,5on^34sktop/b9.^S9e3_l,M
ml
Е-да! tt»ead: iosw
О кно E rro r
Consoles дает
возм ож ност ь
^•^агност ироват ь
про б лем ы с к о ­
дом J a v a S c rip t.
502
глава 11
Emjr;
name:ЯеЛв’в^сесг.'ог
iTwssaee: Stetwnerrtooline i: Refe-ence tosjndefined -.агиЫе; s#wwi<^3ess
Secktrece;
uoe iof sfföt
st»ftb3CaKfiQs'5:
Al {jritnvuntocabon
tstaffnwnt source i»de not e v a il^ J
б раузера S a fa ri
^ 1 ^ а л а с ь ош ибка вы
f j ^ f y x u m e , чт о
осе в порядке.
охота на ошибки
П р о и с х о д и т ч то-то с т р ан н о е . O p e ra п о к а зы в а ет д ругой н о м ер с т р о к и , н о п р и
этом в о с п р о и зв о д и т код, п о к а за н н ы й Safari, ч то для О уэна, к о н еч н о , х о р о ш о . Д ру­
гое д ел о , ч т о о н н е в и д и т в это м коде н и ч е г о кр и м и н ал ьн о го , и п оэтом у р е ш ае т
п о п р о б о в а т ь еш;е и F irefox...
Firefox п о м о г а е т
о6нару>^<ип\ь п р и р о 1^
Эу ошибки.
BSI Case 1: tQCaicuJatof __
0 О О,..
F ir e fo x
Firefox ука зы ва ет
нд совсем д р у ­
гой н о м ер с т р о ­
ки с п р о б лем н ы м
кодом.
trror Console
fii
* Atl
m
ih
Wafnings
Error*
ErroR
Soi4rc«riie:
calculate the average IQ.
#
Messages
{befsffi
Clear
^
^
eiae if .avsrage « SQ <
<htmi>
<head>
Do
<tltle>BSI Case
1: IQ Caloulator</title>
;»rsr;r.rs:>„,
f<Jnction showIQClass (data)
(
dOOuJnt!get\llentBy?d?"outpuj™
.innerHTML; = "You
ralcIQClass(data)
).innerHTMr.
function calcIQClass(data)
Xa! Я ду­
маю, что вижу
проблему.
(
'°aviL“ e ^ :
'
- e r a g e . Math.noor,average
/ data.length);
if
)
Should
else if average < 50 {
their tvs";
^
”
else If (average < 70) (
)
“Should hit the boo.s";
Firefox п о д ­
т верж д ает , чт о
э т а cm poK aj
я вля ет ся и с т о ч ­
н и ко м ошибки.
else If (averag < 81) (
<
®lse if (average < 9i) ^
“ "--r
. r a m exercises
, - t u r n ..people „ho could .e considered dull....
else If (average < m j
)
,
"people Of average lntelllg,„,,,,.
else if (average < i2i) ,
.
" P - P ^ e Of superior intelligence..;
else if (average
< 141) (
J J^eturn ..people of
very superio
else {
• intelligence"
Ш ТУРМ
return ..geniuses..;
Какую ошибку обнаружил Оуэн при помощи
всех этих браузеров?
</script>
</head>
I K “—
„
далее >
503
достоинства Firefox
Firefox считается наиболее подходящим
для устранения дефектов браузером,
по крайней мере, в настоящее время.
Firefox-cnacumeAb
О б н аруж и в, н аск о льк о т о ч н о F irefo x о п и сал
ош ибку, О уэн р еш и л и дальш е п о л ь зо в а тьс я
его помош;ью. О н щ елкнул н а ссы л ке в к о н ­
со л и о ш и б о к и о казал ся н а с т р о ч к е, п р ед ­
ш ествую щ ей п о д о зр и те л ьн о м у коду.
ЦоДсКаЗКа
Firefox не только хорошо обнаруживает дефекты
кода, но еще и оснащен расширением Firebug,
выводящим отладку на совершенно новый уро­
вень. Вы можете бесплатно скачать это расшире­
ние по адресу http://w w w .getfirebug.com /.
EfforConsote
II
J.
E r ro r s ,
W a r n in g s
У
M essages
________
»
: _ С *е а г
На в т о р у ю ош ибку пока не о б раил,айтле в н и м а н и я — будем р а с ­
с м а т р и в а т ь их по одной за раз.
<Ьеа^>
<Ьеаа>
П оследовав по
ссы лке, вы у ви д и т е
код веб -ст р а н и ц ы .
Строчка,, п р е д ш е ­
ст ву ю щ а я п о д о ­
зр и т е л ь н о й , б уд ет
выделена.
—'
case Ь ха
f u n c tio B ^ h o w I ( 3 C la s s { d a ta »
}
*
ddocuaintfeetSlLMtByld
o c u J n t f e e W l L M t B y l d ? «г ™
* ut«
äiiS
«IclOClasstdatai I
fu a c tio a c ftlc io c la s s (d a ta )
• ■' >>••;
{
« - a ,. .
П ричиной п роб лем ы
я в ля ет ся в о т э т о т
код.
o f tJ ,e
J re t« ,
" p e o p le wbo . h o u l 4 k i l l t b . i . w . - ,
e l s e i f a v e r a g e « S* / ____ _
G ise i f
{average < 7 0 ) /
}
“ bo s h o u ld h i t t h e
e ls o i f (a v e ra g < 81) |
-v
^ r e t . « - p o o p l . „ h o S h o u ld c o n s i d e r b r a i . ^
Д.1ДР ;{
f a v rir a q e <
■■
:cises"
Lif»e2S,Cor i
А нализи руя п о к а за н н о е б р аузером F irefo x с о о б щ ен и е
об ош и б ке, О уэн о б наруж ил, ч то б р ау зер Safari п р а ­
ви л ьн о указал н о м е р о ш и б о ч н о й с т р о к и (25). F irefo x
вы д ел и л и упом янул строку 24, н о п р а в и л ь н о п ок азал,
ч то о ш и б ка со д е р ж и т с я в с т р о к е 25. И ч т о н ам н ого
в аж н ей , F irefo x о б ъ ясн и л , ч т о и м е н н о н е в п о р я д к е
с кодом .
504
глава 11
*
e l s e i f a v e r a g e < 50 {
В о п е р а т о р е if п р о вер я ем о е
усло ви е забы ли за к л ю ч и т ь
о скобки.
охота на ош ибки
Часто
Задаваем ы е
Б о і ї р о с ; і ,і
• Где находится консоль в моем браузере?
Q ; к сожалению, все браузеры разные, и иногда обнаружить
консоль для просмотра ошибок JavaScript не так-то просто.
Например, браузеры Safari для компьютеров Макинтош дают
доступ к консоли только через меню Debug, доступ к которому
по умолчанию отсутствует. Для получения доступа введите
Он превосходит другие браузеры в умении находить дефекты
в коде сценариев и указывать на них. Возможно, в будущем
и другие браузеры смогут выполнять данную функцию так же
хорошо, но в настоящее время именно Firefox является самым
мощным инструментом для отладки сценариев JavaScript.
3*
На какую ошибку указывал Internet Explorer?
в приложение Tenninal следующую команду (в одну строчку):
defaults write c o m .apple.Safari
IncludeDebugMenu 1
Если у вас другой браузер, почитайте документацию, там должно
быть написано, как открыть консоль. В браузере Firefox она
открывается командой Еп'ог Console из меню Tools.
! Этого, к сожалению, узнать нельзя. Дело в том, что
код сценария был загружен некорректно, и поэтому ошибка,
о которой сообщает Internet Explorer, — это результат неверной
работы интерпретатора JavaScript. О некорректной загрузке
можно судить по тому, что переменная i q s была указана
как «неопределенная», в то время как код ясно показывает
процедуру создания i q s .
! Что делает браузер Firefox таким особенным?
Напрашивается вопрос: содержит ли сценарий и другие ошибки
и что на самом деле означает термин «неопределенный»?
; Разработчики этого браузера проделали большую работу
и дали своему детищу большие способности к поиску ошибок.
Несло)кная отладка
О уэн счастл и в о т сто л ь б ы ст р о го за в е р ш е н и я п о и с к а о ш и б ки
в к ал ьк у л ято р е Щ . С л егко стью в н еся и с п р а в л е н и я в код, о н р е ­
ш ает, ч т о эта р а б о т а для н е го п о д х о ди т. И у в ерен , ч то б ы стр о
ст а н е т в это м дел е н асто яш и м п р о ф е с с и о н а л о м .
else
if
(average
<
П о м ест ив усло ви е 8 скобки,
м ы у с т р а н я е м ош ибку
в к а л ь к у л я т о р е IQ-
y c m j- a нен а Д обавлением
°твсі^сгг>Бі|іоЩ их
СКовоК.
Н о м о ж ет б ы ть, О уэн и зл и ш н е сам оуверен?
Ж е л а т е л ь н о п р о т е с т и р о в а т ь и с п р ав л е н н ы й
с ц е н а р и й и т о л ь к о п о то м думать об отды хе..
далее *
505
что здесь происходит?
О т ч е т не Всегда указывает на ошибку
к
со ж ал ен и ю , о тлад ка к ал ьк у л ято р а I Q ещ е н е зак о н ч е н а, п отом у ч то
F irefo x с н о в а указы вает н а ош ибку, н о уж е в другом м есте. О уэн п о п ы та л ся
п о л о ж и т ься н а в ы д аваем ы е б р ау зер о м о ц е н к и , н о н а э т о т р а з, каж ется,
п р о сч и тал ся .
В о т скобка, парная
Эля т о й , о к о т о р о й
у п о м и н а е т р!гегох,
■т а к чт о со скобкам и
ц данной ф у н к ц и и все
8 порядке.
<html>
<head>
function ShowIQClassMata, i
alert("Click Off u .
document.9etEle„e„tByM("outpuj
,
“ i«OClass,data, .
Мы р а с с м а т р и в а е м
одну ош ибку за один р а з,
п о э т о м у данную зап ись
снова п р о и гн о р и р уем .
' "Vou are CeaU„,
,4 r "
alculate the average IQ
var average = ofor (var 1 . 0,- 1 < 0 a 0
average +- data
average , Math, floor tillgi ^
B o m скобка,
на о т ­
сут ст вие
кот о р о й
ука зы ва ет
Firefox
ih
// Return the class! |AB ’ EffOfS
If (average < 20) (
r—
return "people „ho
Warnings
Messages
}
eise if (ave^^^^ <
retijrii.>pg^le who
Error: ffiTssingIafterfafictionbofly
v
Source Flfe^ Шй:/ f /Users
\
®lse if (average < ?C
J return "people who :
t'
else if (averag < 81) '•
J i^eturn "people who £
else if (average < 9i)
^ return "people who c'"“
EiTon shov^^Class is not defineil
шІЛШй
^S&yrc«Fik;
else if (average < ur
J return "people of av€
else if (average < 121) ™
J return "people of superio
else if (average < 141, ,
.
,
"P-Ple Of very superior in^
else (
return "geniuses";
Кажется, твой магический от­
ладчик перестал работать. У этой
функции все скобки на месте.
‘55ript>
</head>
<body onload."sho„IQClass(l„3)
<-,^src=..bral„,p„g.. alt'Jb!;!:.. />
Браузеру можно верить не всегда.
К ак в и д и те, со ско б кам и у ф у н кц и и все в п о р яд ке. Н е с м о т р я н а
все сво и сп о со б н о сти , F irefo x в д ан н о м случае ср аб о т а л н е в е р н о .
В п р о ч ем , у п о м и н ан и е об отсутствую щ ей скобке я в л я е т с я п о вод ом
о б р а т и т ь п о в ы ш е н н о е в н и м ан и е н а д ан н ы й аспект.
506
о
Error Console
глава 11
l;
Une:.i
охота на ошибки
инш ерчретаахоороМ JaVa^crij=>t.
Ц|>оБе]=>ьдае скобки Б данном сЦена|зии,
Чщобь1 понять, Чщо именно с ними
<html>
<head>
<title>BSI Case 1: IQ Calculator</title>
не т а к .
<soript type="text/javascript">
var iqs = [ 113, 97, 86, 75, 92, 105, 146, 77, 64, 114, 165, 96, 97, 88, 108 ];
function showIQClass(data) (
alert("Click OK to begin IQ calculation.”);
document. getElementByld ("output") .innerHTML = "You are dealing with <em>" +
calclQClass(data) + "</em>.";
}
function calclQClass(data) {
// Calculate the average IQ
var average = 0;
for (var i = 0; i < data.length; i++) {
average += data[i];
average = Math.floor(average / data.length);
// Return the classification of the average IQ
if (average < 20) {
return "people who should kill their tvs";
else if (average < 50) {
return "people who should really hit the books";
}
else if (average < 70) {
return "people who should hit the books";
)
else if (averag < 81) (
return "people who should consider brain exercises";
)
else if (average <91) {
return "people who could be considered dull";
)
else if (average < 111) {
return "people of average intelligence";
}
else if (average < 121) {
return "people of superior intelligence";
)
else if (average < 141) {
return "people of very superior intelligence";
}
else {
return "geniuses";
</script>
</head>
<body onload="showIQClass(iqs);">
<img src="brain.png" alt="brain" />
<br />
<div id="output">Ready to calculate the average IQ.</div>
</body>
</html>
далее ►
507
стань решением
гадшщАчи
^ а М 1^ЖНо ёььЛо nj^oB ejniipb с к о б к и
<html>
<head>
<title>BSI Case 1: IQ Calculator</title>
Б данно]уг cUeHap*uu и цонящь, Чщо
именно с HuMu не т а к .
<script type="text/javascript">
var iqs = [ 113, 97, 86, 75, 92, 105, 146, 77, 64, 114, 165, 96, 97, 88, 108 ];
function showIQClass(data) {
alert("Click OK to begin IQ calculation.");
document.getElementByld("output").innerHTML
calclQClass(data) + "</em>.";
)
После
в ы р а ­ function calclQClass (data)f{%
I I Calculate the averagee TQ
жения
var average = 0;
для
for (var i = 0; i < data.length; i++)((
переaverage += data[i];
МеННОМ ^^verage = Math, floor (average / data, length) ;
a d d itio n
Эолжна
стоять
eturn ..people k ^ o u i d k i l l th e ir tvs";
3aK pt> i-(T)
--
6afOU4a S ! ^ s e
CKo Sk A.
"You are dealing with <em>" +
1
^^сщ ранения
оШ цбки Д обавим
........^
У ..........
эт о й от
кры ^
баю щ ей с к о ккы
от сут ст вус^m
пара!
if (average < 5 0 ) ^ 0 - __
___________
"people who shiuld really hit th e b o o k s ^
aise if (average < 70)
----return "people who should hittte books "~r>
Q ,se if
(averag < 81)(
return "people whoI sKould
snou. consider brain exercises^^
©
« s e if (average < 91)Г{Л-..............
^.^^^return "people who coHld be considered d u l l " 7 ^
Закры Б аю п^Ю ся
CKo6ig.
А м о ж н о , наоборош ,
у б р а т ь о т к р ы ва ю щ у ю
скобку п о сле цикла fo r,
ведь ц и кл все равно з а ­
п у с к а е т т о ль к о одну
ст р о ч к у кода. Скобки
т у т нужны т о ль к о для
наглядност и.
else if (average < 111)^77 ------- ---- — -v.
return "people of averse intelligence";]
Q ) ---------------------—
^
Л е е if (average < 121) f o ____ ________ —
^_jeturn "people of supeiKor intelligence";^
else if (average < 141)
return "people of very superior intelligi
Q,
re t W n "geniuses"
#
< /^ ril
</head>
<body onload="showIQClass(iqs);">
<img src="brain.png" alt="brain" />
<br />
<div id="output">Ready to calculate the average IQ.</div>
</body>
</html>
508
глава 11
Несовпадающие или
отсутствующие скобки
являются частой ошибкой
в 1ауа8спр1. Но ее
легко избежать, уцелив
повышенное внимание
синтаксису.
охота на ошибки
Неопределенные переменные
К аж ется, о тд ы х О уэну н е св е ти т, потом у ч т о кал ьк ул ятор I Q о б ­
н ар у ж и в ает все н о в ы е и н о в ы е о ш и б ки . Т е п е р ь F irefo x указы вает,
ч т о п е р е м е н н а я «не о п р ед ел ен а» , ч то н а п о м и н а е т нам ф и кти вн ую
ош ибку, о к о т о р о й уж е до кл ады вал I n te r n e t E x p lo re r. Н о н а э т о т р аз
н е о п р е д е л е н н а я п е р е м е н н а я н а зы в а е т с я a v e r a g , а н е i q s .
О б р а т и т е вн и м а н и е, чт о
вт о р а я ош ибка исчезла сам а
содой. И ногда внесенные
одном м е с т е и сп р авлен ия
способны у с т р а н и т ь срази
несколько ош ибок
воо
Возьми 6 руку карандаш
Как вы думаете, что означает термин undefined в контексте
последней обнаруженной Оуэном ошибки?
далее *•
509
проверь свою работу
Возьми в руку карандаш
Решение
Вот что означает термин undefined в контексте последней
обнаруженной Оуэном ошибки.
.*5. несозЭднной перем енной^ т а к
м к п е р е м е н н о й J к о т о р о й не было присвоено начальное значение.
О ш ибка во зн и ка ет п р и ссы лке на т а к у ю п е р ем ен н у ю .
иногда Все просто
в д ан н о м случае о п р е д е л е н и е u n d e fin e d о т н о с и л о с ь к п ер е м е н н о й ,
кото р у ю п о п ы та л и с ь и сп о л ь зо в ать , н е создав, х о т я и со в ер ш ен н о
случайно. П р и ч и н о й стал а о п еч атк а. В р езу л ьтате и н т е р п р е т а т о р
Jav aS crip t р еш и л , ч т о п е р е д н и м совсем д ругая п ер ем ен н ая .
function
// Calculate the=
r, , ,
average - 0
^0
for (var i . o-'i < H
^ «erage
ditall,;
I
''re't:"“^"'"
--age
T ' ’“ 9e < 50)
IQ
У с т р а н и т ь one
чат ку прост о,
а б о т оонйруж ит ь
т рудно!
—:
reall,
th
"people „.o 3.o„ld M t
-
--------------------------------
t.e
e lse if
}
(average < 81)
{
r eturn "people w ho s h o u l d c o n s i d e r
b r a i n exercises";
if (average <
else If (average < щ ,
/
h
,
,
і,
И сп р а ви в о п е ч а т к у ,
мы реш им пробле­
м у неопределенной
перем енной.
,
)
if -average <
Иногда причиной
проблемы может
стать обычная
опечатка.
,
"
i-elllg.„,„,,.
(average < ip-i\
superior
Calculator
l^iiigence";
О
averag
average
Ready to calculate the average IQ.
Click OK to begin IQ caiculat
Done
510
глава 11
охота на ошибки
Ч асзц о
^аД аБ аеМ ы е
БоИ роС Ь!
Есть ли разница между «undefined»
и «not defined»?
; Нет. Термины означают одно и то же,
просто некоторые браузеры используют
один из них, а некоторые — другой.
А в чем тогда разница между
«undefined» и
Про значения «undefined» и null нужно
помнить только то, что в логических выра­
жениях, например, при проверке условия
А так как этой новой переменной значение
еще не присвоено, невозможно использо­
вать ее в условии оператора i f . Вы же
не можете написать обзор фильма, даже
не посмотрев его?
в операторе i f они дают значение
false. Именно поэтому код вида if
(someObject) используется для про­
верки существования объекта перед тем,
как осуществить доступ к его членам.
null?
3 » Вы шутите? Работая в текстовом
редакторе, я постоянно делаю опечат­
ки, и это ни на что не влияет. Почему
иа7а8сг1р1 столь чувствителен?
А почему опечатка сделала пере­
Q l Здесь все сложнее. На техниче­
ском уровне между «undefined» и null
существует разница, но она не настолько
существенна, чтобы об этом задумы­
ваться. Дело в том, что null — это
значение, которое можно присвоить пере­
менной. Существует также тип данных
undefined, к которому автоматически
причисляются все переменные, которым
пока не присвоено никакого значения.
Но переменным никогда автоматически
не присваивается значение null. Это
делается вручную на начальном этапе,
чтобы показать, что объект еще не был
создан.
менную
average
неопределенной?
Как это случилось?
на то что переменная
0:! Несмотря
была создана и инициализи­
average
рована, JavaScript не может установить
связи между переменными averag
и average только потому, что их
имена похожи. С точки зрения JavaScript
переменная averag могла называться
и shazbot или lederhosen. Други­
ми словами, JavaScript интерпретирует ее
; к этому вам просто придется привык­
нуть. Сценарии пишутся не для людей,
а для машин, и машины не прощают
ошибок, вне зависимости от того, на каком
языке написан сценарий. Он перестанет
работать даже из-за одного неверного
символа. Существует определенная
свобода в расстановке пробелов и знаков
переноса строки, но сам код не должен
содержать ошибок.
как совершенно другую переменную.
Работа с цифрами
П о сл е и с п р ав л е н и я о п е ч а тк и кал ьк у л ято р 1Ц н ач ал р а б о т а т ь к о р р е к т н о , вы ­
ч и с л я я ср е д н е е и з м асси ва ч и сел и о т о б р а ж ая по резул ьтатам соответствую ­
щую к л асси ф и к ац и ю . О уэн м о ж ет с ч и т а т ь р аботу в ы п о л н е н н о й и п о ч и т ь н а
лаврах ... в о т т о л ь к о н ад олго ли.''
вы Case 1: iQ C a icu l^ r л .
О
Б лагодаря ст а р а н и я м
О уэна к а л ь к у л я т о р IQ
т е п е р ь р а б о т а е т maKj
как и было задум ано
к у , М ы y c rn j^ a H u jiu
/
_
Y o u а » dealing with p e o p le o f a v e ra g e in teU ig en ce.
Done
■_
далее ►
511
звони и выигрывай
и
>
КЛЮЧЕВЫЕ
МОМЕНТЫ
^
Хотя большинство браузеров и снабжено консолью,
на которой отображается информация об ошибках
иауаЗспр!, эта информация не всегда достоверна.
Несмотря на излишне схематичный характер инфор­
мации об ошибках, она зачастую дает понять, на что
именно нужно обратить особое внимание.
Распространенной ошибкой является неверная
расстановка скобок вокруг блоков кода — следите,
чтобы число открывающих и закрывающих скобок
совпадало.
Опечатку легко сделать, но трудно обнаружить —
всегда проверяйте имена идентификаторов.
Звонки на радио
Н е успел О уэн о б р ад о в а ть с я удачном у за в е р ш е н и ю р а б о т ы , как
ему д ал и н о в о е зад ан и е. Н а э т о т р а з ему п р е д с то и т и м е т ь дело
со сц е н а р и е м , обрабаты ваю ш ;им зв о н к и н а р ад и о , к о т о р ы й пс
н ом ер у зв о н к а о п р е д е л я е т п о б е д и те л я в и к то р и н ы . С ц е н ар и й
д о л ж ен п о д с ч и ты в а ть зв о н к и и п ри суж дать победу человеку,
позво н и вш ем у , н а п р и м е р , седьм ы м .
В Ы С а $ е ? \.У п п П 9 С аН ег
© .© в
512
глава 11
охота на ошибки
Начинаем расследование
П е р е д и с п ы т а н и е м с т р а н и ц ы в б р ау зер е О уэн р еш и л взглянуть
н а ее код (его м о ж н о ск ач ать п о адресу http://wivw.headfirstlabs.
сот/books/hfjs/), ч то б ы п о н я т ь , каким о б р азо м о н р аб о т ае т . Ведь
и н о гд а м о ж н о сразу увидеть, ч т о к о н к р е т н о и д ет н е так, и л и по
к р а й н е й м е р е п о н я т ь , как и м е н н о д о л ж ен р а б о т а т ь сц ен ар и й .
И м я звонящ его и н о ­
м е р вы игравш его звонка
в м е с т е с о б ъ ек т о м
fo r m п ер ед а ю т ся
в ка ч ест ве а р гу м е н т а
ф ункции ckeckW innerQ .
Если ном ер
звонка с о в п а ­
д а ет с вы >игрышныМ1
показы ваем
им я звонящ его
С чет чи ку з в о н ков п р и с в а и в а ­
ет с я начальное
значение ноль.
от дельном
кне.
Увеличение
показаний
счет чика
на единицу.
Если звонящ ий
не я вля ет ся
по б ед и т е л е м ,
уд а ля ем его
и м я из поля.
Сценарий с е р в е ­
р а для с о хр а н е^ ч я инф о р м а ц и и
' победит еле.
Щ елчок на кнопке Call
вы зы вает ф ун к ц и ю
про вер ки поб едит еля
ckeckW innerQ .
Возьми в руку карандаш
Помогите Оуэну, указав, сколько ошибок, по вашему мнению,
содержит данный сценарий.
Ноль
Одна
Четыре
две
Три
Пять
далее ►
513
что? синтаксическая ош ибка
Возьми в руку карандаш
IX
'ешение
Ноль
Одна
Вот сколько ошибок содержит код данного сценария.
две
Трц
Пять
/Д авайт е продолж им и п о ­
м ож ем О уэн у н а й т и все
эт и ошидки...
Проверка синтаксиса (ошибка # 1 )
П олучи в п р е д с та в л е н и е о то м , как до л ж ен р а б о т ат ь э т о т сц е­
н а р и й , п о с м о тр и м , ч то п р о и с х о д и т п р и п о п ы тк е зап усти ть
его в б р ау зер е F irefox. Э то т б р ау зер н ем ед л ен н о д ае т свед ен и я
о си н та к си ч е с к и х о ш ибках, т о есть о н ар у ш ен и ях п р а в и л я зы к а
JavaS crip t.
Браузеры всегда
сообщают
о синтаксических
ошибках.
О
пшаЬвг ФcaiiHm 4.
else i
»ost caller
Б р а узер у к а зы в а ­
ем. на п р о ц ед ур у
соединения ст р о к.
)
caiierPield.select();
П р и в к л ю ч е н н о й ф у н кц и и со о б щ е н и я об о ш и б ках б р ау зер ы
всегда и н ф о р м и р у ю т о п р о б л ем ах с си н так си сом . И м е н н о это
посл у ж и т о т п р а в н о й т о ч к о й д ля н аш и х и зы ск ан и й .
514
глава 11
■LoUay s w-sner: }
охота на ошибки
Аккуратнее со строками
F irefo x указал н а проц едуру с о е д и н е н и я стр о к , и и м е н н о ее мы
н ач н ем а н а л и зи р о в а ть. В ы зы в ается ф у н кц и я a l e r t ( ) , в к о т о ­
р о й н еск о льк о ст р о к о в ы х л и т е р а л о в с о е д и н я ю т ся с п е р е м е н ­
н ы м и c a l l e r и c a llN u m .
if
(callNum
=
alert(caller
winningNum)
+
+
callNum
+
Э т и два ст р о ко вы х
л и т е р а л а о о ьединяю т ся
с двум я п ер ем ен н ы м и .
В J a v a S c г ip t в а ж н а п а р н о с т ь к а в ы ч е к .
К ав ы ч к и всегда д о л ж н ы и д ти п ар ам и , и н ач е Jav aS crip t н е см о­
ж е т о п р е д е л и т ь , где к о н ч ае т ся од н а с т р о к а и н ач и н а е т с я другая.
В с ц е н а р и и , об р аб аты ваю щ ем зв о н к и н а рад и о , в од н ом и з
ст р о к о в ы х л и т е р а л о в н е х в а т ает кавы ч ек. Т о е с ть п е р ед нам и
б ан ал ь н ая с и н так си ч е ск ая ош ибка.
И д о с т а т о ч н о д о б ав и т ь н ед о стаю щ и е к авы ч к и в к о н е ц строки :
if
(callNum
=
alert(caller
if
(callNum
=
al e r t (caller
winningNum)
+
",
caller
numbei^^^
callNum
+
"...
today's
winner!")
winningNum)
+
",
caller
number
" -I- c a l l N u m
+
"...
today's
winner!")
Q m u S x a усгв|=>анена
ДоёаБл^ением naj^H bix
КаВьхЧек.
далее ►
515
важно быть последовательным
КаВычки U апострофы
Н е д о стаю щ и е к ав ы ч к и — эт о т о л ь к о о д и н в а р и а н т ош и б ки , в о з­
м о ж н ы й п р и р а б о т е со стр о кам и . Д ел о в то м , ч т о вы д ел ен и е с т р о к
в Jav aS crip t и в ы д ел е н и е атр и б у то в в Н Т М Ь во зм о ж н о как п р и п о ­
м ощ и кав ы ч ек, т а к и п р и п о м о щ и а п о с т р о ф о в . А зн ач и т , важ н о не
п ер еп у тать эт и д ва знака.
А т р и б у т ы HTML
“заклн?чян?тся
в кавш ки.
<input type="button" value="Call"<
onclick="checkwinner(this.form, document.getElementByld{'caller')-value, 7)" />
V
Ч а с т о д ля в ы д ел е н и я Н Т М Ь -атр и б у то в и сп ользую т кавы ч ки ,
в то в р е м я как с т р о к и Jav aS crip t, р а с п о л о ж е н н ы е вн утри эти х
атр и б у то в, в ы д ел яю тся а п о с т р о ф а м и . Н о м ож н о и с п о л ь зо в ат ь
и о б р а т н ы й сп о со б в ы д ел ен и я , как п о к а за н о ниж е:
<input type='button' value='Call'
—
С т роки J a v a S c r ip t в н у выдр.л/>и1т р и аат
тю
р иибцт
б у т а выделены
п р и п о м о щ и апост роф ов.
С оврем енны е с т а н д а р т ы
XHTML не р а зр е ш а ю т
вы делят ь а т р и б ут ы
( ап о ст р о ф а м и .
Д)
I
onclick='checkwinner(this.form, document.getElementByld("caller") .value, 7)' />
4
8 эт ом прим ере anocm po_ ф ы и с п о л ь зу ю т с я для H T M L --------- —
ат р и б ут о в,, в т о вр е м я как
с т р о к а J a v a S c r ip t заклю чена
в кавычки.
В аж н о за р а н е е р еш и ть , ч т о и м е н н о вы будете и с п о л ь зо в ат ь
для в ы д ел ен и я о п р е д е л ен н ы х ф р а гм е н т о в кода. И т а к как
X H T M L , с о в р е м е н н а я в е р с и я H T M L , т р еб у ет в ы д ел ен и я
атр и б у то в т о л ь к о п р и п о м о щ и кав ы ч ек, зн а ч и т , д ля вы д ел ен и я
ст р о к Jav aS crip t о стаю тся а п о с т р о ф ы .
П р о б л е м а в о зн и к а е т, есл и вам тр еб у ю тся к авы ч к и и л и а п о ­
с т р о ф , н о э т о т зн а к уже исп о льзу ется, н а п р и м е р , как п о к азан о
ни ж е:
alert{'It's so exciting!'
В у д е т ли р а б о т а т ь
э т о т код?
516
глава 11
В строках 1ауа8спр1
и атрибутах НТМЬ
кавьпки и апострофы
могут заменять друг
друга.
Ш ТУРМ
Что делать, если вам нужно вос­
пользоваться знаком, применяе­
мым для выделения строки?
охота на ошибки
Е$С-СимвоАЫ
Р а с п р о с т р а н е н н о й о ш и б к о й я в л я е т с я и с п о л ь зо в ан и е к а в ы ч ек и л и ап о ­
с т р о ф о в как си м в о л о в в с о став е стр о к и . И м е н н о т а к а я с и н так си ч ес к ая
о ш и б ка с о д ер ж и тся в коде д ля всп л ы ваю щ его окн а. И н т е р п р е т а т о р
Jav aS crip t н е м о ж ет р а с п о зн ат ь , к ак и е а п о с т р о ф ы у казы ваю т н а к о н ец
с т р о к и , а как и е —яв л я ю т ся ее частью . К счастью , м ы м ож ем л егк о о б о зн а ­
ч и т ь «реальность» сим вола, п о м ести в п е р е д ни м об ратную косую черту
( \ ) . В р езу л ьтате о н п р е в р а т и т с я в т а к н а зы в а ем ы й е8с-си м вол .
alert('It\'s so exciting!');
Т е п е р ь Jav aS crip t т о ч н о зн а е т , ч т о м ы х о т е л и п о м ес т и т ь в строку
си м вол а п о с т р о ф а , а н е указать н а к о н е ц э т о й с т р о к и . В п роч ем ,
м ы м о гл и и обм ан уть и н т е р п р е т а т о р , за м е н и в о гр ан и ч и в аю щ и е
строку зн ак и н а кавы чки .
alert("It's so exciting!
_ Esc -с и м в о л
больш е не нужен.
Esc-символы указывают
на символьные литералы
в строках.
В п ро ч ем , м о ж н о при дум ать и в о т т а к о й в а р и а н т кода:
alert("They said, "you've won!"");
Т ак к ак в дан н о м случае с т р о к а с о д е р ж и т в ка ч е ств е л и т е р а л о в
и кав ы ч ки , и а п о с т р о ф , о с т ае т с я т о л ь к о п р и б егн у ть к п о м о щ и escсим во л о в. Т а к о й с ц е н а р и й к том у ж е н ам н о го б езо п ас н е й , потом у
ч то н е д опускает н и к а к и х вари ан тов^гр а к т о в ^ .
ддбол туил
alert("They said, \"you\'ve won !\"
о б я з а т е л е н , НО
Аучш е его п о с т а ­
вить).
пражнение
Устраните проблему, связанную с наличием кавы чек и апостроф ов, в показанном ниже
фрагменте кода.
var message = 'Hey, she's the winner!';
var response = "She said, ''I can't believe I won.""
<input type="button"' vaiue=="Winner" onclick="givePrize("Ruby");" />
далее >
517
реш ение упражнения
Вот каким образом при помощи esc-символов были внесены исправления в код, содержа)З Ж Н 2 Н И 2
'ешение
множество апостроф ов и кавычек.
var
message
=
' Hey,
she's
the
winner!';
v a r m essage = 'H ey, s h e \ s th e w inner!';
Здесь e sc си м во л не
о б яза т елен,
т а к как
апост роф
находит ся
в ст роке,
за клю ченно й
в кавычки.
var
response
=
"She
said,
"I
can't
believe
1 won.""
~
—
v'ar response - "She sa id , V I c a n \‘t believe I w o n.\""
<input
type="button"
value="Winner"
o n c l i c k = " g i v e P r i z e (" R u b y " ) ;"
/>
^
“^ in p u t t y £ e ~ ‘b u tto n " v a lu e -'W in n e r" o n c lic k - ‘givePrize('Ruhy');" />
................................................................................................: ......................................
8 даннолА случае e sc -с и м во лы р а б о т а т ь не б уд ут ,
т а к как у нас и м е е т с я с т р о ка J a v a S c r ip t вну т р и H TM L-а т р и б ц т а . П роблема р еш а ет ся п р а ­
вильной расст анобкой кавы чек и ап ост роф ов.
Неопределенность функции (Ошибка # 2 )
И так, од н а о ш и б ка и сп р ав л ен а, по О уэн зн ает, ч то р а б о т а дал ека о т зав ер ш ен и я . Р аб о та о б р а ­
б аты ваю щ его зв о н к и с ц е н а р и я н а ч и н а е т с я гладко, б ез ош иб ок, а вот п р и щ елчке н а кн о п к е Call
п р и п о п ы тк е указать им я зв о н ящ его п о л ьзо в ател ь с тал к и в ается с п р о б л ем о й . И каж ется, о н а
связан а с ф у н кц и ей c h e c k w i n n e r {).
СЭ
BSI Case 2: Winning Caller
e o e
S J -
CaEer n a m e : jH ow ard
0 0 6
в '
1 All
Щ елчок на к н о п ­
ке Call п р и во д и т
к ош ибке, к а к и м т о образом с в я ­
занной с ф ункцией
checkW innerQ .
&
Errors
Error Console
iL
Warnings
m
Messages
Clear
Ermr. checto«Rn€f Is not defined
Source
П очему - m o
э т а ф ункция
не о п р е д е ­
лена.
518
глава 11
f&t’N /Users /mjchaei .‘Document«/headWr’
§iЬMШШйЩfш\ммШçм^2^2^hmï Une 1
—
- ...........- ..........
У казание на н о м е р ст р о ки
н а м ничем не пом ож ет ,
т о ч н о зн а е м , чт о
с п ер во й ст р о ч ко й H T M L кода п р о б ле м нет .
охота на ошибки
Обычный список подозреваемых
О уэн р е ш а е т и с п о л ь зо в ат ь п о л у ч ен н ы й р а н е е о п ы т и п р о й ти с ь
по списку сам ы х р а с п р о с т р а н е н н ы х в Jav aS crip t ош и б ок. Ведь,
во зм о ж н о , с т а к о й о ш и б ко й о н уже сталкивался.
,rm, caller, winningNum)
звонка на единицу
кругла, cKosJ ..
Несовпадающая им, отсу^
(
// проверка победителя
callNum +
form, submit о ;
else
" ^"“irertirw ПГсГеп"^детеш1
irilS fe fa ^ a lu e = "Next caller..
' caller’, ;
callerField.focusO ;
c a l l e r F ield.select 0 ;
Ссылка на
ф ун к ц и ю
ckeckW in n erQ
попадаем ся
т о ль к о два
раза.
</script
</head>
</form>
</body>
</html>
возьми в руку карандаш
Укажите, какая проблема, с вашей точки зрения, мешает рабо­
те сценария обработки звонков.
I I Н есо в п ад аю щ ая и л и отсутствую щ ая
ф и гу р н ая скобка.,
I I О п е ч а тк а в и м е н и и д е н т и ф и к а т о р а .
□
Н есо вп ад аю щ ая и л и отсутствую щ ая
круглая скобка.
Н е п р а в и л ь н о е и с п о л ьзо в ан и е
к ав ы ч ек и ап о ст р о ф о в .
П К акая-то другая п роб л ем а.
далее >
519
реш ение упражнения
Возьми В руку карандаш,
Решение
□
Вот в чем заклю чается проблем а, м еш аю щ ая работе сцен ари я
о б р а б о тк и звонков.
Н есо в п ад аю щ ая и л и отсутствую щ ая
ф и гу р н ая скобка.
_ Н есо в п ад аю щ ая и л и отсутствую ­
щ ая круглая скобка.
Н е п р а в и л ь н о е и с п о л ьзо в ан и е
к ав ы ч ек и ап о с т р о ф о в .
О п е ч а тк а в и м е н и и д е н т и ф и к ат о р а .
□
К акая-то д ругая п роб л ем а.
ф ункция ckeckW in n erQ вы зы вает ся как
ck e c kw in n erQ j п о т о м у ч т о в и м ен и по
ош ибке по яви ла сь м а ле н ьк а я w. В р е з у л ь ­
т а т е и н т е р п р е т а т о р п ы т а е т с я вы ­
зв а т ь ф у н к ц и ю , ко т о р а я не была о п р е д е ­
лена.
А л я ус т р а н е н и я
ош ибки дост ат очно
за м е н и т ь w на W
t y p e="butt||fi"
# 2
y c n f -а н е т
UC-
^аВ лет ем
Ш ет ф у н к ц и и .
J
<input
Г
value="Call'
onclick="checkWinner(this.form, document.getElementById('caller').value, 7)" />
Побе}кдают бее (Ошибка # 3 )
Д аж е п о сл е у с т р ан е н и я д о сад н о й о п е ч а т к и в и м ен и ф ун кц и и
с ц е н а р и й н е р а б о т а е т нуж ны м о б р азо м . Х о р о ш о х о т я бы то,
ч т о б р ау зер н е в ы б р ас ы в а е т с о о б щ е н и й об ош ибках. В от т о л ь к о
в ы и гр ы ш н ы м т е п е р ь я в л я е т с я каж ды й зв о н о к —с ц е н а р и й п р и
эт о м п р и с в а и в а е т ему к о р р е к т н ы й н о м ер . И ес л и О уэн н е спа­
сет ситуацию , р а д и о с та н ц и я р а з о р и т с я н а вы д ач е п ри зов!
BSie. caller nymber 7...today’s w in ie
С
Ж
Э
С т ш н н о т о , ч т о каж до­
м у звон ку п р и сва и ва ет ся
вы игры ш ны й н о м ер , вне
за ви си м о ст и о т т о го к а ­
к и м по сч е т у он я вля ет ся
С£^МОМ дбЛ&.
|
"“« b er ^...today's win, e
tobv. сан« number
П обедит елем о б ъявляет
СЯ каждый позвонивший.
520
глава ft
охота на ошибки
Отладка с помощью ВсплыВающих окон
М ы зн аем , ч т о о п р е д е л е н и е п о б е д и те л я п р о и зв о д и тс я путем с р а в н е н и я п е р е ­
м е н н о й c a llN u m с аргу м ен то м w in n in g N u m ф у н кц и и c h e c k w i n n e r ( ) . Н о
что-то с эти м кодом н е так, по это м у д ав а й те б о л ее п о д р о б н о р а ссм о тр и м , ч то
п р о и с х о д и т с п е р е м е н н о й c a llN u m .
На первы й взгляд с к о ~ -------- - дом все в порядке.
if
(callNum
=
winningNum)
-
И м е е т см ы сл п р о с ле д и т ь ,
как м е н я е т с я значение
п е р ем е н н о й саНМит по
м е р е раб от ы сценария.
Как бы посмотреть на зна­
чения переменной в раз­
ные моменты времени?
Всплывающие окна являются
отличным инструментом
р я отслеживания значений
переменой.
В с п л ы в а ю щ и е окна как инструмент отладки.
В спл ы ваю щ и е о к н а го д я тся н е т о л ь к о для о т о б р а ж ен и я
и н ф о р м а ц и и , п р е д н а зн а ч е н н о й д ля к о н е ч н ы х п о л ьзо ва­
т е л е й . С и х пом ощ ью м о ж н о так ж е о т сл еж и в ат ь зн а ч е н и я
п е р е м е н н ы х и п р о в е р я т ь к о р р е к т н о с т ь в ы зо в а о тд ел ьн ы х
ф р а гм е н т о в кода. В наш ем случае п р и п ом ощ и всп л ы ­
ваю щ их о к о н м ы п р о сл ед и м за зн а ч е н и я м и п е р е м е н н о й
c a llN u m .
В сплы ваю щ ее окно по
зв о л я е т п р о след и т ь за
зн ачен ием п ер ем енной
callNum .
f~ o iT 3
далее >
521
всплывающие окна — это тоже инструмент
Следим за значением переменной
Т е р м и н «контрольное значение» о зн а ч а е т н е п р е р ы в н о е о т с л е ж и ­
в а н и е п е р е м е н н о й в п р о ц е сс е р а б о т ы п р о гр ам м ы . В сплы ваю щ ее
о кн о н е п о зв о л я е т н е п р е р ы в н о сл ед и ть за п е р е м е н н о й , н о в наш ем
случае о н о в п о л н е м о ж ет пом оч ь.
----------------- '
alert (callNxjm) ;
if (callNum = winningNum) (
a l e r t (caller + ” , caller number
callNum + "... todayX's
winner!");
NaN
aiiVimi1".(W
О уэн п о н ял , ч т о с т о ч к и зр е н и я с ц е н а р и я п е р е м е н н ы е callNum
и w inningNum р а в н ы н е с м о т р я н а то , ч т о сразу п е р ед о п е р а ­
т о р о м if п е р е м е н н ая callNum и м е е т зн а ч е н и е NaN. У ж е од н о
эт о н е совсем п о н я т н о , н о О уэн р е ш и л с н ач ал а п о с м о т р еть , ч то
п р о и с х о д и т вн у тр и о п е р а т о р а i f.
if (callNum - WinningNum)
(
alert(callNum);
alert(caller + ", caller number
Winner!");
form.submit ();
С разу после п р о вер ки усло ви я
п ер ем ен н а я callN u m п о л у ч а е т
значение 7.
Ш ТУРМ
Теперь, когда вы знаете, что переменная callNum
всего за одну строчку таинственным образом по­
лучила значение 7, как вы думаете, что стало при­
чиной этого?
522
глава 11
>^е.кущего звонка.
OiC
охота на ошибки
a v / ^ А
д к А
П Р И
п о м е а д и
И нтервью н ед ел и :
В спл ы в аю щ ее о кн о п р е з и р а е т д еф екты
Head First: Д о л ж ен п р и зн а т ь с я , я слы ш ал о вас
р а зн о е . Л ю ди го в о р я т, ч т о ч ас т о вы и х р а зд р а ­
ж аете. Н о п р и это м вы я в л я е т е с ь лучш им другом
о тлад чи ко в. Р асскаж и те, кем ж е вы я в л я е т е с ь на
сам ом деле.
Всплывающее окно: Д о л ж н о п р и зн а т ь с я , ч т о не
так-то п р о с т о р а б о тать, если п е р е м е н н а я м ен я е т ­
ся м н ого р а з, н а п р и м е р , в п р о ц е сс е в ы п о л н ен и я
ци кла.
Всплывающее окно: Э ти п е р в ы е п р о с т о н е н о р ­
м альн ы е. М не даю т и н ф о р м а ц и ю , а я ее о т о б р а ­
ж аю . К ак о й о т эт о го вред?
Всплывающее окно: К ак вы п о м н и те, я в сп л ы ­
ваю и уб р ать м ен я м ож н о т о л ь к о щ елчком . А если
я вспл ы ваю м н ого раз, нуж на ц ел ая с е р и я щ ел ч ­
ков.
Head First: Н о вы «всплы ваете». Т о ч н о т а к ж е,
как м н о го ч и с л е н н а я н ад о ед л и в ая реклам а.
Всплывающее окно: Т о есть, если п л о т н и к не
ум еет о б р ащ ать ся с м о л о тк о м , в и н о в а т м олоток?
Head First: Вы х о т и т е сказать, ч то вас использу­
ю т некорректно?
Всплывающее окно: И м е н н о так. Е сли м ен я за­
ставл яю т о т о б р а ж а т ь всю эту глупую реклам у, м не
это н е н р а в и тс я . Н о в ы б о р а у м ен я нет. В п р о ч ем ,
я думал, вы х о т и т е узнать, как и м е н н о я пом огаю
п роц ессу отладки .
Head First: Д а, и зв и н и т е . Т а к как ж е вы эт о де­
лаете?
Всплывающее окно: О ч е н ь п р о сто . С каж ем ,
п е р е м е н н о й н е ч а я н н о п р и с в аи в а ю т какое-то н е
им ею щ ее см ы сла зн а ч е н и е . П р о гр ам м и сту нуж но
о тсл ед и ть, как о н а м е н я е тс я п о м ер е р а б о т ы
с ц ен а р и я . И о н п р о с и т м е н я о т о б р а ж а т ь ее зн а ч е ­
н и я.
Head First: Н о каким ж е о б р азо м вы ум удряетесь
узнать зн а ч е н и е п е р е м е н н о й в р а зн ы е м о м ен ты
врем ен и ? Н а в е р н о е , это слож но...
Head First: П оч ем у же?
Head First: Тут вы п р авы . Н о ещ е я слы ш ал, ч то
вы м о ж ете б ы ть п о л е зн ы даж е в случаях, когд а не
тр еб у ется о т с л е ж и в ат ь дан н ы е.
Всплывающее окно: О , да. Сущ ествую т ситуа­
ц и и , когд а н ея с н о , в как о й м о м ен т в ы зы вается
ф р а гм е н т код а и в ы зы в ае тся л и вообщ е. И м е н н о
м оя п о м о щ ь п о зв о л я е т узн ать о том , ч т о в ы зо в
код а все-таки п р о ш ел успеш но.
Head First: И во в сех эт и х п ро ц ед у р ах отл ад к и вы
то л ь к о в р е м е н н ы й участник?
Всплывающее окно: И м ен н о так. Н о я н е в о з­
р аж аю . В к о н ц е ко н ц о в, у м ен я есть п о с т о я н н а я
р аб о та , а п ом ощ ь в отлад ке эт о так, н еб ол ьш ая
п о д раб отка.
Head First: С п аси б о за п о т р а ч е н н о е н а нас
в р е м я и за о б ъ я с н е н и е в аш ей р о л и в д ел е б о р ь ­
б ы с д еф е к т а м и кода. Н ад ею сь, м ы ещ е н е р а з
в с т р ет и м с я .
Thanks. See уа!
Всплывающее окно: В овсе н ет. Д о с та т о ч н о в ы ­
звать м ен я в нуж ны х то ч к а х с ц е н а р и я.
Head First: П о н и м аю . А стал к и в ал и сь ли вы с п р о ­
б лем ам и в п р о ц е сс е т а к о й работы ?
далее ►
523
это логично?
Некорректная логика
О уэн н ато л кн у л ся н а ло ги ч еску ю ош ибку. Т о е сть код с о в е р ш ен ­
н о к о р р е к т е н с т о ч к и зр е н и я я зы к а Jav aS crip t, н о д ел ает совсем
н е то , ч т о д о л ж ен д елать. В д ан н о м случае вм есто == введ ен о =,
и в р езу л ьтате в м есто с р а в н е н и я двух п е р е м е н н ы х п е р е м е н н о й
c a llN u m п р и с в аи в а е тс я зн а ч е н и е п е р е м е н н о й w in n in g N u m .
С виду коррект ны й код
на сам ом деле несет
о себе т рудно обнару­
ж иваемую ошибку.
______ у»
if
{callNum(^winningNum)
{
З ам е н и в = н а = =
if
(callNum ==
winningNum)
{
Мы изёавим ат ощ ’
ош ибки # ^ .
Т а к и е о ш и б ки н е о б н ар у ж и ваю тся б р ау зер ам и . И н т е р п р е т а т о р
Jav aS crip t в ы п о л н я е т свою работу, возвраш ,ая п р и с в о ен н о е п е р е ­
м е н н о й w in n in g N u m зн а ч е н и е , к о т о р о е затем а в т о м а т и ч еск и п р е ­
о б р азу ется в зн а ч е н и е t r u e п р и п р о в е р к е усл ови я о п е р а т о р о м i f .
Д ру ги м и сл овам и, код н а п и с а н к о р р е к т н о , п р о с т о о н д ел ает н е то,
ч т о нам нуж но.
(
То есть логические
^ ошибки не распознаются
V
браузерами?
]
у
Логические ошибки — это как полет ниже уровня радара.
О с н о в н ая п р о б л ем а в то м , ч т о л о ги ч ес к и е ош и б к и в о т л и ч и е о т
о стал ь н ы х н е о б н аруж и ваю тся авто м ати ч еск и . П усть сооб щ е­
н и я о т б р ау зер а и вы гл яд я т пугаю щ е, п о к р а й н е й м ер е, о н и даю т
п р е д с та в л ен и е о том , где и ск ать ош ибку. А в о т с л о ги ч ес к и м и
о ш и б кам и вам п р и х о д и тс я б о р о т ь с я уж е б ез под сказок.
С д ругой ст о р о н ы , т а к и е о ш и б ки п р и в о д я т к н е к о р р е к т н о й
р а б о т е с ц ен ар и я . Н а п р и м е р , есл и п р и ч и н о й стал а н е и н и ц и а л и ­
зи р о в а н н а я п ер е м е н н а я , с о о б щ ен и е « u n d e fin ed » п о к аж ет, ч то
и м е е т м есто п о п ы тк а со сл аться н а такую п ерем енн ую . Т ак ч то
в о х о т е н а л о ги ч ес к и е о ш и б ки так ж е ес ть свои т о н к о с т и и х и ­
т р о с ти .
524
глава 11
охота на ошибки
КЛЮЧЕВЫЕ
МОМЕНТЫ
Синтаксическими называют
ошибки, нарушающие правила
языка иауаЗопр!. Они обнаружи­
ваются браузером.
В НТМ1-атрибутах обработчи­
ков событий, содержащих код
иауаЗспр!, нужно использовать
как кавычки, так и апострофы.
Количество открывающих и за­
крывающих апострофов и кавы­
чек должно совпадать.
Всплывающие окна можно ис­
пользовать для отслеживания
значения переменных.
В операторе проверки условия
часто используют = вместо
==, что становится причиной
ошибки.
часш°
задаваем ы е
БоЦ роС Ь!
В роли esc-символов могут
выступать только кавычки
и апострофы?
; Нет, в JavaScript поддерживаются
и другие esc-символы. Например, вот так
\t в строку вставляется табуляция.
Знак
переноса строки представлен символом
\ п . А так записывается обратная косая
черта \ \ .
и ничего больше. KaKoif бы символ вы
ни применяли для обозначения начала
при ссылке на неопределенную
переменную или функцию?
из JavaScript как значение атрибута.
Вы можете вставлять эти символы
0 ; Неопределенной называется
переменная, которая или не была
создана, или же ей забыли присвоить
начальное значение. В обоих случаях
ее значение воспринимается как
в HTIVIL-атрибуты при условии, что они не
конфликтуют с символами, указывающими
на границы атрибута. Ведь значения
атрибутов обработчиков событий не
интерпретируются, как код JavaScript.
Эти символы часто применяются для
форматирования текста во всплывающих
окнах. Символы \
t и \п выравнивают
текст и разбивают его на строки.
3 * Почему ограничено использование
esc-символов в HTML-атрибутах?
Q ; Дело в том, что HTML-атрибуты не
подчиняются правилам JavaScript в том,
что касается символов, ограничивающих
значение. Вы можете использовать escсимволы в строках JavaScript, входящих в
HTML-атрибут, но те же самые символы
при этом могут применяться для
обозначения границ атрибута.
С точки зрения HTML атрибут — это
значение, которое появляется между
кавычками или апострофами.
Что именно происходит
атрибута, следующий аналогичный
символ будет указывать на его конец.
Ведь HTIV1L не обрабатывает esc-символы
неопределенное. Поэтому попытки
прочитать его и проделать с ним
какие-то операции не имеют смьюла,
и JavaScript создает сообщение об
ошибке. Аналогичная ситуация возникает,
если при вызове функции интерпретатор
JavaScript не может ее обнаружить. Вызов
неопределенной функции не имеет
смысла, и вы снова получаете сообщение
об ошибке.
Существуют ли отладчики
иауа8сг1р1, предоставляющие
подробный контроль процесса
получала значение
отладки?
проверкой условия в операторе
; Да, такие отладчики бывают.
И наверное, вам имеет смысл
попробовать их в деле. Однако
хорошая манера написания кода вкупе
с изученными в этой главе методиками
отладки способна помочь вам в создании
Почему переменная callNum
NaN перед
1 f?
! Мы этого не знаем. Можно только
сказать, что с кодом все еще что-то не
в порядке. А значит, нужно продолжать
отладку...
сценариев, не содержащих ошибок.
далее >
525
синтаксическая ошибка и логическая
Беседа у камина
Синтаксическая и логическая ошибки обожают плохие сценарии.
Синтаксическая ошибка:
Логическая ошибка;
Э й, я т е б я знаю . Н асл ы ш ан а о тв о ем к о в а р ­
стве. Н о л ю б и ш ь л и т ы п л о х о н а п и с а н н ы е
с ц е н а р и и так ж е, как лю блю и х я?
О да! Н е т н и ч е го лучш е с ц е н а р и я , к о т о р ы й
н а п е р в ы й взгляд в ы гл яд и т к о р р е к т н о , н о н а
сам ом дел е п е р е п о л н ен ош ибкам и.
Н е т , н ет. Я п р е д п о ч и т а ю с ц е н а р и и , п р о ­
б лем н ы е даж е с виду. Я там вы деляю сь. М ои
с е с тр ы р а зб р о с а н ы п о всем у сц ен ар и ю ,
и б р ау зер г а р а н т и р о в а н н о будет возмуш;ен.
Н е м огу н е о ц е н и т ь тв о е х и тр о у м и е, н о ведь
т ы допускаеш ь р аб о ту сц е н а р и я . А я н а это
п о й т и н е могу. С ц е н а р и й в о о б щ е н е д о л ж ен
р а б о та ть . Н и как.
Э то да. Н о к со ж ал ен и ю , п р и ч и н я е м ы й
нам и в р ед весьм а о гр а н и ч е н . П о р т и т ь веб ­
с т р ан и ц ы , не д авая им к о р р е к т н о р а б о т а т ь
в есело , н о б ольш е никуда у нас доступа нет.
В от есл и бы нас пустили п а ж е с т к и й диск,
п о л н ы й в аж н о й и н ф о р м а ц и и !
И ч т о тут веселого? Все зн аю т, ч т о удары
и сп о д ти ш ка б о л ее эф ф е к т и в н ы . П усть
п о л ьзо в ат ел ь думает, ч т о все в п о р я д к е, в то
в р е м я как т о там , то зд есь н ачнут в о зн и к а ть
н еб о л ьш и е п р о б л ем ы . И есл и как следует п о ­
ст ар ат ься , п о л ь зо в а т ел ь вооб щ е задум ается
о том , р а б о т а е т л и его браузер.
А ведь эт о м ы сль. Ж а л ь , ч т о я сам а п е до­
думалась о с тан ав л и в ать раб о ту с ц е н а р и я так
ж е, как и ты . И л и даж е вы зы в ать п ад ен и е
б раузера. В от б ы ло бы здорово!
Д а, эт о б ы ло б ы п о тр ясаю щ е. А ты уверен а,
ч т о н ам н и к а к н е л ьзя туда п рон икн уть?
526
глава 11
охота на ошибки
Синтаксическая ошибка;
У вы , и н т е р п р е т а т о р Jav aS crip t д е р ж и т нас
креп ко .
Логическая ошибка;
Н и ч его . В есел и ться это нам н е меш ает.
Я р асск азы в ал а теб е п р о м ал ен ьки й ф окус
с о п е р а т о р а м и = и ==?
Н ет. А как он рабо тает?
П р о гр а м м и с т х о ч е т н а п и с ать == и с р ав н и т ь
д ва зн а ч е н и я , н о случайн о вво д и т = и вм есто
эт о го в ы п о л н я е т п р и с в аи в а н и е. А по то м
си д и т часам и, п ы та я сь о т ы ск а ть к о р е н ь зла.
И д аж е и н т е р п р е т а т о р Jav aS crip t н е м о ж ет
ему п о м о ч ь, потом у ч то т е х н и ч е с к и код со ­
в е р ш ен н о к о р р е к те н .
И как т ы вы х о д и ш ь сухой и з воды?
У м е н я м н ого сп особ ов. Э то т ак зд о р о в о , не
наруш ая закон а, п р и ч и н я т ь массу н е п р и я т ­
н о стей .
У м ен я в ар с е н а л е т о ж е е с ть п о д о б н ы е т р ю ­
ки. С каж ем , когд а п р о гр а м м и с т за б ы в ае т п о ­
ст ав и ть в к о н ц е о п е р а т о р а то чку с за п я т о й .
Э то н е к р и т и ч н о для и н т е р п р е т а т о р а , и все
р а б о т а е т , п о к а каж ды й о п е р а т о р н ах о д и тся
н а с в о е й стр о к е . Н о в о т п о п ы тк и « о п ти м и ­
зи р о в ать» код и со е д и н и т ь о п е р а т о р ы в одну
стро чк у п о зв о л я ю т м н е как следует п о в е с е ­
литься!
Т ы н а п о м н и л а м н е одну и з м ои х л ю б и м ы х
ш уток. О б ож аю , когд а п р о гр а м м и ст р е ш ае т
п о м е н я т ь аргум ен ты уж е н а п и с а н н о й ф унк­
ц и и . П р и это м о н ч асто заб ы вает о б н о в и т ь
все в ы зо в ы э т о й ф ун кц и и . И н т е р п р е т а т о р
н и ч е г о н е зам еч ает, и п р о гр а м м и ст получает
н ео ж и д а н н ы е резу л ьтаты из-за н е в е р н о го
сп и ск а аргум ентов.
Н о есл и и н т е р п р е т а т о р вдруг ч то-то зам е­
ч ает, в р або ту вклю чаю сь я и о ш елом ляю
со о б ш ен и ем об ош иб ке. Э й, а ведь нам и м еет
см ы сл р а б о т а т ь в ком анде. Т ак м ы см ож ем
п р и ч и н и т ь н ам н о го б ольш е вреда.
С огласна! Д авай т а к и сделаем .
Я следую за тобой !
далее >
527
ош ибочное радио
Проигрывают 8се! (Ошибка # 4 )
О уэн н а ч и н а е т п о н и м ать , ч то р а б о т а о тл ад ч и к а дал ек о н е т ак п р о ста,
к ак ему сн ач ал а п о к азало сь. И с п р а в и в л оги ч ескую ош ибку в о п е р а т о р е
, о н о б н аруж и л, ч т о т е п е р ь с ц е н а р и й во о б щ е н е о б ъ я в л я е т п о б ед и те­
л я. Е сли р ан ь ш е у нас в ы и гр ы в а л каж ды й п о зв о н и в ш и й , т о т е п е р ь все
п р о и гр ы в а ю т. Э то м о ж ет н е га т и в н о п о в л и я т ь н а сам ооц ен к у слуш ателей,
п о это м у ош ибку следует у стр ан и ть как м о ж н о ско р ее.
в ае..
528
81 Casвг Wtn
глава 11
Звонок 3.
охота на ошибки
А така Всплывающих окон
О уэн п ы т а е тс я п р о с л е д и т ь за зн а ч е н и е м п е р е м е н н о й c a llN u m .
О н п о п ы та л с я в с тав и ть н е с к о л ьк о в сп л ы ваю щ и х о к о н в р а зн ы е
ч ас т и кода, в р езу л ьтате о казал ся за в а л е н о кн ам и с п р а к ти ч е с к и
б есп о л езн о й и н ф о р м а ц и е й . И т е п е р ь о н п р о с т о н е зн ает, ч т о
п р е д п р и н я т ь дальш е...
При наличии по вт о р я ю щ его ся
кода п о п ы т к и от слеж иват ь
значение п ер ем ен н о й пр и п о ­
м о щ и всплы ваю щ его окна п р и ­
водят к п о я вле н и ю больш ого
числа окон.
^
По м е р е у в е л и ч е ­
ния числа звонящ их,
п ер ем ен н а я callN um
дем онст риру c m п о лн ы й с п е к т р
ст р а н н ы х значений.
Было бы здорово, если бы следить
за переменными можно было без
всплывающих окон...
\
У
далее >
529
нет ли для этого консоли?
Отладочная консоль браузера
Б о л ьш и н ств о б р ау зер о в и м ею т отлад очн ую ко н со ль, н а к о т о р о й о т о б р а ­
ж а е т с я и н ф о р м а ц и я о содерж аш ;ихся в с ц е н а р и и ош ибках. Э то т и н стру­
м ен т п о зв о л я е т п о н я т ь , ч то и м е н н о н е т а к с ваш и м сц ен ар и ем . К ак вы уже
убедились, лучш е всего и с п о л ь зо в ат ь к о н со л ь б р ау зер а F irefox.
SyntijiErf®'СаіїЧем!
д.-»'
tsij
ass
1«
Консоль ошибок прекрасно
указы ваем на о ш й к ^ щ Т н а cm i ^
^^^^^^aкcuчe-~
Мы п о ла га е м ся на
консоль ошибок
браузера Firefox.
А как консоль ошибок
поможет мне проследить
за значением перемен­
ной?
•Л .«......
В л.
*»
Efrors «аггйпв» ws*“9«‘
£№»віічо«*(ІПа**япм«і«яп«і
Консоль ошибок не позволяет следить
за переменными.
К со ж ал ен и ю , п р и всех сво и х достоинстваих эту
задачу ко н с о л ь о ш и б о к р е ш и т ь н е п о м о ж ет. Н о
вам н и к т о н е м еш ает со зд ать свою собственн ую
ко л со л ь, п р ед н азн ач ен н у ю и м е н н о для о тсл е­
ж и в а н и я зн а ч е н и й п ер ем ен н ы х .
530
глава 11
E r ro r C e n s o te
»
Oear
,
охота на ошибки
Пользовательская консоль
Т акая задача, как со зд ан и е со б с т в е н н о й к о н со л и , м о ж ет сн ач ал а
п о к азаться с л о ж н о й , но ведь нам всего л и ш ь нуж но п о зап р о су о т о ­
б р аж а ть о п р е д е л е н н ы й текст. П р о с т о о тл а д о ч н ая п а н ел ь до л ж н а
д ел ать эт о н е в о тд ел ьн о м о к н е, а н е п о с р е д с тв е н н о н а ст р ан и ц е .
В сплы ваю щ ее о к н о неудобн о потом у, ч т о п о л ьзо вател ю п о с т о я н н о
п р и х о д и тс я щ ел к ать н а к н о п к е О К , ч то б ы его зак р ы ть.
В51 Са$е 2: Winп'шg СаНе^
00в
О
Сообщения от ла д чи ка
от ображ аю т ся в с м ц и а л ш о й об ла ст и в нижней
ч а ст и ст раницы .
оаИНшл! 1
В каждой ст р о ч ке
о т д ельн о е сообщ ение
о т лад чика.
►с а И Н о т г
оаХ Ш чв!
саИ Н аи!
оаИ Н чт:
2
3
4
5
Возьми в руку карандаш
Представьте конструкцию консоли, позволяющей отображать список
сообщений отладчика в динамически создаваемой области страни­
цы. Нарисуйте, из каких компонентов она должна состоять и как они
соединяются друг с другом и со специальным объектом JavaScгipt,
который и представляет собой консоль.
далее *
531
реш ение упражнения
Возьми В руку карондаш,
Решение
О т ла д о чн а я консоль
п р е д с т а в л я е т содой
о б ъ ект D e b u g C o m o k,
обладаю щ ий одним
сво й ст во м и одним
м ет о д о м .
Вот из каких компонентов должна состоять консоль, позволяющая
отображать список сообщений отладчика в динамически создавае­
мой области страницы.
DebugConsote
. Каждый вызов мет ода сИ5р1ауМ5д() приводит
к появлению новой ст р о ч ки на консоли.
Сама консоль на ст р а н и ц е с о з­
д ает ся п р и п о м о щ и т е га div.
Л огическое свойст во
sh a d e d м е н я е т свое
значение с tr u e на
raise и обрат но для
каждого следую щ его
сообщ ения, м ен я я ■
пр и э т о м ф оновы й
цвет .
В нут ри т ега div,
определяющ его вид
ИТМ и -э л е м е н т ы для
от ладочной област и
динам ически с о з д а ю т ­
ся ко нсо лью , т о е с т ь
п о л ь зо в а т е л ю не нужно
п и с а т ь никакого с п е ц и ­
ального Н Т М и-кода для
поддерж ки консоли.
консоли, располож ены
дочерние т е ги d iv для
от ладчика.
"callNum:
532
глава 11
от дельны х сообщений
div
2'
охота на ошибки
Магниты JavaScript
в коде отладочной консоли отсутствуют несколько фрагментов.
Заполните пробелы магнитами таким образом, чтобы получить
объект В еЬ и дС оп зоХ е.
function DebugConsoleO
//
Создание
области
{
отладки
);
var
consoleElem
consoleElem.id
=
=
document.
"debug";
c o n s o le E le m . style. f o n t F a m . l y = m o n o s p a c
consoleElem.style.color -
•
,
#333333 ,
(consoleElem);
document.body.
//
создан и е
( " h r " ) );
(document.
consoleElem.
с .о й с - .а ,
this.
у п р а .л я т е г о
и з м е н е н и е м ф о н о .о г о
цвета
= false;
}
DebugConsole.prototype.displayMsg
// С о з д а н и е с о о б щ е н и я
var msgElement = d o c u
m e n t
=
function(msg)
.c r e a t e E l e m e n t ( d i v
{
),
msgElement. a p p e n d C h i l d (d o c u m e n t............................................) "#FFFFFF”
n ^ s g E l e m e n t . s t y l e . backgroundColor
var
consoleElem
=
d o c u m e n t
изменение
this.shaded
значения
=
this.shaded
7
"#EEEEEE"
:
.g e t E l e m e n t B y l d (...............)''
consoleElem. a p p e n d C h i l d (
//
=
............
свойства,
лтпявпяюшего
управляющего
изменением
из
фонового
цвета
this.shaded;
msgElement
appendChild
"debug''
createElement
createTextNode
далее ►
533
решение задачи с магнитами
Решение задачи с магнитами
Вот каким образом нужно было расположить магниты, чтобы по­
лучить код объекта О еЬ и д С о п зо 1 е.
function
//
DebugConsoleO
Создание
var
области
consoleElem
consoleElem.id
=
=
{
отладки
createElement
document.
"debug"
c o n s o l e E l e m . s t y l e .c o l o r
appendChild
consoleElem.
11
Создание
this.
=
свойства,
shaded
к
=
"monospace
»consoleElem);
document
управляющего
т false;
,
"# 3 3 3 3 3 3 ";
appendChild
d o c u m e n t .b o d y .
div консоли добавляется
т ело докум ент а, поэт ам и
Консоль появляет
п о я вля ет ся
с я в нижней
части ст раницы
Гег
c o n s o leElem. style. f o n t F a m i l y
ichr"));
createElement
I
изменением
фонового
цвета
^
^ ницы.
DebugConsole. p r o t o t y p e . d i s p l a y M s g = f u n c t i o n ( m s g )
{
// С о з д а н и е с о о б щ е н и я
v a r m s g E l e m e n t = document .c r e a t e E l e m e n t (" d i v " );
m s g E l e m e n t .a p p e n d C h i l d ( d o c u m e n t .
msgElement.style.backgroundColor
var
consoleElem
=
createTextNode
=
this.shaded
document.getElementByld
.
Иербыи дочерний э л е м е н т
— го р изон т аль-
Н ачальное значение
false с о о т в е т с т в и е т
(msg) ) ;
белому ц ве т и ф она
ее от ост альной с т р а Сообщения
добавляются
на консоль
в дочерних
т егах div.
; "#EEEEEE"
; "#FFFFFF";
"debug
c o n s o l e E l e m .a p p e n d C h i l d ( ~ m s ^ ^ ^ n t j | ) ;
/ , изм енение 3 » a . e „ , с . о й с т . а , у о р . . . я „ е г о „ з м е н ,» д е „ ф он»„го^ц^^^
th is .s h a d e d -
' | ; h i s .s h a d e d ;
/
чередуются.
}
534
глава 11
черт
охота на ошибки
Отладка отладчика
О уэн н е м о ж ет д о ж д аться м о м ен та, когд а н о в ая о т л ад о ч н а я ко н со л ь
п о зв о л и т ему п о н я т ь , ч то ж е н е так со с ц е н а р и ем о б р а б о т к и зв о н к о в
н а рад и о . О н и м п о р ти р у ет в стр ан и ц у ф а й л d e b u g . j s и со зд ает о б ъ ек т
DebugConsole в заго л о вке.
<script
//
t y p e = " t e x t / j a v a s c r i p t ">
Глобальная
var
console
=
переменная
new
отладочной
консоли
Э т о т код создает
в заголовке ст раницы
о б ъ ек т DebugConsole как
глобалш ун? п е р ем ен н ую .
DebugConsoleO;
r ^ ~ ~ - _________
К со ж ал ен и ю , п л ан ам н е суж дено сбы ться. П е р в а я п о п ы тк а
и с п о л ь зо в ан и я к о н с о л и п о к а зы в а ет, ч т о О уэн т о л ь к о увел и ч и л
ч и сл о п р о б л ем , д о б ав и в с о в е р ш е н н о н о в ы е ош иб ки.
■Д
_____ _ ____
S i
Alt ? Errors
ch
Error Con ole
ÿ
Messages
CD
J
Clear
Evaluate
Q ïwoKdocumenbboiJy has по properties.
Куда же пропали свойства
тела документа? Ведь имен­
но в них хранится содержи­
мое веб-страницы.
■■
К аж ет ся,
в сценарии
появилась
совсем н о вая о ш и б ­
ка...
б р а у з е р сообщ ает , ^ т о в т е л е до
к у м е н т а о т с у т с т в у ю т свойст ва.
С тавш ая п р и ч и н о й о ш и б к и с т р о ч к а код а д о б а в л я е т к телу до­
кум ен та д о ч е р н и й узел ( d i v ) , ч то п о и д ее н е д о л ж н о созд авать
н и к а к и х п р о б л ем .
document.body.appendChild(console);
П о л у чается, ч т о чего-то н е х в а т а е т и эт о ч то-то св я за н о с н о ­
вы м о б ъ е к то м DebugConsole.
Ш ТУРМ
Что могло стать причиной отсутствия свойств
в теле документа?
далее >
535
как ут екает время...
За го ло во к ст раницы
загруж ает ся перед
ее т е л о м , п о э т о м у
содерж имое п о с л е д ­
него в э т о т м о м е н т
недост упно.
0)кидание загрузки
П р о б л е м а с о т л а д о ч н о й ко н со ль ю с в я за н а с в р е м е н е м загрузки
с т р а н и ц ы и м о м ен то м , когд а код с ц е н а р и я п ол уч ает доступ к ее
содерж им ом у.
Н Т М и -злем ен т ы ст ра­
н и ц ы загруж аю т ся
т о ль к о п р и з а г р у з к е ,
т е л а , по сле з а г р у з к и з а ­
головка.
<tltle>BSI Case 2- WH
■
• " “ "i n g C a U e r < / t i t l e >
<3cript t y p e - t e x t / j a v a s c r i p t " s r c - ’d.h
•
avascript ">
обальная переменндо
function checkwlnnpr<f
// У величение
,
var callNum;
звонка на единицу
++callNum;
// П роверка п обедителя
form.submitO;
'
"“"Ьег
callNum
today\’s winner!");
else
{
» f —
s : : ~ г г
~ » .
c a l lerField.select o';
<body>
___
<form name="callform” a
c
t
,
.
'
'
--- --------
-tbod...posT..>
"'oncLc\"-":?“r ° " ’'
</html>
------- —
type...te«.. />
____ _____
Т®^а8сг1р1 в заголовке не имеет доступа к содержимому
страницы.
Т ак как сн ач ал а загруж ается заго л о в о к и т о л ь к о п о то м все
о стал ьн о е, коду с ц е н а р и я н е д о л ж ен т р е б о в а т ь с я доступ
к Н Т М Ь -элем ен там в т е л е с т р ан и ц ы . Э то о г р а н и ч е н и е м о ж ет
п о к а заться ст р ан н ы м , н о о н о и м е е т см ы сл, есл и в с п о м н и ть, ч то
п р а к т и ч е с к и весь код запускается и м е н н о в заголовке.
536
глава 11
охота на ошибки
А что по поводу функ­
ций в заголовке? Они
тоже не работают?
Н е весь содержащийся в заголовке страницы код
выполняется там же.
П о м е с т и т ь ко д ф у н кц и и в за го л о в о к с т р а н и ц ы вовсе н е о зн ач а ­
е т зап у сти ть ее там —ф у н кц и я запускается т о л ь к о п о сл е ее вы ­
зова. А во т код, п о м е щ е н н ы й в за го л о в о к вн е ф у н кц и и , запуска­
е т ся сразу ж е п о сл е загрузки заголовка. И м е н н о эт о с т ан о в и т с я
п р и ч и н о й пр о б л ем .
О б ъ е к т DebugConsole н е л ьзя бы ло со зд авать в заго л о вке, т а к
как его ко н стр у к то р за в и с и т о т со д е р ж и м о го в т е л е с тр ан и ц ы .
реш ение упражнения
Возьми в руку карандаш
Решение
Вот когда следует создать объект DebugConsole, чтобы
гарантировать его доступ к элементам страницы.
.БМУШ .ИШ Зывает нй .окончание
И ? . . § . .Ü
?
.
оЫРЛ4.-. .Имен .?.-^?.' Сл создават ь о б ъ ект
console САедуеп% о с т а в и т ь
в за го ло вке ст р а н и ц ы , ведь о б ъ е к т я вля е т ся глобальны м — к о н ­
с т р у к т о р о б ъ е к т а б уд ет вы зван т о ль к о после собы т ия onload'......
^ МениВ
со^данигг
<body onload="console = new DebugConsole (); ">
ош и б ку, с Б я ЗанЕ^іо с KoHcojTbjo
__ __________ Т е п е р ь п о являет ся
ß о т в е т на собы т ие
onload.
Самая проти8ная ошибка
Ошибки при выполнении
возникают при
определенных условиях
во время работы сценария.
П р о б л е м а с н езагруж аю щ и м ся тел о м д окум ен та о т н о с и т с я
к о ш и б к а м п р и в ы п о л н е н и и —т а к и е о ш и б ки п о я в л я ю тся
то л ь к о п р и о п р е д е л ен н ы х услови ях во в р е м я р а б о т ы с ц ен ар и я .
П о д услови ям и м о ж ет п о д р азу м еваться и ввод п о л ьзо в ател ем
о п р е д е л ен н ы х д ан н ы х и л и о п р е д е л е н н о е ч и сл о п о в т о р е н и й
ци кла. О ш и б к и п р и в ы п о л н е н и и с л о ж н о об н аруж и м ы , потом у
ч т о и х н е в о зм о ж н о п р ед сказать. И н о гд а п р о б л ем о й я в л я е т с я
д аж е в о с п р о и зв е д е н и е о ш и б ки , н а ко то р у ю ж алуется
п о л ьзо вател ь.
Error Console
вв©
Hj
в
‘ All ■ Errors
їй
!,
warninas
Mtss«e«s
Oear
[ Evaluate
„
f r r o c diicumentiKHiy
^ sour»file,
538
глава 11
no proiaertits
^
tins:
t
П роблем а с консолью
о т лад ки от н о си ла сь
к ош ибкам п р и в ы п о л ­
нении и была вызвана
п о п ы т к а м и до ст уп а
к ещ е незагруж ен­
ны м данны м. Подобные
п ро б лем ы во зн и к а ю т
т о ль к о в процессе р а ­
бот ы сценария.
охота на ошибки
Три самых популярных типа ошибок
В м есте с о ш и б кам и п р и в ы п о л н е н и и л и д и р у ю т в Jav aS crip t еш;е два
т и п а уже и зу ч ен н ы х нам и ош ибок: с и н т а к си ч е ск и е и л о ги ч еск и е. О н и
могут п о я в л я ть с я в с ц е н а р и я х как вм есте, т а к и по отд ел ьн ости ! Д ля
их усп еш н о го р а с п о зн ав а н и я и у с т р ан е н и я нуж но п о н и м ать разн и ц у
между ним и.
Синтаксические
В о зн и каю т п р и н ару ш ен и и п р ав и л
я зы к a Jav aS c rip и дел аю т код н е п о ­
н я т н ы м д ля и н т е р п р ет а т о р а .
При Выполнении
В о зн и каю т в п р о ц е сс е р а б о ты
сц е н а р и я , н а п р и м е р , п р и вводе
п о л ьзо в ател ем д ан н ы х , к о т о р ы е
н ев о зм о ж н о о б р аб о т а ть , и л и п р и
п о п ы тк е д оступа к ещ е н е со зд ан ­
ном у объекту.
<html>
<head>
2; Winning Caller</title>
<title>BSI case
"debug. js"X/script>
ript type="text/Javascript"
:="text/javascript"
<script type^
;~nehua conaole global
----console * new D e b u g C o n s ^ О ;
7
// Total number of calls
var callNum = 0;
Логические
В ы зван ы н е в е р н о й л о ги к о й
и в о сн о в н о м св я за н ы с кодом ,
к о т о р ы й д о л ж ен в ы п о л н я т ь одну
о п е р ац и ю , н о д ел а е т что-то дру­
гое. И н о гд а м огут б ы ть обусловле­
ны тем , ч то п р о гр а м м и с т с сам ого
н а ч ал а н е в е р н о п о н я л задачу.
нение
function checkwinner(form caller;
// Increment the call number
winningNum)
var callNum;
++callNum;
con s o l e . displayMsg C'callNum;
allNum ) ;
a...dinner
^ I N u n . . "... t o d a y s wlnne.l");
a l e r t (caller
form, submit 0 ;
I
Какому типу ошибки соответствует каждое из описаний.
О тсу тстви е ско б о к вокруг усл ови я в о п е р а т о р е i f .
П е р е м е н н о й c o u n t e r н е п р и с в о е н о н а ч ал ь н о е зн а ч е н и е 0. .
Ц икл, повторяю щ ий ся после последнего элем ента массива.
О тсу тстви е закр ы в а ю щ е й ф и гу р н о й скоб ки у ф ункц ии.
далее *
539
реш ение упражнения
ПраЖ НгН Иб
типам ош ибок соответствуют данны е описания:
решение
Синтаксическая
О тсу тстви е ско б о к вокруг усл ови я в о п е р а т о р е i f .
П е р е м е н н о й c o u n t e r н е п р и с в о е н о н а ч а л ь н о е зн а ч е н и е 0.
Логическая
Ц и кл , п о в т о р я ю щ и й ся п о с л е п о сл ед н его эл е м е н т а м ассива.
.
О тсу тстви е закр ы в а ю щ е й ф и гу р н о й ско б ки у ф ункц ии.
Почему номер звонка
отображается как
«не-число»...
Э то не-чисАо
Т е п е р ь , когд а к о н со л ь отл ад к и г о то в а и к о р р е к т н о р аб о т а ет ,
п р и ш л о в р ем я в ы я сн и т ь , ч то ж е н е т а к с н аш ей п е р е м е н н о й
c a llN u m . Эту проб л ем у Оуэну д авн о уже сл едовал о р еш и ть. П е р е ­
м ен н а я c a l l N u m о т о б р а ж ае т с я как NaN, т о е с ть и м еет н еч и сл о в о е
зн а ч е н и е. В от т о л ь к о почему?
console.displayMsg("callNum:
Эта ст рочка
задает слежение
за переменной
" +
callNum)
CD
BSI Case 2; Winning Cailer
^ М З ..о
callNum.
По крайней м ере,
консоль отладки
работ ает !
540
глава 11
Caller палю; |Next caller
callMums
caiiNums
callNums
callNumt
саІІЯиш:
KaK
HaH
HaN
NaN
NaS
Call
охота на ошибки
Когда сАе)кения недостаточно
И н о гд а о т с л е ж и в а н и е з н а ч е н и й п е р е м е н н о й п р и н о с и т
б ольш е в о п р о с о в , ч ем о т в е то в . Н у почем у п е р е м е н н ая
c a l l N u m н е я в л я е т с я числом ? П о ч ем у ее зн а ч е н и е н е
у вел и ч и в ается н а еди н и ц у п р и каж дом следую щ ем зв о н ­
ке? З а ч е м нуж на к о н со л ь отлад ки , есл и о н а всего л и ш ь
п о д тв ер ж д а е т т о , ч т о м ы и т а к зн аем , т о е с ть т о т ф акт,
ч то у н ас п р о б л ем а. И как нам н а й ти п р и ч и н у т ак о го п о ­
веден ия?
А теперь что?
А может быть, начать
удалять код, пока номер
звонка не начнет менять
свое значение.
Удаление кода позволяет упростить сценарий.
П р и о тлад ке с ц ен ар и е в Jav aS crip t б ы в ае т и так,
ч то д ей ству ет п р ав и л о «чем м ен ьш е, тем лучш е».
В от и в д ан н о м случае и м е ет см ы сл удалять ф р а г ­
м ен ты ко д а и с м о тр е т ь, ч т о п олучается. Х отя
н а сам ом д ел е н ам нуж ен всего л и ш ь сп особ н а
в р ем я д еа к ти в и р о в а т ь код, а н е удалять его. Ведь
п осл е за в е р ш е н и я о тлад ки с ц е н а р и й ж ел ател ьн о
в о сс та н о в и т ь в п е р в о н ач ал ь н о м виде.
далее *
541
испорченный комментариями
Комментарии
Д е а к т и в и р о в а т ь код в п р о ц е сс е о тлад ки л е гч е всего,
п р е в р а т и в его в к о м м е н т а р и и . И м е н н о э т о т сп особ д ает
во зм о ж н о сть и зо л и р о в а т ь ош ибку.
function checkwinner(form, caller, winningNum)
console.displayMsgC'callNum; " + callNum);
Комментарии позволяют
на время деактивировать
фрагменты кода.
{
/*<=-------
// Increment the call number
var callNum;
++callNum;
// Check for a wil iner
if (callNum == wil' ningNum) {
caller number
alert(caller +
winner!");
form.submit();
callNum
today\'S
}
else {
// Reset the caller field for the next caller
var callerFieLfi = document.getElementByld('caller );
callerField.^lue = "Next caller";
callerFielcVfocus 0 ;
callerField.select 0;
)
*/ « )
Э т о т м но го ст р о чны й
ком м ент арий о т к л ю ­
ч а е т весь код ф ункц и и
за и с клю ч ен и ем ст р о чки
от ображ аю щ ей сообщ ение
от лад чика.
П ерем енная саНЫит
т еперь им еет
значение О, зн а ч и т ,
пр и ч и на п р о б лем ы
в о т к л ю ч е н н о м коде.
Ш Т У РМ
Что произойдет, если вернуть только строчку, увели­
чивающую значение переменной на единицу?
542
глава 11
Теперь номер звонка показан как 0.
Значит, именно фрагмент изолиро­
ванного кода становится причиной
появления значения NaN.
охота на ошибки
Проблема ка)кется решена
П е р е й д я о т м н о го с т р о ч н ы х к о м м е н т а р и е в к о д н о с тр о ч н ы м ,
м ож н о в ы б о р о ч н о п о д о й т и к о тк л ю ч ен и ю кода. П о сл е д обавл е­
н и я с т р о ч к и , у вел и ч и ваю щ ей зн а ч е н и е п е р е м е н н о й c a llN u m
н а еди ниц у, все н а ч и н а е т р а б о т а т ь как нуж но. З н ач и т , п р о б л е ­
м а с о д е р ж и т с я где-то в о тк л ю ч е н н ы х с т р о ч к ах кода.
function checkwinner(form, caller, winningNum)
console.displayMsg("callNum: " + callNum);
О дност рочны е к о м м е н т а ­
рии п о зв о л я ю т о т к л ю ч а т ь
и в к л ю ч а т ь обрат но о т - "
дельны е ст р о ч ки кода.
// Increment the call number
// var callNum;
++callNum;
-----------— ■"
e© 0
С нят ие значка к о м м е н т а р и я
с эт о й ст р о ч ки наконец ----- т о за с т а в л я е т п е р е м е н н у ю ^
ca llN um ко р р ект н о ф ункцио
пироват ь.
Check for
winner
if (callNum == winningNum) {
//
alert(caller + ", caller number
winner!");
11
p
{
//
+
callNum
today\'s
m Case 2: Wmning Caller
Id for the next caller
iment.getElementByld('caller');
iext caller";
Т еперь значение п е р ем ен н о й
callN um увели ч и ва ет ся на
единицу при каж дом звонке,
как и п р ед п о ла га ло сь с с а м о ­
го начала.
далее ►
543
реш ение упражнения
Возьми В руку карандаш,
Решение
Вот что было не так с переменной callNum.
6
.с л у н а й т . ш М н л .ф;ш . о.днл,. локялшйя ш р.е. .М^ат^.Она<<перекр_ы6ае^
м ^_ еш н н ую _ callN um .
Ч . 9 . > . и н и ц и а л и з и р о в а н а ,
увеличе-
^ >^олАе^ом-победит елем д ает в р е з у л ь ­
т а т е значение « n o t а n u m b e r» . Д л я исп р а влен и я ош ибки дост ат очно
у д а л и т ь с т р о ч к у , в ко т о р о й создает ся э т а перем енная.
//
У д ал ен и е c3nj>o4Ku,
со зд аю щ ей Л о к з д ь ^ ю
Увеличение
++callNum;
^ ^ е м е н і^ ю , у о п Р а н я е ш
ош ибку # 4 .
номера
\
звонка
на
единицу
Убрав э т у с т р о ч к у , в кот орой
случайно создает ся ло к а льн а я п е р е ­
м енная ca llN u m , м ы за с т а в л я е м
ф ун к ц и ю и сп о льзо ва т ь гло б а льн ую
перем енную callN um , ко т о р а я п р е д ­
по ла га ла сь с сам ого начала.
Два}кды объявленные переменные
П р и ч и н о й о ш и б ки в с ц е н а р и и о б р а б о т к и зв о н к о в стал а д в а ж д ы
о б ъ я в л е н н а я п е р е м е н н ая c a llN u m . Т а к а я п р о б л ем а в о зн и к ает,
когд а и м я л о к а л ь н о й п е р е м е н н о й дублирует и м я гл обал ьн ой . П р и
это м все и зм е н е н и я л о к а л ь н о й п е р е м е н н о й н и к ак н е о тр аж аю тся
н а с о с т о я н и и гл о б ал ь н о й — о н а как бы н а в р е м я с к р ы в а ет с я о т
сц е н а р и я.
Двойное объявление
возникает, когда
локальная и глобальная
неременные создаются
нод одним именем.
Глобальная
переменная.
Глобальный код
tcallNum;
Локальны й код
Локальная
++callNum;
перем енная.
Одно и т о '
же им я!
544
глава 11
Э т о т код на единицу —
ув е л и ч и в а е т гло бальную
перем енную , давая в р е ­
з у л ь т а т е 6.
Э т о т код у в е л и ч и в а е т на ед и н и т ло к а л ь н у ю п е р е м е н н у ю , давая
о р е з у л ь т а т е 1 — глобальная
п ер ем ен н а я п р и э т о м своего з н а ­
чения не м ен я е т .
охота на ошибки
Часзп'
'^ а Д а Б а е М ы е
БоЛ роС ь!
Б
А как понять, какие строчки кода следует превратить
в комментарии?
0 ; Вы научитесь отвечать на этот вопрос по мере роста
вашего опыта в отладке сценариев изуаЗспр!. Впрочем, обычно
имеет смысл изолировать большую часть или весь код вокруг
проблемной области. В случае больших проблем можно начать
с превращения в комментарии всего кода. Не забудьте также
удалить теги, импортирующие внешний код.
Если вы уже нашли содержащий ошибку фрагмент, используйте
другой подход. По очереди превращайте в комментарии строчки,
пока ошибка не исчезнет. То есть вместо отключения всего кода
и постепенного его включения до появления ошибки вы по
одной выключаете строчки, пока ошибка не исчезнет.
Первый подход применяют в случаях, когда непонятно,
где именно локализована ошибка, в то время как второй
используется после обнаружения дефектного фрагмента.
Б: Можно ли намеренно дважды объявить переменную?
О
! Это все равно что спросить, можно ли намеренно сломать
себе ногу? И ответ на это — нет. То, что вы самостоятельно
причиняете себе боль и страдания, не делает их приемлемыми
и допустимыми. Кроме того, код зачастую и так содержит
достаточно ошибок, чтобы еще вносить их специально. Поэтому
двойного объявления переменных следует избегать в любой
ситуации.
Дело закры то!
Дело закрыто! ) о.
Б л аго д ар я своем у т е р п е н и ю и н аш ей п о м о щ и О уэн завер ш и л
отладку п р о гр ам м ы и получил д о л ж н о сть те сти р о в щ и к а.
О уэн , о п ы т ш о т ­
лад чик сце-нариео
JavaScript■
с а И Н и т !
1
о а Н Я и т !
5
са1Мц»5 2
о л И М о я !
3
оаИНиш! 4
саИНа»!
с а 1 1 8 и т
А!ап. саИег пытЬег 7...1ойау*$ \«тпег1
К о р р е к т н о р а б о т а ю щ и й код
щ е н а р и я р адиоигры оснащ ен
ко нсо лью от ладки.
далее >
545
конт рольная проверка
•
Хрнтролъная таблица Оуэна
(убедись, что все скобки имеют пару.
^
‘П едись,чт о
заключены в ско^т ,— аккуратные
отступы помогают определить границы блощ.
Кзеегай опештвке иштх.ги:решиныхи функций — »^
случ1Ш_итошдоштем.тстъ е иж на^аш т виш я причтои
проблем.
(Будь последователен в жполъэовании павычекм
фов и при необходимости ак^ратно смешиваи ю с в Я Ш Ь -
атрибутаХ;
Символы со спеицалъным значением не забывай заменять escев
символами, например (\")для павычеки ( \ ) д л я апострофов.
уГикргда не используй оператор =
ш ^Г'
ЗаУоЗспрг и не считает это ошибкри, но код будет раЬо-
Х от я
тать вовсе не так, как,^^^ нужно.
это
ОГеред ссылкой на объект убедись что он уже создан,
особенно касается элементов веб-страницы, которые создаются
только после появления события onload.
Ш когда не присваивай мжальным и глобальным переменным
о д ^ к о в ы е имена, ведь в этом случае м>кальтя переменная
начинает использоваться вместо глобальной, и поведение
сценария становится непредсказуемым.
546
глава 11
охота на ошибки
Вкладка
Согните страницу
по вертикали, ч т о б ы
совместить два мозга
и р е ш и т ь задачу.
Чего заслуживают дефекты кода?
--------------- - Ум' хо|^оШо, а два лучте!
---- -------
Подставлять дру1ую щеку —
неправильный подход, который может
истощить ваше терпение. Отвращение
к борьбе с дефектами ослабит ваш код а это уже проблема.
Ih
и н а М и Ч е с К и е
Д а н н ь хе
%
Удобные
веб-приложения
,
Современный Интернет очень ОТЗЫ ВЧИВ, страницы умеют
реагировать на каждый каприз пользователя. И м енно об этом
мечтаю т многие разработчики. JavaS cript играет важную роль в о сущ ест­
влении этой мечты при помощ и технологии Ajax, позволяю щ ей эф ф ектив­
но менять «чувствительность» страниц. Благодаря A jax страницы научились
быстро загружаться и динамически сохранять данные, отвечая на дей­
ствия пользователя в реальном времени без необходимости перезагрузки
б раузера.
.
хочу больш е динамических данны х
Жа)кда динамических данных
Добавление в блог YouCube
новых записей не должно
требовать редактирования
кода страницы.
Помните Руби, фанатку головоломок и автора блога? Руби обо­
жает свой блог YouCube, написанный с применением JavaScript,
но она устала редактировать H T M L -файл при добавлении
каждой новой записи. Поэтому она хотела бы отделить записи
в блог от H T M L -кода, описывающего страницу, чтобы сосредо­
точиться только на создании новых постов.
в Ов
YouCube - The Blog for Cube Puulers
Мне хотелось бы
о
~
-
SearehttmWogJ
новые записи в блог
без редактирования
НТМи-кода.
Ш night а Siuge о й » was chasing як, and St !rept уеШщ шу i
ЄbackwMds...Ybur!
-ЯиЬ>’
W o w
%it took me a month but Ehc new cube is fmiOiy solved?
/ / Returr a for»atte
BEog .prototype.toHTHI
/ / Use a gray back(
I var blogHTML »
rate tlie for
7*7*7 cube. CoaB be my last blog post for a whUe...
^ T M L += “<stn
9^/2008
Attended a tally ouBide of a local азу store
that ssjpped carrying cube puzzles. Powei’to й!е puzzlers
if a 7x7x7 cube. Mixed feelings.
Random Snsfotiy i
.І'ьі^гГГ“
w Date(“08/19/2008")),
ordered the scory 7x7x7 cube. Stortina n m^t-rn
feelings.", new Date('"88/29/2008''^^
oily outside of 0 local toy stor» thot stopped corrylm^r!^ reginen to p r e p a r e . n e u
'
----------к-*-*-!®*,
r uPwo e^rr t oto t the ou^,l.„i7x7x7 cube. Could be .y lost blog
‘= * "
Date("09/03/2008")),
о wh le... , new Date(“09/05/2008")),
me a couple of weeks but the
f.nolly S O I « , - , ne„
-cube777.p„,.)
0ateCm/ei/2m-))
Уставший владелец
Ьлога Руби...
550
глава 12
Ч т о б ы до бавит ь н о вцю
за п и с ь , Руби до л ж н а р е ­
д а к т и р о в а т ь H T M L -ф а й /
с т р а н и ц ы YouCube.
динамические данны е
ф айлы с новой версией блога Руби
м о ж н о с к а ч а т ь т у т к!:Ь р'.//\м \ы ^.
Блог, управляемый данными
Руби на пороге новых открытий. Версия блога, разделяющая
содержимое и структуру страницы, связана с динамическими
данными, которые в реальном времени вставляются в страницу,
в то время как сама страница обрабатывается браузером. Соот­
ветственно, нам нужен блог, управляемый данными. Его веб­
страница будет всего лищь определять структуру, в то время как
содержимое будет меняться при помощи данных.
д а н н ы е блога х р а н я т с я б о т ^ _
К е л ьн о м ф ай ле , ко т о р ы й м о ж
но р е д а к т и р о в а т ь н езависим о
от
в е б
-страницы.
Д а н н ы е б л о га
Веб-страница
Г.,«,...
В е б -с т р а н и ц а с о д е р ж и т
Н Т М и -к о д , опре д е л яю щ и й
ее с т р у к т у р у , а т а к ж е
ко д J a v a S c rip t для вст а вки
в с т р а н и ц у д и н а м и ч е с ки х
данны х блога.
З а п и си блога в с т а в л я ю т с я
в с т р а н и ц у из от дельного
ф айла.
JavaScript о т в е ч а е т
за о б р а б о т ку данны х
блога и в с т а в к у их
в в е б -с т р а н и ц у .
С помощью JavaScript строчки данных блога динамически
вставляются в H T M L -код и генерируют окончательный вариант
страницы блога YouCube, выглядящий точно так же, как и рань­
ше. Н о управляемая данными страница состоит из двух частей:
структура страницы и данные блога. Благодаря тому, что запи­
си содержатся в отдельном файле, Руби больше не понадобится
вмешиваться в код HTML, CSS и JavaScript.
y<wCube ■The Blog for Cube P om U*»
Руби н у ж н о
редакт ироват ь
Т о л ь к о ф айл
с д а н н ы м и блога.
m
bfPtakrЫ
>у
youcube.html
blog.xml
далее >
551
дорога ложка к обеду
Кажется, работа с динамиче­
скими данными очень сложна
и требует большого количества
кода JavaScгipt.
Н ебольш ие дополнительны е усилия по написанию
кода вознаграж даю тся в конце.
Разумеется, написание страниц, управляемых данными,
требует дополнительного программирования, но в ре­
зультате вы получите возможность быстро и легко обнов­
лять их содержимое. Кроме того, вJavaScript существует
встроенная поддержка динамических данных благодаря
современной технике программирования, называемой
Ajax.
552
глава 12
динамические данные
Ajax как возмо)кность для общения
Ajax дает возможность работать с динамическими данными благо­
даря постоянному обмену небольшими сообщениями между браузе­
ром клиента и сервером. Сценарий может запросить данные с сер­
вера, например набор записей блога, а сервер доставляет их при
помощи технологии Ajax. Сценарий же берет полученные данные
и динамически вставляет их в страницу.
позволяет
веб-страницам
динамически получать
данные с сервера.
К л и е н тска я ст р а н и ц а
запрам ибает с
данные блога п р и
т ехно л о ги и AjaKК л и е н т д е л а­
е т за п р о с A ja x
и ж д е т от вет а.
Р
J a v a S c rip t с л у ж и т
п о с р е д н и к о м , вы полняя
з а п р о с , обрабат ы вая
о т в е т и о ст авляя п о ­
лученны е данные в в е б ст раницу.
</head> ■
Щ
</so<SS>
Щ
і ^
youcube.html
Б р а узе р .
^
С ервер п о л у ч а е т з а ­
прос и от правляет
о о т в е т за п и с и блога.
. Клиент
С т б е р оо т
т б^еч ча лі ^еГ т-
„
ьіод.хті
за п исе й олога.
П олучив о т в е т сервера,
кл и е н т бе р е т за п и си блога и м гновенно
о ст а в л яе т и к в веб­
с т р а н и ц у , не т р е б уя
ее п е р езагр узки .
Ш Т У РМ
Что о зн ач ает « X M L » в контексте записей
блога? Каким образом он пом огает работать
с динам ическим и данны м и?
далее >
553
htm l под другим именем
HTML для любых целей: XM L
Буквы «ML» в аббревиатуре H T M L расшифровываются как
«язык разметки» и указывают на то, что язык H T M L исполь­
зует атрибуты и теги для создания гипертекста («НТ»), X M L это еще один язык разметки, используемый для создания всего,
что вам будет угодно. Именно па это указывает буква «X»! Ведь
существуют различные типы данных, которые имеет смысл
сохранить при помощи тегов и атрибутов. Так почему бы не
создать для них расширенный язык разметки?
IB 1 4 T M L
XML — язык разметки
для форматирования
данных любого типа.
Веб-ст раница.
badtwaf(l».-.Yl№!
З а п и с и блога.
Основным достоинством языка X M L является его гиб­
кость. В отличие от HTML, имеющего фиксированный
набор тегов и атрибутов, X M L всего лишь задает правила
их создания и использования. И каждое построенное на
X M L приложение может по-своему воспользоваться ими
для представления определенной информации.
554
глава 12
!.. Powa- №(he pusden’
динамические данные
форматирование с помои^ью XM L
Прелесть языка X M L состоит в возможности самостоятельно соз­
давать теги и атрибуты, подгоняя язык под свои цели. Существу­
ют и предустановленные варианты XML, заточенные на решение
определенных проблем, и ими вполне можно воспользоваться
при необходимости. Н о сложно воспротивиться искушению соз­
дать свой собственный вариант языка.
Как и код HTML, код
XML сост оит из
и е р а р х и и эле м е нт о в.
<movie>
Каждый ф рагм ент
и н ф о р м а ц и и о ф и л ьм е
х р а н и т с я между своими
со б ст в е н н ы м и т е га м и .
<title>Gleaming the Cube</title>
<releaseDate>01/13/198 9</releaseDate>
<director>Graeme Clifford</director>
<Summary>A skateboarder investigates the death of his adopted brother.</summary>
</movie>
Инф ормация
Несмотря на то что раньше вы никогда не видели такого языка
разметки, ведь он полностью со,здан пользователем, названия
тегов дают возможность понять назначение данных. Более
того, теги связаны с заключенной внутри них информацией —
вполне логично использовать тег <director> для хранения
сведений о режиссере фильма!
■о ф ильм е з а ­
ключена в т ег
<m ovie>.
Соедините показанные ниже теги с соответствующим описанием и укажите, к какому язы­
:н 2 н и е
ку — HTML или XML — принадлежит каждый тег.
<itunes:author>
Выделение жирным текста на странице.
<span>
Заголовок новостей.
<title>
Элемент управления вводом данных.
<strong>
Преобразованный в речь текст для звонящих
по телефону.
<input>
Автор цифровой записи 1Типе5.
<prompt>
Выравнивание содержимого веб-страницы.
далее >
555
реш ение упражнения
Вот какое описание соответствует каждому из тегов.
^ п р а ж н ш е
решение
....
.. <зрап> —
...
_НТМи
Выделение жирным текста на странице.
<ltunes :аиЪЬог>
<11Ъ1е>
---- Заголовок новостей.
”’”^ 4
Элемент управления вводом данных.
<зЪгопд>-- -- Преобразованный в речь текст для звонящих
\
телефону.
.. <1приЪ>
-------Автор цифровой записи [Типез.
...
Выравнивание содержимого веб-страницы.
<prompt>
X M L — это Всего лишь те к ст
Как и HTML, X M L -данные — это всего лишь текст, соответствен­
но, хранятся они в текстовых файлах. Н о файлы X M L имеют
расширение .xml, в то время как для H T M L -файлов используется
расширение .html или .htm.
Х М L -д а н н ы е
хранят ­
ся в ф а й л а х
с расш ирением
.x m l.
С?
blog.xml
556
глава 12
динамические данные
XHTML — это
версия HTML,
придерживающаяся более
строгих синтаксических
правил XML.
X M L + HTML = XHTML
Несмотря на различные расширения файлов, X M L и H T M L
связаны друг с другом, и эта связь называется X H T M L . Это со­
временная версия HTML, следующая более строгим правилам
языка XML. Например, каждому открывающему тегу должен
соответствовать закрывающий. В H T M L это правило для таких
тегов, как, например, <р>, соблюдать не обязательно.
HTM L
XHTM L
This is а paragraph of text in HTML.<p>
<p>This is а paragraph of text in XHTML.</p>
8 HTML т ег <p> часто
использует ся сам no ce5e~
указывая на начало или
конец параграфа.
8 XHTML каж дом у о т ­
к р ы в а ю щ е м у т е гу должен
соот вет ст воват ь за к р ы ва ю щ и й .
Другим важным отличием H T M L и X H T M L являются пустые теги,
такие как <Ьг>, которые теперь комплектуются пробелом и косой
чертой, указывающей на отсутствие закрывающего тега.
XHTM L
HTM L
This is just a sentence.<br>
This is just а sentence.<br />
Г
B o m т а к в H T M L вы
гл я д и т т ег переноса
ст роки.
содерж ит
еще и пробел с косой черт ой
Нй конце.
^
В отличие от H T M L в X H T M L в кавычки заключаются все значе­
ния атрибутов.
HTM L
XHTM L
<а href=home.htnil>Go home</a>
<а href="home.html">Go home</a>
О т сут ст вие кавы ­
чек в о кр у г значения
ат рибут а наруш ает
правила X H TM L.
Все значения а т р и б у т о в
в X H T M L до л ж н ы бы т ь
за кл ю ч е н ы в ка вы чки .
Хотя для нужд Руби X H T M L не требуется, он прекрасно иллюстрирует
некоторые синтаксические правила языка XML, на пользовательской
версии которого и будет написан новый вариант блога.
далее ►
557
XHTM L против XML
Беседа у камина
HTML и XML конкурируют за данные.
^ T M L :
.-«чг-
Последняя версия HTML была
переф орм улирована с п о м о ­
щ ью XM L и п о л у ч и л а назва­
ние X H T M L .
------------XML:
Знаешь, ты для меня все запутал. Я был опо­
рой Интернета, а теперь из-за тебя люди
стали путаться.
Н о вот со мной тебе не повезло, потому что
браузеры до сих пор отображают только
НТМЬ-код. А что делать с тобой, они не
представляют.
О чем ты говоришь? Кого заботят данные,
не имеюш,ие внешнего вида?
Не моя вина, что ты думаешь только о веб­
страницах. Я просто имею более широкие
взгляды и потому представляю данные
любого типа.
Вот такой я загадочный парень. Я — суш;ество без лица. Я не имею внешнего вида.
И когда мне нужно показать себя, прибегаю
к твоим услугам.
Вот только пе надо выходить из себя. Весь
мир давно работает с данными, которые
часто не видны. Банковские транзакции,
политические опросы, погодные условия
и многое другое.
И все это можно увидеть только благодаря
мне!
Это так, но вот только каким образом это
все хранится перед тем, как отобразится
браузером? Совсем не в виде абзацев и та­
блиц. Они сохраняются с моей помощью,
плюс я облегчаю обработку данных.
Вот как... То есть ты утверждаешь, что м ы
фактически работаем в паре?
Именно так! Я не имею понятия о том, как
выглядят данные, зато фокусируюсь на их
значении. И пока люди пользуются браузера­
ми, для отображения данных мне нужен ты.
Приятно было это узнать!
558
глава 12
динамические данные
XM L u данные блога YouCube
X H T M L является замечательным приложением XML, быстро
улучшающим структуру и надежность веб-страниц. Н о для блога
YouCube Руби понадобится пользовательский вариант языка
XML, моделирующий нужные ей данные. Давайте посмотрим,
как представить записи блога при помощи тегов XML.
YouCube - The Blog, for Cube Puzzlers
Blog.prototype.signature
<entries>
<entry>
= "by Puzzler Ruby";
реш ение упражнения
Возьми В руку карандаш
Вот вариант языка XML для хранения записей блога.
Решение
Блог н й ~ - '^ Ь 1 од>
У одиился
м еж д у
h r Cube P u z z le rs < /title >
1^егам и
<Ь!од>,
< a u th o r> P u z z le r R u b y < /a u tk o r>
V „_ _ _ T e z < title > с о д е р ж и т
...................................................................................................... заголовок- -оло-га............
..........................
Ш к р _
записеи
хранит СЯ в т еге
<en tries>.
..........................................
< d a te > ll/1 4 -/2 0 0 7 < /d a e e r
.......cube I o rd e re d . I t ’s a re a l p e a r l. < / b o ^ >
..
< /e n tr u ^ i^
— ■
о т д е льн а я за п и с ь
.....Зй^л.^ченй ,6 тег. .<£ntsry>..
т ело з а ­
и дат а.
п и си 'блогй' ■заключеныв свои собст венны е
т еги.
................
</blog>
_
Часщо
^адаБ аеМ ы е
B o iij> o c : b i
_ >А почему не хранить записи блога в виде обычного, не­
форматированного текста?
О
^ ! Вы можете хранить их в таком виде, но потом будет неимо­
верно сложно разбить информацию на набор записей, каждая из
которых связана с отдельной датой. XML структурирует данные
предсказуемым образом, позволяя легко выделять отдельные
записи, не говоря уже о заголовке или имени автора блога.
5= Как XML связан с Ajax?
С ! Название Ajax образовалось как сокращение от
«Asynchronous JavaScript And XML» (асинхронный JavaScript
и XML), так что XML непосредственно связан с Ajax. В настоящее
время роль технологии Ajax расширена настолько, что для нее
не всегда требуется XML. Но именно этот язык формирует осно­
ву большинства Ajax-приложений, предоставляя замечательный
механизм моделирования данных.
Насколько для записи данных блога в формате XML
нужен тег < e n t r i e s > ?
Q : НЕ являясь обязательным , этот тег делает данные более
структурированными и легкими для понимания. Например,
в предыдущем примере без тега < e n t r i e s > оказалась бы
невозможной поддержка множественных тегов < e n t r y > ,
остались бы только теги < t i t l e > и < a u t h o r > . Тег
< e n t r i e s > предполагает наличие набора записей и делает
более очевидным способ использования данных.
560
глава 12
Как вы увидите в этой главе, связь между Ajax и XML обнару­
живается также в способе поддержки технологии Ajax языком
JavaScript. В качестве формата данных для обработки запросов
Ajax JavaScript не ограничен языком XML, но именно этот язык
упрощает обработку этих запросов. Так что хотя некоторые
пуристы и утверждают, что XML никак не связан с Ajax, на самом
деле они идут рука об руку.
динамические данные
Я до сих пор не понимаю,
почему, сохранив данные в опреде­
ленном формате, мы делам их дина­
мическими?
Сам по себ е форм ат XML не делает данны е
динамическими, но он связан как с технологией Ajax,
так и с DOM.
Именно формат X M L чаще всего используется в Ajax,
и, следовательно, именно в нем логично представлять
данные, которые будут пересылаться на сервер и обратно
в управляемой данными версии блога YouCube. Именно вы­
сокая структурированность языка X M L делает его идеаль­
ны м для пересылки данных.
А сходство X M L с H T M L (XHTML) делает возможным
применение D O M для доступа к X M L -данным, представ­
ленным в виде дерева узлов. То есть вы можете написать
код JavaScript, проходящий по дереву X M L -узлов, аккурат­
но изолировать нужные вам данные и затем динамически
встроить их в веб-страницу. Именно это делает X M L наи­
лучшим решением для построения динамических страниц,
управляемых данными.
далее >
561
добавляем ajax
Добавим к блогу Ajax
Имея на руках документ X M L с записями блога, Руби готова ди­
намически вставить их на странипу YouCube при помощи Ajax.
Каким же образом
A jax динамически
вставляет XM Lданные в страницу?
©
I
Сервер получает
запрос и начина­
ет ф орм ирование
ответа.
Серве|»
Х ш т йЯ
Запрос
в основе работы Ajax концепция запро­
сов и ответов, означающая поддержку
обмена данными между клиентом и сер­
вером.
Запрос п р е д с т а вл я е т
содой и м я X M L -ф айла
с з а п и с я м и блога.
О
Y c w C u b e -T h e B
т
Б р а у з е р о тп р а в л я ­
ет серверу запрос
О
и ж д е т о тв е та .
До от правки
A j a x -за п р о са
ст раница не и м е е т данны х
и п о т о м у не мож ет о т о сразит ь з а п и с и блога.
youcu6e.html
562
глава 12
динамические данные
С е р в е р с о з д а е т о тв е т
д л я б р а у з е р а ,у п а к о в а в
д а н н ы е в ф а й л Ы од.
В о т в е т во звр а щ а е т ся
с о д е р ж и м о е X M L -ф а й л а
с з а п и с я м и блога.
blog.xml
Ответ
Сервер
И ногда для обра б о т ки
за п р о с о в A ja x и п о д г о ­
т о в ки о т Ь е т н ы к д а н ­
ны х т р е б у е т с я сцена р и й на ст о р о н е сервера.
о
..., ТвиСи&е~Пж»О
ДfefСиЬеPut*»-*'
Y o u C u b e - T h e В1<% Гог C u b e P u a d e rs
Браузер распако­
вы вает полученны е
Х М Ь д ан н ы е и акку­
„SMTChrteSoiif..........
'■-
9/24/2008
a b u ^ соЬс w » chastof me. snd it faq« yeHmg щ name
ратно вставляет и х
9/19/2009
в страницу.
Wow. Цюок me a niMth but me ПС» cube h Anally .-Mlved!
Ь Piaster/1ы1>у
9/SOM
9/3/2008
После вс 1т а 6к и Х М и -д а н н ы х
о Н Т М 1 ~ к о д с т р а н и ц ы они
ст ановят ся видим ы в б р а у ­
зере.
tМ
аЮ с « 1 ^ppedcarrying„.ЬсpcvJ«.
«*
8Л »М ев
м
youcu5e.html
•в ттштт т щ т щ г ^
Ш Т У РМ
На с т р а н и ц е р а б о т а е т
код JavaScript, о т в е ч а ю ­
щ ий за создание за п р о са
Ajax и о б р а б о т ку о т в е т а .
Какой им енно код JavaS cript отвечает за обработку
запросов A jax и ответов на них?
далее ►
563
что касает ся JavaScript
интерфейс XMLHttpRequest
BJavaScript существует встроенный объект XMLHttpRequest,
инициирующий запросы Ajax и обрабатывающий ответы. О н
достаточно сложен и содержит набор методов и свойств, кото­
рые и осуществляют поддержку технологии Ajax.
readyState
Текущее состояние объекта;
О (неинициализирован), 1 (открыт), 2 (отправка данных),
3 (получение данных), 4 (данные
загружены).
/
/
status
V
(
\
О бъект X M LH ttpR equest и м е ­
е т и другие свойства и м е ­
тоды, но т у т перечислены
самые важные из них.
abort()
XMLHttpRequest
Отмена текущего
запроса.
НТТР-код статуса запроса
например 404 (не обнаружено) или 200 (ОК).
Э т от м ет од п р и ­
м еняет ся, чтобы
от м ен и т ь сделан­
ный запрос.
Эти свойства
определяю т . 5ыл
ли получен к о р ­
рект ны й о т вет на
запрос Ajax.
open О
Подготовка запроса путем
указания его типа, U R L
и других параметров.
onreadys tatechange
send()
Ссылка на функцию,
вызываемую при измене­
нии состояния запроса.
responseText
Отправка запроса
на сервер для об­
работки.
S
Эти два мет ода и с ­
пользую т ся в паре
ОЛЯ подготовки
запросов A jax и их
от правки на сервер.
Текст ответа на запрос.
t
Это уникальное свойство
содержит ссылку на специ­
альный обработчик собы­
т ия, кот орый вызывается
при изменении состояния
— именно он
обрабатывает от вет ы .
564
глава 12
responseXML
Текст ответа на за­
прос в виде дерева
X M L -узлов.
J
Э т и два свойства
хранят данные, п о ­
лученные с сервера
в о т в ет на запрос.
динамические данные
Применение XMLHttpRequest
Объект X M L H t t p R e q u e s t — потрясающе мощный и удивительно гибкий.
Н о мощность и гибкость сопровождаются сложностью, в результате
даже базовые запросы Ajax требуют изрядного количества кода JavaScript.
Частично за это в ответе несовместимость различных браузеров. Удруча­
ет также возможность легко запутаться в параметрах настройки объекта
даже в случае, когда вам требуется только быстрое динамическое пере­
мещение данных.
Рассмотрим в качестве примера код создания объекта X M L H t t p R e q u e s t ,
работающего с различными браузерами;
var request = null;
if (window.XMLHttpRequest)
try {
Объект
XMLHttpRequest
является мощным,
но сложным в ис­
пользовании инстру­
ментом.
Различны е подходы
к со зд а н и ю о б ъ е кт а
X M L H ttp R e c ^ u e s tj т а к
к а к он п о -р а з н о м у п о д ­
д е р ж и в а е т с я р а зн ы м и
в е р с и я м и б раузера IE.
{
request = new XMLHttpRequest{); ■fer
} catch (e) {
request = null;
}
// Пробуем версию ActiveX (IE)
} else if {window.ActiveXObject) {
try {
request = new ActiveXObject{"Msxml2.XMLHTTP ) ;
// Пробуем объект ActiveX более старой версии I E
} c a t c h (е) {
ttry
request = new ActiveXObject("Microsoft.XMLHTTP"
о д ска зка
Создание
объекта
X M L H ttp R e q u e st
. J
} catch(e)
{
request = null;
O n e m m o p t r y - c a t c h являет ся
усо в ер ш е н с т во в а н н ы м м е х а н и з ­
м о м о бр а б о т ки о ш и б о к испо лне ни я
о J a v a S c rip t.
затруднено тем, что для
ка ж д о го браузера тр е ­
буется своя реализация.
К счастью, набор методов
и свойств од и н аков для
всех браузеров — учи ты ­
вать ра зни цу в браузерах
требуется тол ько при
создании объекта.
Теперь, когда объект X M L H t t p R e q u e s t готов, нужно задать
функцию обработки запроса и затем создать сам запрос.
__ Э т а ф у н кц и я вы зы вает ся после
о т в е т а сервера на запрос.
request.onreadystatechange = handler;
request.open(type, url, true); // всегда асинхронный (true)
, чт ы й за п р о с г о т о в к о т п р а в к е , здесь
ж е у к а зы в а е т с я его т и п (Q E T или POST).
При открытии запроса следует указывать его тип ("GET" или "POST"),
адрес U R L сервера, а также является ли этот запрос асинхронным или
нет. Асинхронные запросы выполняются в фоновом режиме, не застав­
ляя сценарий ждать, именно поэтому почти все запросы Ajax являются
асинхронными.
далее *
565
все получено
Получение U отправка
Тип запроса Ajax крайне важен, поскольку отражает не
только содержимое запроса, но также и его назначе­
ние. Первый тип, его еще принято называть методом
запроса, называется GET и применяется для получения
данных с сервера, не влияя на них. Второй тип запро­
са, POST, обычно связан с отправкой данных на сервер,
что приводит к некоторому изменению его состояния.
В Ajax используются
те же два типа запросов,
которые применяются для
отправления HTML-форм,
то есть GET и POST.
GET
Используется для получения д а т ы х
и не меняет ничего на сервере. Н е ­
большие фрагменты данных могут
быть при необходимости отправлены
на сервер в виде URL. Запрос GET пре­
красно подходит для получения запи­
сей блога из хранящегося на сервере
X M L -файла.
PO ST
изменени^’^вдпрТм^
инициируя
ных в базу. Ппи
“ хранение данданных в ответ на
°™Равка
идеально подходит
Запрос Pos Т
записей в блог при п н о в ы х
■^ог при помощи веб-формы.
Запрос PO ST
З а п р о с GET
Date: 0 9 / 2 6 / 2 0 0 8
Body: "These d r e a m s just.
I m a g e : c u b e a p a r t .p n g
Имя XM L'айла, с о 'ержащ &го
з а т е и блога.
Запрос ^5ET н и к а к
не в л и яе т на
сервер,, т ак как
он всего лиш ь
просит прислат ь
за п и си .
blog.xml
О тв ет н а з а ­
п р о с GET.
566
глава 12
Запрос POST меняет
состояние сервера
т ребуя сохранит ь
новую запись.
О тв ет н а з а ­
п р о с PO ST.
N
Новая за п и сь
в блог, к о т о р у ю
нужно сохранит ь
1на сервере.
динамические данные
Запрос с объектом XMLHttpRequest
Определившись с типом запроса и указав этот тип в момент открытия,
м ы подходим к задаче отправки запроса на сервер для последующей
обработки. Код отправки запроса зависит от того, какой тип вы выбра­
ли, GET или POST.
Тип d E T и URL указы ваю т ся
о м о м ен т от кры т ия запроса.
request.open("GET",
"blog.xml",
true);
//
всегда
асинхронный
Если а р гум ен т мет ода
Записи блога в формате
XML запрошены из располо­
женного на сервере файла
blog.xml при помощи запро­
5епсі() и м еет значение
са GET.
request.send(null);
пиИ, значит , о т п р а в ­
ленный запрос не содер­
жит данных.
/Ш
Е
З а п р о с GET
Ь
Новая запись в блог от­
правляется на сервер при
помощи запроса POST.
При от кры т ии запроса
указы вает ся его т и п POST
и URL сервера.
Запрос вклн>чает
Нй сервер данные, поэт ом у нужно
указывать их тип.
request.open("POST",
(true)
"addblogentry.php",
true);
//
всегда
асинхронный
(true)
r e q u e s t .s e t R e q u e s t H e a d e r (" C o n t e n t - T y p e " , " a p p l i c a t i o n / x - w w w - f o r m - u r l e n c o d e d ;
c h a r s e t = U T F - 8 " );
request.send("09/26/2008&These dreams just..,&cubeapart.png");
Н е волнуйтесь, если вы пока н е поняли
разницу м еж ду запросами GET и POST,
Отправляемые вм ест е с запро­
сом данные передаются методу
5епс1() в качестве аргумента.
Все станет намного понятнее по мере того,
как м ы используем полученные знания на
практике для обновления нашего блога YouCube.
далее >
567
болезни роста: упрощаем ajax
Упростим задачу
Объект XMLHttpRequest является крайне м о щ н ы м инструментом,
но пользоваться им непросто, в чем вы уже успели убедиться. Впро­
чем, требуется и изрядное количество «стандартного» кода, который
применяется в любом Ajax-приложении. Поэтому для облегчения
работы с объектом XMLHttpRequest пишутся сторонние библиотеки
Многие из них расширяют функции JavaScript, что требует изучения
дополнительного материала.
Специальный объект
A^axRequest упростит
создание А^ах-запросов.
Упростив задачу до предела, создадим для нашего блога YouCube
специальный объект, который поможет работать с объектом
XMLHttpRequest. Это даст нам возможность сфокусировать вни­
мание на технологии Ajax, вместо того чтобы бороться с объектом
XMLHttpRequest или настраивать стороннюю библиотеку. Н а ш
объект Aj axRequest сделает работу с объектом XMLHttpRequest
намного проще.
е>ольилинство методов
объект а AjaxRequ&st
являю т ся свойст ваMU дост упа к объект у
XMLHttpRequest.
XMLHttpRequest
\
'
Л е ж а щ и й в о с н о в е о б ъ е кт
X M L H ttp R e q u e s t х р а н и т с я
в св о й ств е re q u e s t с п е ц и а л ь н о ­
го о б ъ е кта A ja x R e q u e s t.
Конструктор объекта Aj axRequest крайне упрощен, по срав­
нению с конструктором объекта XMLHttpRequest. Вот как про­
сто выглядит код создания объекта Aj axRequest, способного
инициировать запросы Ajax во всех современных браузерах;
var
568
ajaxReq
глава 12
=
new
A j a x R e q u e s t ()
_М ет од 5епс(0 объект а
AjaкRecшest вы полняет
ОСЮ работ у по от кры т ию
и от правке запросов.
К о нст рукт ор AjaxRequest
авт ом ат ически берет на
себя все сложности соз­
дания базового объекта
XM LH ttpRequest.
динамические данные
Магниты JavaScript
Специальный объект Aj axRequest является оболочкой стандартного объекта
XMLHttpRequest, предоставляя более простой интерфейс для отправки Ajaxзапросов и обработки ответов на них. Но в методе send () этого объекта не хватает
ряда фрагментов. Воспользуйтесь магнитами, чтобы восстановить код метода.
.
if
u
n
c
t
i
o
n
,
p
o
.
t
O
a
„
T
,
p
,
,
P = .t .« a ,
,
( t h i s .r e q u e s t != null) {
// У д а л е н и е п р е д ы д у щ е г о з а п р о с а
t h i s .r e q u e s t .a b o r t () ;
// д о б а в и м п а р а м е т р durrmy д л я п е р е п и с ы в а н и я к э ш а бр а у з е р а
url += "?du m m y = "
try
+ n e w Date (). g e t T i m e О ;
{
t h i s . r e q u e s t . o n r e a d y s t a t e c h a n g e = .................
t r u e ) ; // в с е г д а а с и н х р о н н ы й
(true)
this .r e q u e s t .o p e n (............ '........... '
if
( t y p e .t o L o w e r C a s e 0 = = "get ) {
// О т п р а в к а з а п р о с а GET; без д а н н ы х
t h i s .r e q u e s t .s e n d (.
^ / / ' L i p a B K a з а п р о с а POST;
.) ;
п о с л е д н и й а р г у м е н т с о д е р ж и т д а нные
t h i s .r e q u e s t .s e t R e q u e s t H e a d e r (" C o n t e n t - T y p e " , ...................
);
this .r e q u e s t .s e n d ( .................. ' '
}
} c a t c h (e) {
. f
the s erver \n" + "Details:
a l e r t ( " A j a x e r r o r c o m m u n i c a t i n g w i t h the server. \
e)
}
handler
ty p e
postDataType
PostData
далее >
569
реш ение задачи с магнитами
//
,сз
Решение задачи с магнитами
Вот как выглядит метод send () объекта Aj axRequest.
М е т о д sendQ о т п р а в л я е т
за п р о с ы с у к а з а н н ы м на ~
оором аргум ент ов.
AjaxRequest.prototype.send=
if
fun c tion(type,
url,
handler,
postDat a T y p e ,
postData)
(
( t h i s .r e q u e s t != null) {
// У д а л е н и е п р е д ы д у щ е г о з а п р о са
t h i s .r e q u e s t .a b o r t ();
им
у//I Дf о б а вJ—
пара
--м е т ір d u m m y•• д л я п е р е п и с ы в а н и я к э ш а б р а у з е р а
url += "?du m m y = "
try
t h i s .r e q u e s t .o n r e a d y s t a t e c h a n g e
t h i s .r e q u e s t .open.(.
if
[
handler
і
true);
type
( t y p e .t o L o w e r C a s e () —
"get") {
^
// О т п р а в к а з а п р о с а GET; нет д а н н ы х
t h i s .r e q u e s t .s e n d (
pi"I
11
ф у н кц и я h a n d le r
вы зы вает ся для
об р а б о т ки о т в е ­
т о в сервера.
+ n e w D a t e ()- g e t T i m e ();
II •
О т п р а в к а з а п р о с а POST;
11
всегда асинхронный
Л р г ц м е н т ty p e м е т о д а
sendQ о п р е д е л яе т , б у ­
д е т ли э т о за п р о с Q E T
или P O S T
п о с л е д н и й а р г у м е н т с о д е р ж и т д анные
postDataType
t h i s .r e q u e s t .s e t R e q u e s t H e a d e r ( " C o n t e n t - T y p e " ,
Данные
о т сы ~
лаю т ся "
на сервер
т о л ь ко
в случае
за п р о са т и п а
POST.
t h i s .r e q u e s t .s e n d (
PostData
глава 12
);
);
a l e r t ( " A j a x e r r o r c o m m u n i c a t i n g w i t h the s e r v e r . \ n
+
Details.
Э т о т ко д х р а н и т с я oo
в н е ш н е м ф айле a ja x.js
вмест е с к о н с т р у к т о ­
р о м и другим и м ет одам и
о б ъ е к т а A ja xR e q u e st.
570
(true)
+ e) ;
ajax.js
динамические данные
Анализ запросов Ajax
Специальный объект Aj axRequest состоит из конструктора
и набора методов, один из которых нам особенно полезен. Это
метод send (), подготавливающий и отправляющий на сервер
запросы Ajax. Все эти запросы принадлежат или к типу GET или
к типу POST, аналогично запросам отправки форм в HTML. Но
в случае с Ajax запросы не сопровождаются полной перезагруз­
кой страницы.
AjaxRequest
send(type, url, handler, postDataType, postData)
type
Тип запроса, G E T или POST,
handler
url
Функция обратного вы­
зова, используемая для
обработки ответов.
Адрес U R L сервера (в случае
с блогом YouCube это blog.xml).
П р и необходимости данные
пакуются в этот URL.
postData
postDataType
Тип отправляемых данных (толь­
ко для запросов типа POST).
Отправляемые данные (только для
запросов типа POST). Эти данные
можно отправлять в различных
форматах.
Все запросы Ajax имеют одинаковую структуру, хотя у за­
просов типа GET отсутствует два последних аргумента.
Соответственно, самыми важными для самых простых
запросов Ajax являются первые три аргумента метода
send (). В качестве примера рассмотрим запрос данных
X M L из находящегося на сервере файла movies.xml:
URL запрашиваемо^Tun за­
проса.
Л
ajaxReq.sendC'GET",
ф айла.
"movies.xml " , handleRequest);
П редп о л а гае т ся, ч т о
об ъ е кт А ]а кЯ щ и е ^Ь
у ж е создан и х р а ­
н и т с я в переменной
a ja x R e q .
Н е волнуй­
тесь об
обработке
запросов.
Пока вам достаточно понимать, что
существует специальная функция,
вызываемая после получения ответа
на запрос.
Эта ф у н кц и я б у­
дет вы зы ват ься для
о б р а б о т ки о т в е т а
Нй запрос.
далее ►
571
м огу ли я сделат ь запрос?
Выполнение запросов
Пока метод send {) отправляет запрос на сервер, веб-страница
может выполнять другие операции. Именно поэтому запрос на­
зывается асинхронным. Пр и синхронном запросе происходит
«заморозка» страницы. В ы ничего не можете делать до получения
ответа с сервера.
У о и С о Ь е - - П и Ш о д f o r C u b e P o K ie r s
П о к а з а п р о с о бр аб аты в а­
ется с ер в ер о м , с тр а н и ц а
м о ж б т в ы п о л н я т ь д ру*’*'*®
Сервер
д ей ств и я -
^^youcujte.html
Тот факт, что страница не замораживается в процессе обра­
ботки запроса, не означает, что пользователь действительно
может сделать что-нибудь продуктивное. Все зависит от осо­
бенностей страницы. В случае с блогом YouCube успешный
просмотр записей целиком зависит от скорости получения
ответа на запрос А^ах.
Асинхронные запросы
Ajax не замораживают
странипу во время своей
обработки.
А
КЛ Ю Ч Е В Ы Е
М О М Е Н ТЫ
и
Объект XMLHttpRequest является стэндартным и предназначен для обработки запросов Ajax.
Все запросы Ajax делятся на два типа, get и post,
и определяются отправляемыми на сервер
данными.
Специальный объект Aj axRequest позволяет
работать с Ajax, избегая непосредственных обраще­
ний к объекту XMLHttpRequest.
572
глава 12
Метод send () объекта Aj axRequest открывает
запросы Ajax и отправляет их на сервер.
часаро
динамические данные
ЧаДаБаеМые
B o lIp o C b i
Обязателен ли для выполнения
запросов объект A j a x R e q u e s t ?
может быть и не связан с доставкой
HTML-данных. Более того, основным
достоинством Ajax является именно
возможность запросить данные любого
Q ; Нет. Для отправки запросов
и обработки ответов можно
воспользоваться непосредственно
типа.
объектом X M L H t t p R e q u e s t . Но
зачем это делать, если использовать
объект A j a x R e q u e s t удобнее
и проще? Он создается для удобства и
упрощает работу с Ajax, взяв на себя
всю сложную работу по формированию
запросов.
3 * Чем запросы/ответы на них Ajax
отличаются от запросов/ответов
в HTTP?
; Запросы HTTP и ответы на них
используются браузерами для получения
HTML-страниц с веб-серверов. Запросы
Ajax во многом с ними сходны. Вот их
основные различия: запрос Ajax
Важную роль таюке играет размер
запрашиваемых данных. Ajax вовсе не
обязан запрашивать за один раз целую
страницу или документ. Вполне можно
ограничиться пересылкой фрагмента
данных. Именно благодаря этому Ajax
позволяет динамически редактировать
страницы. При этом вставка новой
информации происходит без перезагрузки.
^ 5 То есть Ajax позволяет
динамически разобрать страницу
по кусочкам?
в реальном времени, не прерывая
использования страницы. Другими
словами, пользователю не приходится
перезагружать страницу для обновления
ее небольшого фрагмента. Подгрузка
этого фрагмента происходит в фоновом
режиме.
Каким образом со всем этим
связаны запросы G E T и P O S T ?
; Тип G E T или P O S T определяет
особенность обработки запроса на
сервере. Однако способность время
от времени динамически запрашивать
данные не зависит от типа запроса.
Основное различие между запросами
G E T и P O S T в том, меняется или нет
состояние сервера в ответ на получение
новых данных. Скажем, если данные
сохраняются в базе, их отправка
Q ; Да! При этом важна не только
сама способность собирать страницу
из фрагментов. Важно распределение
во времени этой сборки. Запросы Ajax
типа P O S T . В противном случае можно
и обработка ответов на них происходит
ограничиться запросом типа G E T .
осуществляется при помощи запроса
КТ9 И НТСовместите фрагменты кода с описанием.
XMLHttpRequest
Запрашивает данные, ничего не
меняя на сервере.
GET
Отправляет запрос на сервер
и получает ответ.
s e n d ()
Отправляет данные на сервер,
меняя его состояние.
A jaxRequest
Стандартный объект JavaScript
для работы с А^ах.
POST
Специальный объект для упро­
щения работы с Ajax.
далее ►
573
от вет на задачу
Вот какое описание соответствует каждому из фрагментов кода.
XMLHttpRequest
Запрашивает данные, ничего не
меняя на сервере.
GET
Отправляет запрос на сервер
и получает ответ.
send()
Отправляет данные на сервер,
меняя его состояние.
AjaxRequest
Стандартный объект JavaScript
для работы с Ajax.
POST
Специальный объект для упрош,ения работы с Ajax.
AjaxR equest
X M U H ttp R e q u e b t
----------------
упрощая работу С Ajax.
574
глава 12
динамические данные
Создание запросов
Вне зависимости от того, каким образом используется Ajax и к каким
данным он пытается получить доступ, обмен данными начинается с за­
проса. Поэтому первая задача, которую нужно решить Руби для нревраш;ения блога YouCube в приложение, управляемое данными, — это
запросить файл X M L с записями блога.
Кажется, мне нужно создать объ­
ект /AjaxRequest, а затем запросить
записи блога.
Создание объекта. AjaxRequest.
Запрос GET для получения
с сервера файла blog.xml.
Обработка запроса?
По поводу ш ага 3 Руби п о к а не
-- уверена,, п о э т о м у она р е ш а ­
е т с ф о ку с и р о в а т ь с я на первы х
двух э т а п а х -
далее ►
575
реш ение упражнения
„^В озьм и В руку карандаш
Решение
Вот как выглядит код создания объекта A j a x R e q u e s t и со­
ответствующий запрос записей блога.
v a r oj'axRefj = n e w A ja xR e q u e stQ ;
©
Н а м п о т р е б у е т - ___
СЯ за п р о с G E T для
п о лучени я данны х
с сервера.
^
a ja xR e q .se n d ("Q E T "j ‘'b lo g .x m l“ , h a n d le R e q u e st);
.
j
Ф айл ф о р м а т а X M L
у к а з а н , к а к U R L за п р о с а
^
Д л я о ё р а д о т ки з а п р о сй н а м п о т р е б у е т с я
специальная ф у н кц и я
h andleR equestQ .
Закончишь — Вызови меня
Сценарий на стороне клиента
После отправки запроса Ajax роль браузера меняется — он
не ждет ответа с сервера. Благодаря тому, что запросы Ajax обрабатывает ответ, полученный
обычно являются асинхронными, пользователь может
продолжить работу со страницей, а ожидание ответа проис­ на запрос Ajax, при помопщ
ходит в фоновом режиме. Как только обработка запроса на
специальной функции обратного
сервере закончена, ответ обрабатывается кодом JavaScript
при помощи функции обратного вызова.
вызова.
Сервер о т п р а в л я е т о т ­
в е т б р а у зе р у , к о т о р ы й
вы зы вает с п е ц и а л ь н у ю
ф у н к ц и ю о бработ ки.
Создание объекта A j a x R e q u e s t .
@
Занре€-€&¥-йДя-нодучения
-с-сеушера файла hlo^ptwU(^ ^ ^ б р а б о т к а
576
глава 12
handleRequestО ;
В сценарии блога до л ж н а
присут ст воват ь ф у н к­
ция о б р а т н о го вызова
n a n d le R e q u e s t ( ) .
динамические данные
Обработка ответа
в нашем случае окончание обработки запроса должно приводить
к вызову специальной функции handleRequest (), которая в за­
висимости от полученных с сервера данных предпринимает опреде­
ленные действия.
Каким же образом функция, об­
рабатывающая ответ на запрос, получает
доступ к присланным с сервера данным?
Доступ к полученным в ответ на запрос данным имеют методы
объекта AjaxRequest.
Для этой цели применяется два метода объекта Aj axRequest,
которые называются getResponseText {) и getResponseXML ().
A jaxRequest
getResponseText()
Получение ответа на за­
прос Ajax в виде текста.
g e t R e sponseXML()
Выбор метода зависит от того, в каком формате вам нужно
получить ответ. Для получения структурированного кода
используйте метод getResponseXML (). Соответственно,
метод getResponseText () даст ответ в виде обычного
текста.
Получение ответа на запрос
Ajax в виде структурированного
X M L -кода.
Ш ТУРМ
Код X M L во многом н апом и нает код H T M L . Как бы вы орга­
низовали доступ обработчика запросов к данны м X M L ?
далее >
■
577
на помощ ь приходит DOM
Если XM L является набором
тегов, нельзя ли для обработки
таких данных использовать DOM?
DOM как Выход из поло)кения
Любовь Руби к сісладьіванию головоломок явно развивает ло­
гическое мышление, потому что она совершенно права, пред­
лагая воспользоваться D O M для обработки данных в формате
XML. Как вы помните, D O M управляет данными HTML, пред­
ставляя их в виде дерева узлов. А значит, аналогично можно
поступить с данными XML. Достаточно представить как дерево
узлов блог YouCube.
^<tltle>YouCube - The Blog for Cube Puzzlers</title>
<author>Puz2ler Ruby</authot>
<entries>
<entry>
<date>08/14/2008</date>
^
<body>Got the new cube I ordered. It's a real pearl.
.
</entry>
<entry>
<date>09/26/2008</date>
<body>These dreams just keep getting weirder...
a cube take itself apart. What <strong>does</strong> it
mean?</body>
<image>cubeapart.png</image>
</entry>
</blog>
author
"Puzzler Ruby
Тег <Ьое(у> м о ж е т бы т ь
п р е д к о м для целого н а ­
бора т егов, если за п и си ~
блога с о д е р ж а т НТМЬфюр м а т и р о в а н и е .
.....
Тег <аиИаог> с о д е р ж и т
и м я а в т о р а в виде д о ­
чернего т е кст о в о го
эл е м е н т а .
578
глава 12
Руби нужно извлечь записи блога из набора узлов XML, что прош;е всего сделать при помош,и функции. Нет смысла добавлять
к блогу YouCube дублируюш;иеся фрагменты кода, если этого
можно избежать.
динамические данные
Q «функции get]e^t() Подробно
Специальная функция getText () выполняет монотонную ра­
боту по извлечению содержимого узлов DO M .
function getText(elem)
Э т от аргум ент ука~
. зы ва е т на э л е м е н т ,
содерж им ое кот орого
т р е б у е т с я извлечь.
var text =
if
(elem)
if
{
(elem.childNodes)
for
(var 1 = 0 ;
Ц иклический
просм от р всех
дочерних узлов
эл е м е н т а .
{
i < elem.childNodes.length; i++)
{
var child = elem.childNodes[i];
if
(child.nodeValue)
text += c hild.nodeValue;
else {
^ _______________
if (child.childNodes)
if
Д обавление
содерж им ого
дочерних узл о в
в перем енную
te x t.
(child.childNodes[0].nodeValue)
text += child.childNodes[0].nodeValue;
return text;
в руку карандаш
В о зв р а щ а е м
. п е р е м е н н у ю te x t ,
в кот орой т е ­
п е р ь н а хо ди т ся
все с о д е р ж и м о е
дочерних узлов.
Если дочерние узл ы ,
в свою очередь, я о л я ■ю т с я п р е д к а м и для
др у г и х узл о в, б ерем
т е кс т о в о е со де р ж и м о е первого из них
и двигаем ся дальше.
П р е д п о л о ж и м , ч т о п о л у ч е н н ы е в о т в е т на з а п р о с д а н н ы е
в ф орм ате X M L уж е со хр ан е н ы в пе р е м е н н ую
xmlData. Н а п и ­
ш и те код, з а д а ю щ и й с и г н а т у р у б л о га Y o u C u b e к а к с о д е р ж и м о е
X M L -тега
<author>.
далее V
579
ответы на запросы о себе
Вот как выглядит код, задающий сигнатуру блога YouCube как
содержимое XML-тега <author>.
‘'«t-riM
я
\^^'^/< ^J< aK ^cu
zH ai'vvwM
M yp a м
я вилляяеемт сся
сб о й ст в о м у р о вн я к л а сса , ее з а ­
дание до л ж н о рсущ есилвлят ься
п р и п о м о щ и п р о т о т и п а Blog.
В спом огат ельная
ф у н кц и я y e tT e x tQ и зв л е ­
к а е т с о д е р ж и м о е т ега
< a u th o r> .
В Х М и -д а н н ы х м о ж е т
бы т ь т о л ь к о один т ег
<аиЬког>_, п о э т о м у п р о с т о
дерем п е р вы й тег.
^ ^ Q B P A S O T IC A . еУ Ш Ё Т еЗВ Й Л
Э А П Р С (С Ы
И нтервью нед ел и:
И с п о в е д ь ф у н к ц и и h a n d le R e q u e s t O
Head First: М ы слышали, что вы достигли совер­
шенства в ответах на запросы Ajax. Расскажите,
что для этого нужно?
handleRequestO: Это решаю не я. Я же специаль­
ная функция и меняюсь от приложения к прило­
жению.
handleRequestO: Когда приходит ответ на за­
прос, я его обрабатываю. Сначала нужно убе­
диться, что ответ корректен, затем я перехожу
к полученным данным и при необходимости
интегрирую их в веб-страницу.
Head First: Почему?
Head First: То есть вас вызывают сразу после за­
вершения запроса?
handleRequestO: Да. Хотя на самом деле меня не­
сколько раз вызывают и в процессе обработки за­
проса, но по большей части в моих услугах люди
заинтересованы только в самом конце.
Head First: И как же вы узнаете о том, что насту­
пил тот самый момент?
handleRequestO: Ну, объект AjaxRequest имеет
пару методов, при помощи которых я могу про­
верить состояние запроса и убедиться в том, что
его обработка без проблем завершена.
Head First: А откуда вы узнаете, что нужно делать
в этот момент?
580
глава 12
handleRequestO: Потому что разные приложе­
ния используют полученные в ответ на запрос
данные по-разному.
Head First: В ы хотите сказать, что для каждого
приложения вас нужно писать заново?
handleRequestO: Именно так. И это имеет
смысл, ведь, к примеру, приложение для покупок
в Интернете обрабатывает Ajax-запросы совсем
не так, как блог. Ajax гарантирует мой вызов по­
сле завершения обработки запроса, а дальше все
зависит от приложения.
Head First: То есть создание управляемой Ajax
страницы означает создание специального обра­
ботчика запросов?
handleRequestO: Да, вы все правильно поняли.
Head First; Спасибо за поучительную беседу.
handleRequestO: Всегда счастлива поговорить.
динамические данные
М Ш А ПОМЯ ГАМТА
П о п р о б у й т е с е ^ я Б р>оДи сосв д аБ и в д е Л я
n jn iM e ^ a H u u U og-bffC H um e, к а к j^ a S o m a e m
=ф у н к ц и я W i J I e R e ' ^ s t O
1 -
iu n c tio iL
М аГиЧ есКое Ч исло. Ц айД ехпе
Л и Б ь 1 'J oC ogpH H ooxieU , В е д у щ и х
к y<3iemHo]viy Б ь л о л н е н и р э з а п р о с а ?
function
if
handleRequestO
{
(ajaxReq.getReadyStateО
11
Сохраняем
var
//
xmlData
Задаем
полученные
=
//
сигнатуру
Создаем массив
entries
for
(var
//
=
a j a x R e q . g e t S t a t u s ()
формате
==
200)
{
XML
блога
=
объектов
"by
"
Blog,
+
g e t T e x t ( x m l D a t a .g e t E l e m e n t s B y T a g N a m e ( " a u t h o r " ) [0])
содержащий
отдельные
записи
i <
e n t r i e s .l e n g t h ;
i ++)
{
запись
blog.push(new
new
&&
в
xmlData.getElementsByTagName("entry");
1 = 0 ;
Создаем
4
a j a x R e q .g e t R e s p o n s e X M L ( ).g e t E l e m e n t s B y T a g N a m e ( " b l o g " ) [ О ];
Blog.prototype.signature
var
==
данные
B l o g ( g e t T e x t ( e n t r i e s [ i ] .g e t E l e m e n t s B y T a g N a m e ( " b o d y " ) [0]),
D a t e ( g e t T e x t ( e n t r i e s [ i ] .g e t E l e m e n t s B y T a g N a m e ( " d a t e " ) [ 0])),
g e t T e x t ( e n t r i e s [ i ] . g e t E l e m e n t s B y T a g N a m e ( " i m a g e " ) [0])));
}
//
Отображаем
блог
s h o w B l o g (5) ;
далее >
581
ответ на задачу
О т в е т на
з а д а ч у
I j o r n к а к и м и К о м м е н т а р и я м и сЛ е Д °Б а Л о
снабдить сзаеДиаЛьнук* =рункДи1о Wicllej|e=ji'est().
Убеждаемся в успеш ном
выполнении запроса Ajax,
проверяя его состояние. '
Присваиваем сигнат уре
блога содержимое т ега
<autkor>.
function
if
handleRequestO
{
(ajaxReq.getReadyStateО
//
Сохраняем
var
//
xmlData
Задаем
полученные
=
//
сигнатуру
Создаем
entries
for
(var
/ /
массив
=
i =
Создаем
4
&&
в
ajaxReq.getStatusО
формате
==
2 00)
{
XML
блога
=
объектов
"by
"
Blog,
+ g e t T e x t ( x m l D a t a .g e t E l e m e n t s B y T a g N a m e (" a u t h o r " )
содержащий
отдельные
записи
[ Oi :
ПолучаеМ все
x m l D a t a . g e t E l e m e n t s B y T a g N a m e ( " e n t r y " ) ; ^ — — --------- э л е м е н т ы , с о 0;
i <
e n t r i e s .l e n g t h ;
i ++)
^^рж ащ ие за -
{
писи
запись
blog.push(new
new
==
данные
а j a x R e q . g e t R e s p o n s e X M L ().g e t E l e m e n t s B y T a g N a m e ( " b l o g " )
Blog.prototype.signature
var
X M L -данные содержат
всего один т ег <Ыоу>,
поэт ом у берем первый
элем ент массива, во з­
вращенного функцией
yetE lem entsByTagN am eQ .
бл ога .
B l o g ( g e t T e x t ( e n t r i e s [i ] .g e t E l e m e n t s B y T a g N a m e (" b o d y " ) [ 0 ] ) ,
D a t e ( g e t T e x t ( e n t r i e s [ i ] . g e t E l e m e n t s B y T a g N a m e ( " d a t e " ) [0]
g e t T e x t ( e n t r i e s [ i ] . g e t E l e m e n t s B y T a g N a m e ( " i m a g e " ) [0])));
//
Отображаем
блог
s h o w B l o g (5);
Вызываем ф ункцию 5кошВ1од()
для отображения на ст ранице
пят и последних записей.
Создаем новый объект Ыод для
очередной записи и добавляем
т уда последний элем ент м а с ­
сива при помощ и мет ода pushQ
объект а Array.
О
Сделано!
582
глава 12
динамические данные
YouCube, управляемый данными
---------- — -— ~_Г7ослеЗняя версия ф а й лоб YouCube дост упна
\СРуби восхищена новым обликом, который ее блог приобрел благодаря
Ajax (это сэкономило ей много времени), но она обеспокоена тем, что
происходит на странице в процессе загрузки данных
для скачивания по адресу
h ttp ://w w w M e a d fin tla b s.
com /books/hfjs./.
r
Теперь, когда записи выделены
<Ыод>
<author>
в ХМЬ-код, блог работает просто здо­
рово, но как дать понять пользователям,
<dat*>08/29/200«</.
что идет процесс загрузки?
<body>FounO а 7к-7х7
<«ntry>
<date>OB/?9/JOOS</da
<bo<ly>M«t up with SOI
о prepare.</body>
__...ль.,:*.«««':*“'»"'«
У ш С и Ь с -ТЬс Ш о « tor С»Ье Т т
<tt»t«>09/S/200e</(Jate>
Ла
<«ntry>
«lae«>0S/i9/2O0e</date>
<lme9e>cube777.pn,</imige>
</entry>
<*ntry>
<det»>09/24/2008</dAte>
<bedy>I dre,™d last night a
шшч»
■»».Л»»*»t“Pе““«
ЫРиакгЫу
_
^ ШI iJjoaied
4Дв08
_
^
last meht в
iffРаЫ
егRuby
Теперь блог
управляет ся дан­
ными XML...
Щ
c
h
e
s
m
s
«"У
'
ЬуРиикгИчЬу
S S * « = W 7.7.7 » « , С о . « Ы « у И Ь Ь * , о . Г « . « И . . .
byPiuxterRniry
...но некот орых пользоват елей
см ущ ает пуст ая ст рани ц а .
кот орая появляет ся в п р о ­
цессе загрузки данных.
Возьми в руку карандаш
Впишите в функцию lo a d B lo g ( ) отсутствующую строчку кода, которая
отвечает за отображение картинки wait.gif, демонстрируемой в процессе
загрузки записей.
Подсказка: используйте основной тег
function
loadBlogо
d iv
блога с Ю
"Ы о д ".
{
ajaxReq.send("GET",
"blog.xml",
handleRequest);
далее *
583
реш ение упражнения
Возьми В руку карандаш
Решение
function loadBlogо
Вот как выглядит код функции loadBlog ().
{
.7.
ajaxReq.sendC'GET",
"blog.xml", handleRequest);
И з о б р а ж е н и е дем онст рирует ся
ö процессе з а г р у з к и записей блога.
}
Анимированное изо5ряжение
r
S
src-w a it.g if' a j t - Loading... ' />";
О
YouCub« - The Blog for Cube Puzzlers^
««««»»
Ä
8 данном случае пройде вос­
пользоват ься свойст вом
innerH TM L, чем DOM, пот ом у
чт о т ег image добавляется
к паре ат рибут ов.
VuCub. - The Blog tor C b e P « » * »
пользобйжелям. ч т о идет за
грузка даннш .
N
Hioioc
001 aic
X
X
N
Search the Biog
|j
wait.gif
S h o w All Bofl Entries |
_
View a Random Mofl Entry
Ч асщ о
Задаваем ы е
:>
J'
Б о ц |= » о с гь 1
Последняя запись блога YouCube содержала тег HTML
'I Как работают свойства
readyState
и
status?
<strong> . Допустимо пи это в коде XML?
! Оба этих свойства принадлежат объекту
I
Если помните, XML-код применяется для представления
данных любого типа. В данном случае, учитывая, что тело
записи будет вставлено в веб-страницу, технически возможно
и предназначены для отслеживания со­
стояния запроса, например (0) означает, что запрос не инициа­
лизирован, а (4) — что данные загружены, а также его статуса,
включить HTML-теги, влияющие на вид записи после вставки.
Другими словами, содержимое каждой записи блога может
включать в себя HTML-теги, передаваемые вместе с XML-кодом
например 404 означает (not found), а 200 означает (ОК). Под­
робное рассмотрение этих свойств в данном случае не требует­
ся. Вам достаточно знать, что запрос выполнен, если состояние
равно 4 (loaded), а статус имеет значение 200 (ОК). Только при
в виде специальных узлов, ответственных за форматирование.
Впрочем, это достаточно сложная задача^ ведь нам нужно рекон­
струировать узлы, которые использовались для форматирования
HTIVIL-кода, при вставке в страницу XML-данных. В случае блога
YouCube мы решили отделить текст от HTML-тегов, оставив фор­
матирование за кадром. Но вполне возможно, что в следующей
версии YouCube этот аспект будет учтен.
584
глава 12
XMLHttpRequest
этих условиях вызывается функция
handleRequest (),
динамические данные
Неработающие кнопки
Хотя внесенные при помощи Ajax изменения не оказали осо­
бого влияния на внешний вид блога YouCube, кое в чем интер­
фейс претерпел изменения. Кажется, кнопки на нашей страни­
це перестали работать нужным нам образом.
Sean h the Biog
- Г
'
Пользователи сообщают, что кнопки не
всегда срабатывают. П осле щелчка ниче­
го не происходит. Более того, сам блог
становится невидимым. В чем же дело?
Show А» efoq
Entries
О
View а Random Biog Entry |
По непонят ны м причинам
кнопки иногда п ер ест а ю т
работ ат ь, а блог при эт ом
ст ановит ся невидимым.
Неработающие кнопки
=
Разочарованные пользо­
ватели
Ш ТУРМ
П о ка ки м п р и ч и н а м м о гу т н е р а б о т а т ь кн о п ки ? Н а
ка ко й с т а д и и з а гр у зки с тр а н и ц ы м о ж е т в о зн и ка ть
э та п р о б л е м а ?
Руби не волнует ся,
но очень хот ела бы
уст ранит ь эт и непо­
ладки.
далее ►
585
когда я могу этим воспользоваться ?
Кнопкам ну)кны данные
Дело в том, что кнопки в нашем блоге работают только
при наличии доступа к данным. А так как данные теперь
загружаются из внешнего ХМЬ-файла, некоторое время
страница суш;ествует без них. В этот период сущ;ествовапие кнопок лишено смысла и только запутывает пользо­
вателя.
Отключение кнопок — прекрасное решение.
Отключив кнопки на время загрузки данных, м ы простым
и элегантным способом решим проблему. Ajax отправляет
запрос данных при первой загрузке страницы, а значит,
кнопки можно изначально отключить, предоставив затем
к ним доступ при помощи функции handleRequest (), ко­
торая запускается после завершения обработки запроса.
Отключение реализуется при помощи атрибута disabled
тега <input>. Этому тегу присваивается значение
"disabled" в НТМЬ-коде. И наоборот, ему можно присво­
ить значение false в коде JavaScript, включив тем самым
кнопку.
<input type="button" value="Search the Blog"
S e a rc h th e S lo g
i
disabled="disabled" />
S m r c h th e il o p
buttonElem.disabled =» false;
586
глава 12
динамические данные
Магниты JavaScript
В о с п о л ь з у й т е с ь м а г н и т а м и д л я з а п о л н е н и я п р о б е л о в в ко д е с т р а н и ц ы Y o u C u b e . С д е л а й те
так, ч т о б ы к н о п к и б ы л и н е д о с т у п н ы д о з а в е р ш е н и я з а г р у з к и за п и се й . Н е к о т о р ы е м а гн и т ы
м о ж н о и с п о л ь з о в а т ь н е с к о л ь к о раз.
“ ftl.>Vo„Cub=
- Th e Bio,
£oi е л е
Puz.ler=</tltle>
< s c r i p t type
<script type="text/javascript"
<script type="text/javascript">
f:.;ction h a n d l e R e q u e ^ O
if
(
^
a j a x R e q . g e t S t a t u s () == 200)
{
( a j a x R e q . g e t R e a d y S t a t e и
// В к л ю ч е н и е к н о п о к
) .
document.getElementByld!
) .
d o c u m e n t .g e t E l e m e n t B y l d (_
) .
document.getElementByld(^
}
</script>
</head>
-e
e .o ..
onclick="searchBlog0 ; "
< i n p u t
”t y p e = " t e x f
id="searchtext"
:?SufSe:C«orid="sbowall"
name-searchtext"
value-"
/>
/>
v a l u e = " S b o w Л11 B l o g E n t . i e . "
o n c l i c k = " s h o w B l o g 0 ; " />
<ln;:t;p:i"buln:';l"v;:;a::.m"
value-Vle«
a R a n d o m B l o g Ent.y'^
o n c l i c k = " r a n d o m B l o g {);"
"search"
/>
</ b o d y >
</html>
"showall"
"viewrandom"
^
| disabled
|
false
1
"disabled"
1
далее *
587
реш ение задачи с магнитами
Решение задачи с магнитами
Вот как должен выглядеть код блога YouCube, в котором доступ к кнопкам предоставля­
ется только после окончания загрузки записей.
<html>
<head>
<title>YouCube
- T h e B l o g for C u be P u z z l e r s < / t i t l e >
<script type="text/javascript"
<script type="text/javascript"
ocript
src="ajax.js"> </script>
s r c = " d a t e .j s"> < / s c r i p t >
type="text/ javascript">
function h a n d l e R e q u e s t O {
if ( a j a x R e q . g e t R e a d y S t a t e 0
== 4 && aj a x R e q . g e t S t a t u s ! )
onn^
=- 200)
// В к л ю ч е н и е к н о п о к
d o c u m e n t .g e t E l e m e n t B y l d (
d o c u m e n t .g e t E l e m e n t B y l d (
d o c u m e n t .g e t E l e m e n t B y l d (
)
</script>
</head>
< b o d y o n l o a d = " l o a d B l o g ();">
< h 3 > Y o u C u b e - The B l o g for C u b e P u z z l e r s < / h 3 >
< i m g s r c = " c u b e . p n g " a l t = " Y o u C u b e " />
< i n p u t t y p e = " b u t t o n " i d = " s e a r c h " v a l u e = " S e a r c h the Blog"
"disabled"
disabled
<input type="text"
id="searchtext"
name="searchtext" value-""
/>
<div i d = " b l o g " x / d i v >
,
< i n p u t t y p e = " b u t t o n " i d = " s h o w a l l " v a l u e = " S h o w A ll B l o g E n t r i e s
"disabled"
discjsled
<input type="button"
disabled
</body>
</html>
588
глава 12
|.=
i
id="viewrandom"
"disabled"
|
v a l u e = " V i e w a R a n d o m B l o g Entry"
o n c l i c k = " r a n d o m B l o g {) ;" />
динамические данные
Функция, экономяи^ая Время
Н а данный момент блог YouCube уже управляется динамическими
данными, но Руби пока еще рано почивать на лаврах. На странице
блога отсутствует интерфейс для добавления записей. А Руби хотела
бы не редактировать каждый раз X M L -файл, а писать непосредственно
в блог и сохранять результаты на сервер.
Мне надоело редактировать фай­
лы и отправлять их на сервер по FTP.
Я хочу обновлять свой блог YouCube
непосредственно в браузере!
■ V
Редактировать код +
Отправлять файлы
на сервер
= Надоело!
Руби хотела бы вводить записи в форму непосредственно на
странице блога. Хотела бы, чтобы для этого ей было достаточ
но браузера и чтобы больше никаких текстовых редакторов
и РТР-клиентов.
YouCube - ArfdtaB totht№ o9fofC ubg_gugk«
Уо1;СиЬе Adding to the Blog for Cube Pmriers
Image (optional):
Add tht New B o g Entry
]
,
Для добавления новой записи
дост аточно заполнит ь фор
му и щ елкн ут ь на кнопке!
Страница добавления
новой записи содержит
т ри поля для т р ек видов
данных.
•V
Ш ТУРМ
Каким образом A jax позволяет добавлять записи
в ф о рм ате X M L посредством пользовательского
интер ф ейса на веб-странице?
далее >
589
и снова клиент и сервер
Запись данных 6 блог
Размышляя о записи данных в блог в терминах Ajax, мож­
но представить запрос типа P O S T , отправляющий их на
сервер, где они записываются в файл Ы о д .xml. Ответ
сервера в данном случае не требуется.
И как же новая запись попадет в располо­
женный на сервере файл blog.xml? Насколь­
ко я помню, JavaScript не умеет записывать
файлы.
Да, 1ауа8сг1р1 не п о м о ж е т вам записать д а н н ы е на сервер.
Более того, на стороне сервера вы даже не сможете запустить
код JavaScript. Ведь JavaScript — это клиентская технология,
разработанная для использования исключительно в браузе­
рах. Н о нам-то требуется записать файл на сервер. Эта за­
дача возникает не так уж редко, и поэтому технологии, ис­
пользуемые на стороне сервера, часто применяются в паре
c J a v a S c rip t.
Итак, нам нужна технология, подобная JavaScript, но функ­
ционирующая при этом на стороне сервера. Есть несколь­
ко вариантов, из которых м ы выберем наименее сложный
и умеющий обрабатывать данные в формате ХМ...
590
глава 12
динамические данные
На помощь приходит РНР
Язык написания сценариев Р Н Р — это то, что нам нужно для
записи данных в X M L -файл на сервере. Задача включает в себя
чтение X M L -файла, добавление новой записи к уже существую­
щ и м и сохранение новой информации. Впрочем, в результате
м ы все равно возвращаемся к получению записей с сервера при
помощи Ajax-aanpoca со стороны браузера.
Date:
~
это язык
РНР
написания сценариев,
работающий на стороне
сервера.
~ —
lo o lc in ,..,.
Новая запись от правляем ся
на сервер как данные запроса
A jax т ипа POST.
РНР играет т у
же роль, чт о и
JavaScript, но на
ст ороне сервера,
а не на ст ороне
клиент а.
Сценарий РНР Нй серве­
ре заносит новую запись
блога в ф айл blog.xml.
blog.xml
Р Н Р можно представить как эквивалент
JavaScript, работающий на стороне сервера...
Именно он поможет сделать запись новых
X M L -дапных в блог!
б елее Р
591
на ст ороне сервера
^ o in o B b iÜ К о д
пг
Сценарий Р Н Р на стороне сервера добавляет новую запись
в файл blog.xml.
ст рочны х данных
XML в п е р е м е н н у ю $rawB!og.
<?php
$filename
if
Проверяем,
существует
ли нужный
файл.
"blog.xml";
(file_exists($filename)) (
// З а г р у з к а з а п и с е й б л о г а из ф а й л а X ML
$rawBlog = file_get_con t e n t s ( $ f i l e n a m e ) ;
Если ф айл не
сущ ест вует ,
создаем пуст ой
докум ент XML.
}
else
{
// Создание пустого XML-документа
$ r a w B l o g = "<?xml v e r s i o n = \ " l .0\" e n c o d i n g = \ " u t f - 8 \ " ?>";
$ r a w B l o g .= " < b l o g X t i t l e > Y o u C u b e - T he B l o g for C ube P u zzlers</
title>";
$rawBlog
.=
"<author>Puzzler Ruby</author><entries></entriesX/blog>" ;
$xml = new SimpleXmlElement($rawBlog);
П реобразу­
ем строчные
данные з а п и ­
си в ф о р м а т
XMLj к о т о ­
рый во многом
напом инает
дерево DOM
в JavaScript.
// Добавляем новую запись блога как дочернии узел
$ e n t r y = $ x m l - > e n t r i e s - > a d d C h i l d (" e n t r y " );
$entry->addChild("date",
$entry->addChild("body",
if
-- Новая запись ста -
новится дочерним
узлом в ст рукт ире данных XML.
$ _ R E Q U E S T [" d a t e " ]);
s t r i p s l a s h e s ( $ _ R E Q U E S T [" b o d y " ])
( $ _ R EQUEST["image"] != "")
$ e n t r y - > a d d C h i l d ( " i m a g e " , $ _ R E Q U E S T [ " i m a g e " ]);
// Записываем блог в файл
$file = f o p e n ( $ f i l e n a m e , '
f w r i t e ($file, $ x m l - > a s X M L (
fclose($file);
?>
С охраняем ф а й л блога
после добавления новой
записи.
addblogentry.php
_
т
Чаапо
^аД аБ аеМ ы е
Сценарий РНР хранит ся
в ф айле addblogentry.php.
В о Ц р *о С Ь 1
Обязательно ли использовать РНР
для записи файлов на сервер?
3 * Можно ли применять Ajax без не­
сервера, является главная страница блога
обходимости использовать программы,
работающие на стороне сервера?
YouCube. Но большинство Ajax-приложений
далеко не так просты, и без сценариев,
Q j Не обязательно. Существуют
и другие технологии написания сценариев,
работающих на стороне сервера. Напри­
мер, Perl (CGI), который умеет делать
ровно то же самое, что и РНР. Вы можете
по своему желанию выбрать технологию
для создания работающего на стороне
сервера компонента Ajax-приложения.
592
глава 12
; в некоторых случаях да. Помните,
что все запросы Ajax, кроме самых про­
стых, сводятся к получению сервером дан­
ных от клиента и последующей обработке
этих данных, например поиску информа­
ции в базе или записи в файл. Хорошим
примером запроса Ajax, не требующим
выполнения сценариев на стороне
работающих на стороне сервера, уже не
обойтись. Вопрос в том,отправляется
ли вам в качестве ответа сервера целый
файл, как в случае с файлом blog.xml, или
же данные требуют более сложной об­
работки. Впрочем, большинство предназна­
ченных для этого сценариев крайне просты
и не требуют особых знаний по программи­
рованию на стороне сервера.
динамические данные
Требования РНР
в отличие от языка JavaScript, по умолчанию поддерживаемого
современными браузерами, далеко не на всех серверах поддер­
живается РНР. Поэтому перед отправкой на сервер РНР-файлов
нужно узнать у системного администратора, насколько это допусти­
мо. Возможно вам потребуется провести некоторые операции по
настройке или поискать другой сервер. Ведь без поддержки Р НР
сценарий блога YouCube просто не будет работать.
Для запуска РНРсценариев может
потребоваться
предварительно настроить
сервер.
РНР
У б е д и т е с ь , ч т о в а ш с е р -^
вер п о д д е р ж и в а е т
PHF
Если поддержка от сут ст вует,
вы можете подключить ее само­
стоятельно или попросить это
сделать администратора.
Затем нужно выбрать место на сервере, где будут храниться ваши
РНР-файлы. В большинстве случаев их можно поместить в ту же папку,
в которой хранятся НТМЬ-страницы и внешние файлы JavaScript. Н о
иногда установки Р Н Р требуют сохранения сценариев в отдельную
папку. Узнать это можно у вашего системного администратора.
В большинстве случа­
ев дост аточно п о м е ­
с т и т ь сценарии РНР
в одну папку с вед
addblogentry.php
страницами.
Выбрав место на сервере для ваших РНР-файлов,
продолжим работу над усовершенствованием на­
шего блога YouCube.
youcube.html
blog.xml
ajax.js
далее *
593
особенности использования php
Данные для РНР-сценария
Давайте посмотрим, каким образом РНР-сценарий записывает
данные в расположенный на сервере X M L -файл. Именно это
позволит нам составить запрос Ajax таким образом, чтобы вы­
полнить поставленную задачу.
Сценарию Р Н Р требуется информация о новой записи в блог,
состоящая из двух, а может быть, даже трех фрагментов.
Date
Данные передаются
РНР-сценарию через
запрос i^ax.
^
Дата записи.
Body
Date; 10/04/2008
Body; "I'm really looking..." ■
Image;
Тело записи.
Image
Присоединенное изображение.
Клиентский код JavaScript
должен преобразоват ь данные
о ф о р м а т , пригодный для
от правки на сервер в виде
запроса Ajax.
Всю эту информацию нужно упаковать и отправить на сервер
в виде запроса Ajax. Там он будет обработан и сохранен в файл
blog.xml.
\iZ 3j
Сервер п о л уч а ­
ет запрос A jax
и передает данные
сценарию РНР для
обработки.
<entry>
<blog>
<author>..
<entries>
<entry>
На эт ой с т а дии новая запись
уже добавлена
о ф айл blog.xml
и авт ом ат и­
чески отобра зит ся в блоге
УоиСиЬе после
перезагрузки
страницы.
594
глава 12
blog.xml
<date>10/04/2008</date>
<body>I'm really looking...</body>
<imageX/image>
</entry>
Сценарий PHP преобразует
запись блога в ф о р м а т X M L
и сохраняет ее в ф айл blog.xml.
Теперь нужно понять, как должна выглядеть веб-страница,
интерфейс которой позволяет выполнять ввод новых записей,
а потом собирает информацию и передает ее на сервер при
помощи запроса Ajax. К счастью, нам практически ничего не
потребуется делать в ответ на запрос, кроме разве что под­
тверждения об успешном сохранении новой записи.
динамические данные
реш ение упражнения
возьми В руку карандаш
'ешение
Вот к а к вы глядит веб-страница блога YouCube, пред назначен­
ная для добавления новы х записей.
Данны й запрос A jax от носит ся к т и п у
PO ST и сост оит из следую щ их ф р а гм ен ­
тов:
Страница для до~
оавления записи
содержит ф орм у
с нужными полями.
* Д а т а записи
* Тело записи
YouCube ~ Addif« to the Шод fof Cubt Poaaiefs .
YouCube - Adding to the Blog for Cube Puidcrs
Паю: |l0/04/Z008~_____________________________________
Body: jfm renlly ipoking forward to
f
this puzile paRy al the end of the month
* Изображение (не обязательно)
Введенные данные
пересы лаю т ся на
сервер при помощ и
запроса т ипа PO ST
Щ елчок на
кнопке A d d
приводит
к от правке
запроса A jax
О т в ет на запрос
A jax не возвращ ает
никаких данных, т ак
как в наш ем случае
эт ого не т ребует ся
Сервер записы вает
новое содержимое
олога в виде дан­
ных ф орм ат а XML
о ф айл blog.xml.
596
глава 12
динамические данные
ОшпраВка данных на сервер
Запрос POST сложнее запроса GET, так как связан с от­
правкой данных на сервер. О н поддерживает различ­
ные способы упаковки информации, но для нас вполне
подойдет стандартное кодирование URL. Именно при
помощи этой техники браузеры передают на сервер
поля данных в адресе U R L веб-страницы. Ее можно от­
личить по символу (&), используемому для разделения
фрагментов данных.
Date: 10/04/2008
Body: "I'm really looking.
Image:
щ ш т
у ------------------------"date=10/04/2008&body=I’m really looking forward... simage="
Ф рагмент ы данных
"от деляю т ся друг от
друга сим волом &■
О т дельны й ф р а гм ент
данных сост оит из и м е ­
ни и значения.
В этом формате данных все фрагменты состоят из имени
и значения, разделенных знаком (=), а каждая пара имя/зна­
чение отделена знаком (&). Формат называется закодирован­
ным U R L и имеет свой собственный тип данных, который
указывается в запросе Ajax POST.
Это официальный
т и п данных закоди - рованного URL, ко­
торый указывает ся
при формировании
запроса POST.
"application/x-www-form-urlencoded; charset~UTF-8"
Итак, все готово для написания кода запроса и его отправки
на сервер, где данные будут сохранены в файл blog.xml.
Приведите показанные ниже фрагменты данных в формат закодированного URL, под­
ходящий для создания запроса post.
releaseDate: 01/13/1989
title: Gleaming the Cube
director; Graeme Clifford
далее *
597
удовлетвори свое лю бопы т ст во
Вот как будут вы глядеть ф рагменты данны х в формате закодированного URL,
ненке
^юдходящего для создания запроса P O S T .
"решение
releaseDate: 01/13/1989
title: Gleaming the Cube
director: Graeme Clifford
C liffo rd "
_
Часщо
^аД аБ аеМ ы е
Б оЦ росьі
Если сценарий добавления записи
в блог не требует данных с сервера
в ответ на запое Ajax, зачем нам
обрабатывать этот запрос?
! Нам важно узнать, что запрос был
успешно завершен. Ведь именно эта
информация сигнализирует сценарию,
что можно отобразить всплывающее окно
с подтверждением добавления новой
записи в блог.
Можно ли в сценарии добавления
записи использовать еще и запрос
GET?
Так как обработка запроса Ajax
и сохранение записи занимают
некоторое время, что будет при щелчке
на кнопке Add до завершения запроса?
Q ; Каждый щелчок на кнопке Add
отменяет текущий запрос и отправляет
новый. Хотя можно представить
и преднамеренный двойной щелчок,
в интерфейсе имело бы смысл
предусмотреть, чтобы эта кнопка
становилось недоступной до завершения
запроса. То есть код добавления новой
записи должен отключать кнопку Add
на время обработки запроса, а затем
активировать ее снова. Подобные
усовершенствования интерфейса
I
Технически это возможно. Допустимо
приложений JavaScript сделают работу
отправлять данные на сервер вместе
более интуитивной и простой и, как
с запросом G E T , но нужно точно
результат, осчастливят пользователей.
указывать URL этого запроса. Впрочем,
это не проблема — проблема в том,
Что происходит с пробелами
что запрос GET не предназначен для
в данных, форматируемых
ситуаций, когда меняется состояние
в закодированный URL?
сервера. А в случае добавления записи
в файл blog.xml определенно можно
говорить об изменении состояния. Именно
поэтому нужно использовать запрос
являются проблемой, так как Ajax
P O S T , недвусмьюленно указывающий
на намерение взаимодействовать
с сервером.
обрабатывает данные автоматически
и гарантирует корректность формата
с точки зрения сервера.
598
глава 12
Q l Пробелы в данном случае не
Всегда ли при передаче данных
на сервер к ним нужно добавлять
изображение?
0 ; Нет, этого можно не делать. Вполне
допустимо отправлять пустые фрагменты
данных, у которых после знака равенства
в закодированном URL ничего не стоит:
"date=...&Ьоау=...&1таде="
В данном примере содержимое поля
с изображением отправляется на сервер,
хотя и не содержит данных. Далее
начинается работа РНР-сценария на
стороне сервера, который достаточно
интеллектуален, чтобы увидеть, что
в поле ничего не было введено,
соответственно, новая запись в блог не
сопровождается картинкой.
динамические данные
Возьми S руку карандаш
З а к о н ч и т е н а п и с а н и е к о д а ф у н к ц и й a d d B l o g E n t r y ()
и h a n d l e R e q u e s t () в с ц е н ар и и д о б а в л е н и я записей
в блог YouCube.
function
addBlogEntryо
//
Отключение
//
Пересылка
кнопки
новой
{
Add
и
записи
ajaxReq.sendC'POST",
присвоение
блога
в
виде
if
handleRequestO
Включение
//
Подтверждение
alert("The
кнопки
new
Add
и
==
entry
4
&&
очистка
добавления
blog
busy
Ajax
handleRequest,
charset=UTF-8",
{
(ajaxReq.getReadyState0
//
значения
запроса
"addblogentry.php",
"application/x-www-form-urlencoded;
function
статусу
записи
was
a j a x R e q . g e t S t a t u s ()
==
2 00)
{
статуса
в
блог
successfully
added.
далее ►
599
реш ение упражнения
Возьми в руку карандаш
Решение
Вот как выглядят функции addBlogEntry {) и handleRequest ()
из сценария добавления в блог YouCube записей.
В процессе сохранения новой з а ' писи кнопка A d d от клю чает ся.
8 ст роке состояния о т о ­
бражается сообщение
« b u sy» , чтобы пользоват ель
f u n c t i o n a d d B l o g E n t r y () {
знал, чт о идет загрузка.
//
Отключение
кнопки Add
и
присвоение
статусу
значения
busy
= tru e ;
Сценарий РНР и с ­
пользует ся для
■сохранения з а п и ­
си блога в файле
на сервере.
Это
запрос
POST. ■
//
Пересылка
новой
записи
блога
в
виде
запроса
------------ ^
Ajax
-------------- ---------------
ajaxReq.sendC'POST",
"addblogentry.php",
"application/x-www-form-urlencoded;
handleRequest,
charset=UTF-8",
-f docum ent.getE iem entB yld("date“).value +
“&hody=" + docum ent.getE lem ent3yld("body").value +
"&:image=" + docum ent.getElem entByld("im age").value
—•—
function
if
handleRequestO
{
(ajaxReq.getReadyState 0
//
Включение
кнопки
Сборка данных запро са POST из полей формы
date, body и image.
Add
и
==
4
&&
очистка
a j a x R e q .g e t S t a t u s ()
==
200)
{
статуса
^
П роверка
-- ре-зульт ат ов
= false;
.
,
................................
выполнения
docum ent.getElem entByldC 'status").innerH TM L ?
запроса на
............................................. 'Д'" (^охранение
записи.
//
Подтверждение
alert("The
new
добавления
blog
entry
записи
was
в
блог
successfully
added.");
Включение кнопки A d d
и очистка ст роки сост оя­
ния указы вает на заверш е­
ние процедуры сохранения.
600
глава 12
динамические данные
Вести блог легко
Руби не может поверить, насколько проще стало обновлять
блог. Ведь ей больше не нужно открывать файл, редактировать
код и загружать новую версию файла на сервер. Блог теперь не
только управляется данными, но дарит вдохновение для новых
записей!
ввв
Сообщение подтверждает
успешное сохранение новой
записи.
_ VouCabe-
The new Ы09 entry was suceessfuBy added.
YoaCube - Adding to the Blog for Cubc P u/ders
__________
РакЫо^/гоов
Body: p'm realiy looking
at th* m d of th*
Icnage (opto^);
ІдЗЗле Newr f g j i s i j '
Динамиче­
Руби делает новые
записи прям о на
ст ранице в браузере.
Пользователь
видит, что
добавляется
новая запись.
ские данные
великолепны!
Новая запись по­
является в блоге
V
^Y ouC ube.
YouCube - The И09 fo ' Cube 1>ии 1ег5
в в в ,._
у оаСвЬе - The Blog for Cube РииЛеи
Search ihe Bag '
rm1^1ookingf«ward»tep»*pa«ya<<>»«dofe««ona..
by Pussier Ruby
These
ju« keep getting w eM er.,.ow I » seeing a cube ^ e itself ара«. What
doesitirean?
b y P a a k ’-Ruby
9m m m
I dteamed last night a huge cHbe was
by P v ^ r Ruby
9/19/200S
j,
„
chastog me, and it kept yelimg my паив backwajds-.Ybm-t
a !іюп* but the new cube Й finally solved!
byPuaJerRuby
далее ►
601
удобст во применения как козырь
А ^ е ш 1л
работу с блогом еще удобнее
Невозможно достичь подлинного мастерства в сборке головоломок без
скрупулезного внимания к деталям. Не удивительно, что Руби хочет довести
страницу добавления записей до совершенства. Она узнала, что приложения
Ajax известны внимательным отношением к мелочам, влияющ^им на удобство
работы. И теперь хочет сделать свой блог конкурентоспособным по отноше­
нию к современным удобным веб-страницам.
Я хочу увеличить Э ф ­
фективность добавления
записей,чтобы писать
в блог быстрее и чаще.
Дорабатывает ввод данных в блог
Так как большинство записей датируются текущим
днем. Руби решила сэкономить время, включив автоза­
полнение первого поля. А раз дата в результате будет
вставляться автоматически, фокус ввода имеет смысл
переместить на поле для сообщений. Это даст воз­
можность приступить к набору новой записи сразу же
после загрузки страницы. Разумеется, эти изменения не
критичны для работы блога, они даже не связаны непо­
средственно с Ajax, но они позволяют чувствовать себя
на странице более комфортно, что идеально отвечает
духу Ajax.
Автоматическая
подстановка в поле
текущей даты.
VouCube * Adding to the Ш09 for Cube Puzzjers
YouCube / Adding to the Blog for Cube Puzzlers
Date|io/11/2008
__________ _ _ _ _ _ _ _
~
Image (optional);|
Ф о кус ввода у с т а н о в и м
на э т о по л е , чт о б ы рцби
602
глава 12
Add the Mew Biofl Entry |
.............
- I
О
динамические данные
АВтозаполнение полей
Если помните, в блоге YouCube используется формат
данных ММ/ДД/ГГГГ, значит, именно его нужно ис­
пользовать для автоматического заполнения поля даты.
Метод Date уже создан, но он свя­
зан с главной страницей блога YouCube.
Можно ли использовать его для допол
нительных страниц?
По в т о р н о е использование кода предотвращает
его дублирование.
Нам совершенно не нужен повторяюш,ийся код, ко­
торый придется в случае чего редактировать в раз­
ных местах страницы, поэтому имеет смысл настро­
ить совместное использование двумя страницами
фрагмента кода, ответственного за форматирование
даты.
y jT V P M
Каким образом организовать совм естное исполь­
зование метода S h o r t F o r m a t () разными стр а­
ницами блога?
далее >
603
импорт и экспорт
Повторяющаяся задача?
Совместное использование K O f l a J a v a S c r i p t различными страницами
вынуждает нас поместить такой код в отдельный файл или модуль,
который затем будет импортироваться на каждую страницу. В ы уже
видели, как это делается, на примере объекта A j a x R e q u e s t , храняще­
гося в файле a ja x .js. Вот как он импортируется:
Имя внешнего файла
JavaScript присвоено
а т р и б ут у src т ега
<script>.
<script type="text/javascript" src="ajax.js"> </script>
Для импорта
кода JavaScript
из внешнего файла
воспользуемся рке
знакомым нам
тегом <8спр1>.
Метод s h o r t F o r m a t () объекта D a t e для этой цели поместим
в файл datejs, который затем импортируем в каждую страницу
блога YouCube.
Date .prototype.shortFormat - f u n c t i o n O
return (this. getMonthO
{
+ 1) + "/" + this.getDate () + "/" + this .getFullYearO;
Ter < s c r i p t > , который м ы использовали для кода Ajax, применим
для импорта в страницы блога сценария из файла datejs.
<script type="text/javascript" src="date.js"> </script>
Содержимое ф айла date.js
и м п о р т и р ует ся одним т егом
<script>.
Всегда имеет смысл помещать код многократного использования
во внешний файл, импортируя его затем по мере надобности.
604
глава 12
Д о хр а н и в ко д J a v a S c rip t во
внеш нем файле,, м ы п о л ц иаеум в о з м о ж н о с т ь и с -
динамические данные
.
youCu^-Ts»»oafof be
.
Y ooC uJ». The Blog for Cube Ihtucim
ffio^ jf
"■
10МЯ1008
t ot es' “
Г"
byPiKiierRuby
ш лт
Miwoee
W w jt took me a а ш й butfte nc* cube is ruMlly soh-ed:
нд странице
(Подавления новых записей.
Q0
Y o u C u b e - A d d i n g t o I h c B lo g f o r C u b e P u i d c r s
im age (optional): Г
A d d t h e N w S t e 9 £ n g ! Lj
возьми в руку карандаш
Напишите код функции i n i t F o r m ( ) , вызываемой обработчиком
события o n l o a d в сценарии добавления записей в блог. Функция
должна вставлять в первое поле текущую дату и устанавливать
фокус ввода на втором поле.
далее >
605
реш ение упражнения
Возьми в руку карандаш
'ешение
Вот как выглядит функция initForm ( ) , осуществляющая
автозаполнение поля date и установку фокуса ввода на поле
body.
в поле date появляется
текущая дата.
Date()).shortFormat();
Г
Ф о кус ввода у с т а ­
навливает ся на
поле body.
document.getElementByldC'body").Focus();
}
Сразу после загрузки
страницы фокус ввода
устанавливается на
поле body.
Увеличение продуктивности
Наконец-то Руби довольна тем, как работает ее блог YouCube.
Благодаря Ajax он управляется данными, имеет дружелюбный
интерфейс и внимателен к деталям, которые может оценить
только настоящий фанат головоломок.
Adding to
После открытия
страницы в поле
date автоматически
появляется текущая
дата.
th e В % fo r
Cube Р и г г 1 е ^ “
Oaie:fio7i?l5o08
З Ш
.
Y o u C u b e -T h e
Search theBog
flnaily flnistad wfflkiog OB tl» blog scnpti
byPaakrRuh
rm ^ ^ ^ look m g foiward xo this puzitle paity at «ic end o f 4 » mon*.
by PuzxUr Ruby
9№ Ю Ш
by Pmder Ruby
Done
606
глава 12
T h « (teams just keep geniiig weWer...now I'm seeingacube take itself apart, Whal
lioesitraean?
Download