Text
                    А. В. ДИКОВ

WEB-ПРОГРАММИРОВАНИЕ
НА JAVASCRIPT
УЧЕБНОЕ ПОСОБИЕ

САНКТ-ПЕТЕРБУРГ•МОСКВА•КРАСНОДАР
2026


УДК 004.43 ББК 32.973.26-18.1я73 Д 45 Диков А. В. Web-программирование на JavaScript : учебное пособие для вузов / А. В. Диков. — Санкт-Петербург : Лань, 2026. — 436 с. : ил. — Текст : непосредственный. ISBN 978-5-507-54625-1 Язык JavaScript является самым популярным и развивающимся языком разработки сценариев для веб-браузера. Он относится к одной из базовых фронтенд технологий. В учебном пособии делается акцент на современные стандарты языка ES. Учебное пособие предназначено и для освоения основ современного объектного программирования, и для знакомства с технологией расширения функционала веб-страниц и придания им динамичности и интерактивности на уровне клиента. В последнем случае требуется наличие знаний других базовых фронтенд технологий HTML и CSS. В учебном пособии изложение ведется в форме лекций и практических работ. Большое число практических задач отобрано с популярного социального сервиса Codewars, в котором можно проверить решения в автоматическом режиме через систему тестов. Для студентов, аспирантов и преподавателей университетов, в которых ведется подготовка в области информационных технологий. УДК 004.43 ББК 32.973.26-18.1я73 Автор: А. В. Диков — кандидат педагогических наук, доцент кафедры информатики и методики обучения информатике и математике Пензенского государственного университета (https://dikandr.ru). Обложка П. И. ПОЛЯКОВА © Издательство «Лань», 2026 © А. В. Диков, 2026 © Издательство «Лань», художественное оформление, 2026
Оглавление ВВЕДЕНИЕ ................................................................................................ 6 СОБЫТИЯ ................................................................................................. 9 ОЧЕРЕДЬ СОБЫТИЙ ................................................................................. 13 ОБЪЕКТ СОБЫТИЙ EVENT ....................................................................... 15 ПРАКТИЧЕСКАЯ РАБОТА НА СОБЫТИЯ ................................................... 18 ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ .......................................................... 22 ТИПЫ ЗНАЧЕНИЙ И ПЕРЕМЕННЫХ .......................................................... 23 Числовой тип (целые числа и с плавающей запятой) .................... 23 Числовой тип BigInt.......................................................................... 25 Логический или булевый тип (true/false) ........................................ 26 Строковый тип .................................................................................. 26 СОКРАЩЕННАЯ АРИФМЕТИКА .................................................... 30 КОМБИНИРОВАННЫЕ ОПЕРАТОРЫ ПРИСВАИВАНИЯ .............................. 30 ФУНКЦИИ ПРЕОБРАЗОВАНИЯ ....................................................... 32 ПРАКТИЧЕСКАЯ РАБОТА НА ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ ........................ 36 КОНСТАНТЫ ......................................................................................... 44 ШАБЛОННЫЕ СТРОКИ ..................................................................... 45 ПРАКТИЧЕСКАЯ РАБОТА НА ШАБЛОННЫЙ ЛИТЕРАЛ ............................. 46 ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННОЙ ...................................... 50 ЛИНЕЙНЫЕ АЛГОРИТМЫ ............................................................... 52 ПРАКТИЧЕСКАЯ РАБОТА НА ЛИНЕЙНЫЕ АЛГОРИТМЫ ............................ 54 ЦИКЛИЧЕСКИЕ АЛГОРИТМЫ ........................................................ 56 ОПЕРАТОРЫ ЦИКЛА ................................................................................ 57 МЕТКИ, BREAK, CONTINUE ...................................................................... 62 ПРАКТИЧЕСКАЯ РАБОТА НА ЦИКЛ .......................................................... 64 ВЕТВЯЩИЕСЯ АЛГОРИТМЫ........................................................... 72 УСЛОВНЫЙ ОПЕРАТОР ............................................................................ 73 3
ТЕРНАРНЫЙ ОПЕРАТОР ........................................................................... 75 ОПЕРАТОР МНОЖЕСТВЕННОГО ПЕРЕХОДА ............................................. 75 ПРАКТИЧЕСКАЯ РАБОТА НА УСЛОВНЫЙ ОПЕРАТОР .............................. 79 ПРАКТИЧЕСКАЯ РАБОТА НА ОПЕРАТОР SWITCH-CASE ........................... 85 ПРАКТИЧЕСКАЯ РАБОТА НА ТЕРНАРНЫЙ ОПЕРАТОР ............................. 94 МНОГООБРАЗИЕ ФУНКЦИЙ ......................................................... 104 АНОНИМНЫЕ ФУНКЦИИ ....................................................................... 111 АНОНИМНАЯ ФУНКЦИЯ КАК ОБРАБОТЧИК СОБЫТИЯ .......................... 112 СТРЕЛОЧНЫЕ ФУНКЦИИ ....................................................................... 113 ФУНКЦИИ ВЫСШЕГО ПОРЯДКА............................................................. 114 Функции обратного вызова ............................................................ 114 ФУНКЦИЯ КАК ОБЪЕКТ ......................................................................... 117 ПРАКТИЧЕСКАЯ РАБОТА НА ФАБРИЧНЫЕ ФУНКЦИИ ........................... 123 ПРАКТИЧЕСКАЯ РАБОТА НА ЗАМЫКАНИЯ ............................................ 126 ПРАКТИЧЕСКАЯ РАБОТА НА ФУНКЦИИ ................................................. 128 ПРАКТИЧЕСКАЯ РАБОТА НА ФУНКЦИИ ВЫСШЕГО ПОРЯДКА И ОБРАТНОГО ВЫЗОВА......................................... 133 МАТЕМАТИКА НА ВЕБ-СТРАНИЦАХ. ОБЪЕКТ MATH ......... 139 ДИНАМИЧЕСКОЕ ИЗМЕНЕНИЕ СПИСКА ................................................. 146 ПРАКТИЧЕСКАЯ РАБОТА ....................................................................... 148 МАССИВЫ ............................................................................................ 153 ОСНОВНЫЕ СВОЙСТВА И МЕТОДЫ ОБЪЕКТА ARRAY ........................... 155 ПЕРЕБИРАЮЩИЕ МЕТОДЫ ОБЪЕКТА ARRAY ........................................ 160 ВЛОЖЕННЫЕ МАССИВЫ........................................................................ 165 ДЕСТРУКТУРИЗАЦИЯ МАССИВА............................................................ 166 ПРАКТИЧЕСКАЯ РАБОТА НА ДЕСТРУКТУРИЗАЦИЮ МАССИВА ............. 168 ПРАКТИЧЕСКАЯ РАБОТА НА МАССИВЫ ................................................ 170 ПРАКТИЧЕСКАЯ РАБОТА НА МЕТОДЫ INDEXOF & LASTINDEXOF ....... 184 ПРАКТИЧЕСКАЯ РАБОТА НА ПЕРЕБИРАЮЩИЕ МЕТОДЫ МАССИВА ...... 185 ДОПОЛНИТЕЛЬНЫЕ ЗАДАЧИ В ОНЛАЙН ТРЕНАЖЕРЕ CODEWARS ........ 197 ПРАКТИЧЕСКАЯ РАБОТА НА ДВУМЕРНЫЕ МАССИВЫ ........................... 198 ПРАКТИЧЕСКАЯ РАБОТА НА ВЛОЖЕННЫЕ ЦИКЛЫ ................................ 200 ПРАКТИЧЕСКАЯ РАБОТА НА СОРТИРОВКУ ............................................ 206 ОПЕРАТОР РАСШИРЕНИЯ ............................................................. 211 ПРАКТИЧЕСКАЯ РАБОТА НА ОПЕРАТОР РАСШИРЕНИЯ И REST ПАРАМЕТРЫ ........................................................ 213 СТРОКИ. ОБЪЕКТ STRING .............................................................. 217 4
ПРАКТИЧЕСКАЯ РАБОТА НА СТРОКИ .................................................... 226 ДОПОЛНИТЕЛЬНЫЕ ЗАДАЧИ В ОНЛАЙН ТРЕНАЖЕРЕ CODEWARS ........ 241 ПРАКТИЧЕСКАЯ РАБОТА НА ВЛОЖЕННЫЙ ЦИКЛ .................................. 242 РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ ......................................................... 244 ПРАКТИЧЕСКАЯ РАБОТА НА REGEXP ................................................... 254 ПРАКТИЧЕСКАЯ РАБОТА НА REPLACE С КОЛБЭК ФУНКЦИЕЙ ............... 264 МНОЖЕСТВА....................................................................................... 266 УДАЛЕНИЕ ИЗ МАССИВА ПОВТОРЯЮЩИХСЯ ЭЛЕМЕНТОВ................... 269 ПРАКТИЧЕСКАЯ РАБОТА НА МНОЖЕСТВА ............................................ 269 ОБЪЕКТЫ РАЗРАБОТЧИКА ........................................................... 276 ТИП ДАННЫХ СИМВОЛ ......................................................................... 285 ПРАКТИЧЕСКАЯ РАБОТА НА ОБЪЕКТЫ .................................................. 287 ПРАКТИЧЕСКАЯ РАБОТА НА МАССИВЫ ОБЪЕКТОВ ............................... 300 ДЕСТРУКТУРИЗАЦИЯ ..................................................................... 317 MAP ..................................................................................................... 319 ДАТА И ВРЕМЯ. ОБЪЕКТ DATE ..................................................... 322 ПРАКТИЧЕСКАЯ РАБОТА НА ДАТУ И ВРЕМЯ ......................................... 328 КЛАССЫ ................................................................................................ 334 ПРАКТИЧЕСКАЯ РАБОТА НА КЛАССЫ ................................................... 345 ДОПОЛНИТЕЛЬНЫЕ ЗАДАЧИ В ОНЛАЙН ТРЕНАЖЕРЕ CODEWARS ........ 367 ИТОГОВАЯ ПРАКТИЧЕСКАЯ РАБОТА ..................................................... 367 ОБЪЕКТНАЯ МОДЕЛЬ БРАУЗЕРА ................................................ 383 ПРАКТИЧЕСКАЯ РАБОТА НА ОБЪЕКТЫ БРАУЗЕРА ................................. 409 ОБЪЕКТЫ HTML-ДОКУМЕНТА .................................................... 413 ПРАКТИЧЕСКАЯ РАБОТА НА ОБЪЕКТЫ HTML-ДОКУМЕНТА.................. 428 ЛИТЕРАТУРА....................................................................................... 435 5
ВВЕДЕНИЕ Наиболее известными скриптовыми языками на сегодняшний день являются JavaScript, JScript (аналог языка JavaScript от Microsoft), VBScript (Visual Basic Script от Microsoft) и ActionScript (от компании Macromedia). Скриптовый язык — это объектно-ориентированный язык программирования, который добавляет интерактивность, обработку данных, управление браузером и многое другое в содержимое разрабатываемых веб-страниц или flash-приложений (ActionScript). Скриптовый язык не содержит всех возможностей обычных языков программирования, таких, например, как работа с файлами или управление графикой. Созданные с помощью скриптовых языков программы работают в браузерах, поддерживающих их выполнение. Создаваемые на скриптовых языках программы, называемые сценариями или скриптами, включаются в состав веб-страниц и распознаются и обрабатываются браузером отдельно от остального html-кода. Браузер, встречая ошибки в скриптах, выдает сообщения об этом в консоли инструментов веб-разработчика. ActionScript может компилироваться в код для хранения в SWF-файле. SWF-файлы исполняются программой Flash Player, которая существует в виде плагина к веб-браузеру. Язык JavaScript разработан в 1995 г. фирмой Netscape в сотрудничестве с Sun Microsystems на базе языка Sun's Java*. По инициативе компании Netscape была проведена стандартизация языка ассоциацией ECMA. Стандартизированная версия имеет название ECMAScript (сокращенно ES). Первой версии спецификации ES1, появившейся в 1997 г. соответствовал JavaScript версии 1.1. Всего существует 8 версий ES. Режим strict (строгий режим), введенный в ECMAScript 5, позволяет использовать более строгий вариант JavaScript. * Название Java было дано языку в честь любимой разработчиками марки кофе. 6
Операторы JavaScript размещаются в контейнере <SCRIPT> и разделяются символом ”;” в рамках одной строки. Для браузеров, не поддерживающих скрипты, операторы заключают еще в теги комментариев языка HTML, чтобы они не были видны посетителю при просмотре веб-страницы. Контейнер, содержащий скрипт, можно добавлять в любой раздел html-документа. Версии ES 1997 – ES1 1998 – ES2 1999 – ES3 ES4 не принята 2009 – ES5 2015 – ES2015 2016 – ES2016 2017 – ES2017 Часто вызываемые функции лучше добавлять в заголовочный раздел, так как браузер будет выполнять их быстрее (поиск функций браузером осуществляется сверху вниз). <SCRIPT> document.write ("Это JavaScript!") </SCRIPT> Приведенный скрипт выводит на веб-страницу текстовую строку «Это JavaScript!». Подробное объяснение метода write объекта document можно найти на странице 416. Комментарии JavaScript отличаются от комментариев языка HTML. // комментарии на одной строке /* комментарии на нескольких строчках */ Комментарии могут быть использованы для отладки сценариев. Кроме комментариев можно использовать метод log объекта console, который выводит в консоль браузера значение . console.log(), где  — выражение или переменная. <SCRIPT> console.log (2+3) // 5 console.log ("это Javascript") // это Javascript console.log ("привет, Мир"+" я твой герой") 7
// привет, Мир я твой герой console.log ("корень квадратный из 4 = " + Math.sqrt(4)) // корень квадратный из 4 = 2 </SCRIPT> Консоль в браузере вызывается либо функциональной клавишей F12, либо с помощью меню. Язык чувствителен к регистру при задании значений параметров! Вопросы и упражнения 1. Создайте скрипт, выводящий на веб-страницу четверостишье из известного стихотворения М. Ю. Лермонтова «Парус». 2. Вывести в консоль браузера значения выражений a. 125.3*5; b. корень квадратный из 63; c. «Как посеешь, так и пожнешь». 3. Создайте скрипт, выводящий на веб-страницу список из 5 фруктов, растущих в России 8
СОБЫТИЯ Веб-страница, содержащая скрипт, позволяет обрабатывать события, связанные с окном браузера, — такие как загрузка документа, закрытие окна, появление курсора над объектом страницы, нажатие клавиши мыши или клавиатуры и другие. Скрипт может по-разному реагировать на эти события. Скриптовые программы иногда еще называют сценариями просмотра веб-страницы. Базовые события JavaScript onAnimationEnd окончание анимации (для css-свойства animation) onAnimationIteration повторение анимации onAnimationStart начало анимации (для css-свойства animation) DOMContentLoaded документ завершил загрузку (но не его зависимые ресурсы) onbeforeUnload событие перед закрытием окна браузера или переход на другую страницу <body onbeforeunload = "return Func()"> onBlur элемент теряет фокус onChange изменение значения текстового поля и выбранного элемента списка select onClick щелчок мышкой в области элемента onCopy копирование в буфер обмена onFocus элемент получает фокус 9
Продолжение табл. Базовые события JavaScript onInput изменение содержимого текстового поля. Событие происходит сразу после изменения содержимого, а событие onChange происходит, когда элемент теряет фокус onKeyDown пользователь нажимает клавишу на клавиатуре onKeyPress пользователь нажимает клавишу на клавиатуре. Работает не для всех клавиш (например, ALT, CTRL, SHIFT, ESC). Событие onkeydown работает для всех клавиш const keyName = Event.key alert('keypress event\n\n' + 'key: ' + keyName) // Enter onKeyUp пользователь отпускает клавишу на клавиатуре onLoad завершение загрузки страницы или графического изображения onMouseDown нажатие кнопки мыши onMouseMove перемещение мышиного курсора в области элемента onMouseOut перемещение мышиного курсора за область элемента onMouseOver перемещение мышиного курсора на область элемента onMouseUp отпускание кнопки мыши onContextMenu щелчок правой кнопкой мыши по элементу 10
Продолжение табл. Базовые события JavaScript onDblClick двойной щелчок по элементу onMouseEnter указатель мыши входит в элемент. Событие onmouseenter аналогично событию onmouseover. Разница в том, что событие onmouseenter не всплывает (не распространяется вверх по иерархии элементов) onMouseLeave указатель мыши покидает элемент onDrag перетаскивается элемент или выделенный текст (каждые 350 мс) onDragEnd перетаскивание завершается (отпуская кнопку мыши или нажимая клавишу Escape) onDragEnter перетаскиваемый элемент или выделенный текст попадают в допустимую цель перетаскивания onDragLeave перетаскиваемый элемент или выделенный текст оставляет допустимую цель перетаскивания onDragOver элемент или выделенный текст перетаскивается на допустимую цель (каждые 350 мс) onDragStart начало перетаскивания элемента или выделенного текста onDrop элемент падает в допустимую цель перетаскивания onReset нажатие кнопки типа RESET onResize изменение размера окна браузера, применяется для объекта window 11
Продолжение табл. Базовые события JavaScript onScroll перемещение ползунка линейки прокрутки onSelect выделение текста в текстовых полях с помощью мыши или клавиатуры onSubmit нажатие кнопки типа SUBMIT onTransitionEnd окончание анимационного перехода (для css-свойства transition) onUnload переход на другую страницу или завершение работы браузера События, как и атрибуты, связываются с тегами языка HTML и не заключаются в контейнер <SCRIPT>. <IMG SRC=“smile.gif” onMouseOut=“верни_изо ()”> onMouseOver=”смени_изо ()” <SELECT SIZE=“7” onClick="ch_pict ()"> <BODY onLoad="ss (); clock ()"> <FORM onSubmit=”return проверка_данных ()”> Из примеров видно, что каждому событию сопоставляется вызов функции, код которой должен быть включен в скрипт на языке JavaScript. Вместо имени функции можно написать небольшой фрагмент кода. <INPUT TYPE="button" VALUE="Щёлкни по мне" onClick=’alert ("Куку")’> Команда alert () выводит диалоговое окно с сообщением. В качестве аргумента можно указывать имена переменных или выражения. Тогда в окне будет размещено значение переменной или выражения. 12
Операторы JavaScript могут также размещаться в качестве значения параметра href тега гиперссылки. <A HREF="javascript: window.alert('Do you speak English?')"> "Don`t click here" </A> Если нам необходимо выполнить некоторые действия при выборе гипертекстовой ссылки, но при этом не перегружать текущие страницы, то в параметре HREF можно указать конструкцию: <A HREF="javascript:void(0)"> kuku </A> Код JavaScript может быть еще размещен и во внешнем файле (расширением js или jsc). При загрузке веб-страницы этот код докачивается программой просмотра и исполняется так же, как если бы он размещался в самом html-документе. При просмотре текста документа через опцию «Источник» текст скрипта не отображается. В файле, который содержит конструкции JavaScript, HTML-теги не используются. <SCRIPT SRC=”timer.js”> </SCRIPT> Для написания скриптов, управляющих содержимым веб-страницы, необходимо представлять себе иерархию объектов HTML-документа. Управление содержимым веб-страницы после ее загрузки на компьютер клиента лежит в основе технологии Dynamic HTML. JavaScript вместе с каскадными таблицами стилей (CSS) составляют фундамент этой технологии. Очередь событий Если произошло несколько событий одновременно или во время обработки одного события случилось другое, браузер поставит обработку событий в очередь. Иногда события добавляются в очередь сразу пачкой. Например, при клике на элементе генерируется несколько событий: сначала onMouseDown — нажата кнопка мыши, затем onMouseUp — кнопка мыши отпущена и onClick (два события сразу). Браузер обработает их в следующем порядке: mousedown → mouseup → click. При этом каждое событие из очереди обрабатывается полностью отдельно от других. Веб-страница представляет собой иерархическое дерево htmlэлементов. Можно выделить родительские и дочерние элементы. Дочерние — это те элементы, которые вложены в родительский контей- 13
нер. У родителей могут быть и дальние потомки, что зависит от глубины вложенности элементов. Когда происходит событие на вложенном элементе, обработчики JS сначала срабатывают на нем, потом на его родителе, затем выше и так далее, вверх по цепочке предков. Этот процесс можно назвать всплытием события. div ul li a click В скрипте можно узнать, на каком вложенном элементе произошло событие с помощью объекта event и свойства target. Свойство currentTarget вернет родительский элемент до которого дошло всплытие события. В JS есть еще одно служебное слово, дающее родительский элемент, вызвавший событие — this. Пример <SCRIPT> function fff () { alert (event.target.tagName) // CAPTION / TD / TH alert (event.currentTarget.tagName) // TABLE } </SCRIPT> <TABLE onclick = "fff ()"> <CAPTION> Прайс-лист </CAPTION> <TR> <TH>Наименование</TH> <TH>Модель</TH> <TH>Цена, р.</TH> </TR> <TR> <TD>Процессор</TD> 14
<TD>Pentium II</TD> <TD>2 800</TD> </TR> </TABLE> Объект событий Event При возникновении события браузер записывает в объект Event подробную нформацию о событии и передает ее в качестве аргумента функции-обработчику данного события. Cвойства target и currentTarget были рассмотрены в предыдущем разделе. Свойство Значение Описание только для чтения bubbles true/fralse возвращает логическое значение в зависимости от того, вспыло ли событие вверх по дереву html-элементов или нет canselBubble true/false если присвоить значение true до возврата из обработчика события, то событие не будет распространяться дальше canselable только для чтения true/false показывает возможность отмены события currentTarget возвращает ссылку на родительский элемент до которого дошло всплытие события target возвращает ссылку на элемент, на котором произошло событие до всплытия type название события без учета регистра символов defaultPrevented показывает, была ли для события вызвана функция preventDefault() только для чтения isTrusted true/false 15 показывает было ли событие инициировано браузером (например, по клику мышью) или из скрипта
Продолжение табл. Метод eventPhase Значение Описание NONE = 0 CAPTURING_PHAS E=1 AT_TARGET = 2 BUBBLING_PHASE =3 отображает текущую фазу процесса обработки события createEvent() создает новое событие preventDefault() отменяет событие (если это возможно) stopImmediatePropagation() для данного события не будет больше вызвано обработчиков stopPropagation() остановка распространения события по дереву htmlдокумента Для событий, связанных с действиями мышки, существуют следующие свойства объекта Event Свойство Значение Описание clientX число отображает X координату курсора мыши относительно окна браузера clientY число отображает Y координату курсора мыши относительно окна браузера offsetX число отображает X координату курсора мыши относительно html-элемента offsetY число отображает Y координату курсора мыши относительно html-элемента pageX число отображает X координату курсора мыши относительно htmlдокумента pageY число отображает Y координату курсора мыши относительно htmlдокумента Пример <STYLE> #house { 16
position: relative; top: 500px; left: 500px; width: 300px; border:0px solid red; } #wall { box-sizing: border-box; width: 300px; height: 350px; border: 10px solid black; } #cover { width: 0px; height: 0px; border-left: 150px solid transparent; border-right: 150px solid transparent; border-top: 150px solid transparent; border-bottom: 150px solid violet; } </STYLE> </HEAD> <BODY> <DIV ID="house"> <DIV ID="cover"></DIV> <DIV ID="wall"></DIV> </DIV> <SCRIPT> house.onmousemove = function(v) { console.log(v.clientX + " : " + v.clientY); } </SCRIPT> В консоль скрипт будет выводить текущие координаты мышиного курса окна браузера при движении мышки в области элемента house. Переменная-параметр v — это ссылка на объект Event для мышки. 17
. Практическая работа на события Задание 1. Создайте кнопку на веб-странице с надписью «Тук-тук». Напишите javascript-код, который по щелчку на кнопке выведет диалоговое окно с вопросом «Кто там?» Задание 2. Создайте скрипт, выводящий в консоль браузера текущее число введенных символов (нажатий на клавиши) в текстовое поле по событию onInput. 18
Задание 3. Разместите на веб-странице картинку и напишите javascript-код, который при помещении курсора мыши над картинкой будет выводить диалоговое окно с информацией о картинке. Задание 4. Разместите на веб-странице картинку и напишите javascript-код, который по окончанию загрузки картинки на веб-страницу выводит диалоговое окно с приветствием, а при помещении курсора мыши над картинкой будет выводить диалоговое окно с информацией о картинке. Задание 5. Разместите на веб-странице список считалок овец и сделайте каждый пункт его кликабельным. При щелчке на любом пункте должна вызываться функция, которая в цикле перечисляет всех овец по порядку. Задание 6. Создайте кнопку на веб-странице с надписью «Какая сегодня дата». Напишите javascript-код, который по щелчку на кнопке выведет диалоговое окно с ответом на этот вопрос. Задание 7. Создайте прямоугольный закрашенный блок на веб-странице и напишите скрипт, выводящий в консоль браузера информацию о событиях onclick, onmousemove, onmouseover, onmouseout. 19
Задание 8. Создайте прямоугольный блок на веб-странице и разделите его на две закрашенные разным цветом части. Напишите скрипт, выводящий в консоль браузера информацию о цвете в соответствии с тем, над каким блоком проходит курсор мыши. Задание 9. Создайте прямоугольный блок на веб-странице с несколькими вложенными блоками. Напишите скрипт, выводящий в консоль браузера информацию о теге в соответствии с тем, на каком блоке происходит щелчок мышкой. Можно использовать только одну функцию обработки события. 20
Задание 10. Разместите на веб-странице форму с текстовой областью и кнопкой Отправить. Напишите скрипт, выводящий в диалоговое окно информацию о проверке данных после щелчка по кнопке Отправить. После исчезновения диалогового окна, информация в текстовой области не должна исчезать. Задание 11. Разместите на веб-странице изображение и напишите скрипт, который будет добавлять граничную линию к той стороне картинки, рядом с которой будет перемещаться курсор мыши. 21
ПЕРЕМЕННЫЕ И ЗНАЧЕНИЯ Переменной в языке программирования называют такое слово, которое обладает каким-либо значением и это значение можно изменить в любой момент времени, а предыдущее значение будет безвозвратно потеряно. Значением переменной в JavaScript может быть либо число, либо логическое значение (true/false), либо строка, либо массив. Присвоить (изменить) значение переменной можно разными способами. В этом параграфе будем использовать оператор присваивания. Он обозначается знаком равно (=).  = , где  — имя переменной,  — значение переменной. В JavaScript переменные можно объявлять с помощью служебного слова var (или let), после которого следует имя переменной или нескольких переменных, разделенных запятой. Имена переменных, как и все другие элементы языка чувствительны к регистру. Объявлять одну и ту же переменную в скрипте можно только один раз var  [{,}] var x, y, z var угол, радиус, длина_окружности При объявлении переменной можно сразу присвоить ей значение оператором присваивания. Переменным могут быть даны различные типы значений. 22
Типы значений и переменных Числовой тип (целые числа и с плавающей запятой) var пи = 3.14 var радиус = 5.06 / 2 // 2.53 document.write ("Площадь круга = " + пи*радиус*радиус + "<br>") let сто_миллиардов = 100_000_000_000 console.log (сто_миллиардов) // 100000000000 //научная запись let нч = 3.1415782e + 21 let миллиард = 1e+9 console.log (миллиард) // 1000000000 document.write (“Научная запись ”, нч, "<br>") // восьмеричные (первая цифра ноль) var вч = 015 document.write ("015", "<SUB>8</SUB>", "->", вч, "<br>") //16-ричные (первая цифра ноль) var шч = 0x23 document.write ("0x23", "<SUB>16</SUB>", "->", шч, "<br>") В JS встроен объект Number, у которого имеется ряд интересных свойств и методов. Один из методов isInteger(α) определяет, является ли значение α целым числом. Метод возвращает true в случае успеха или false в противном случае. Number.isInteger(3 / 2) // false Свойства MAX_VALUE и MIN_VALUE объекта Number возвращают информацию о максимальном и минимальном числами, с которыми может оперировать JavaScript. document.write ('Максимальное число JavaScript = ', Number.MAX_VALUE, "<BR>") document.write ('Минимальное число JavaScript = ', Number.MIN_VALUE, "<BR>") 23
Константы Number Описание MAX_VALUE Максимальное число JS. Number.MAX_VALUE MIN_VALUE Минимальное число JS (близко к 0, но не отрицательно). Number.MIN_VALUE NaN Not a Number — не число. Возвращается, если результат арифметической операции (например, квадратный корень из отрицательного числа) или результат метода не являются числами NEGATIVE_INFINITY значение представляет отрицательную бесконечность. Возвращается когда число вычисляется в арифметической операции или функции и оно меньше, чем -Number.MAX_VALUE POSITIVE_INFINITY значение представляет положительную бесконечность. Возвращается когда число генерируется в арифметической операции или функции и оно больше, чем Number.MAX_VALUE Над числами определены следующие операции: умножение (*), деление (/), остаток от деления (%), сложение (+), вычитание (–) и возведение в степень (**). 5*x-7%2+x/5 2**3 // результат 8 9 % 2 // результат 1 24
Числовой тип BigInt Обычные числа в JavaScript хранятся в 64-битном формате, который также называют «числа с плавающей точкой двойной точности». Для хранения больших целочисленных значений, которые слишком велики, чтобы быть представленными обычными числами JavaScript используется тип BigInt — большие целые числа. Обычные целые числа JavaScript имеют точность до 15 цифр. Чтобы создать большое целое число типа BigInt необходимо добавить букву n в конец целого числа или вызвать объект BigInt() let x = 1234567890123456789012345n let y = BigInt(1234567890123456789012345) Арифметические операторы также можно использовать для BigInt. Но арифметические действия между BigInt и Number не допускаются. BigInt не может иметь десятичных знаков, поэтому при делении больших целых чисел могут возникать ошибки типа “Uncaught TypeError: can't convert BigInt to number”. Большие числа могут быть представлены в шестнадцатеричной, восьмеричной или двоичной форме. x = 5n; y = x / 2 // Uncaught TypeError: can't convert BigInt to number Константы Number Описание MIN_SAFE_INTEGER минимальное безопасное целое число // -9007199254740991 MAX_SAFE_INTEGER максимальное безопасное целое число // 9007199254740991 Безопасное целое число — это целое число, которое может быть точ-но представлено в виде числа двойной точности. Метод Number.isSafeInteger() возвращает true, если аргумент является безопасным целым числом. Number.isSafeInteger(12345678901234567890) // false 25
Логический или булевый тип (true/false) В JS предусмотрены логические значения true и false. Их также как и числа можно присваивать переменным, в результате чего переменные будут иметь логический тип. var flag = false var r = 5 < 7 // true Логические значения получаются в результате выполнения операторов сравнения == равно === идентично > больше < меньше >= больше или равно <= меньше или равно && и || или ! не За работу логических значений и переменных в JavaScript отвечает объект Boolean. Строковый тип Строка — последовательность символов алфавита языка программирования, заключенная в кавычки или апострофы (одинарные кавычки). let str1 = “JavaScript” Над строками можно выполнять операцию сложение. let newStr = str1 + “ v.6” // “JavaScript v.6” В JS можно складывать числа и строки, в этом случае он преобразует число в строку и результат выдаст строкой. let numStr = 20.53 + “ euro” // “20.53 euro” Если в кавычки или апострофы не заключить ни одного символа, будем иметь пустую строку. 26
let str2 = “” let str3 = ‘’ Каждый символ имеет порядковый номер. Первый символ строки имеет номер 0. console.log (str1[0]) // “J” console.log (str1[5]) // “c” В строку можно добавлять управляющие последовательности, такие как, например, \n переход на следующую строку \r Enter \t Tab \\ Обратная косая черта var строка="А роза упала на лапу Азора" document.write (строка,"<br>") var строка2='А \r\n роза упала на лапу Азора' alert (строка2) В JavaScript встроен объект String, который курирует работу всех строковых значений и переменных. От него можно использовать свойство length для определения числа символов в строке. “JavaScript”.length // 10 Неопределенное значение (undefined) Бывают случаи при разработке и отладке сценария, когда JavaScript выдает сообщение undefined. Это означает, что запрашиваемое значение не определено или не задано. var x console.log (x) // undefined 27
Бесконечность (Infinity/-Infinity) Иногда JavaScript в качестве значения математической функции или выражения возвращает слово Infinity, что означат бесконечность. alert (Math.log(0)) // infinity alert (-1/0) // -infinity NaN (Not a Number — не число) Если в качестве значения выражения JavaScript выдает NaN, это означает, что в результате вычисления математического выражения не получается числового значения. alert (Math.sqrt (-1)) // NaN Функция isNaN может проверить, не является ли проверяемое значение числом? var x=prompt ("Введите какое-либо значение") if (isNaN (x)) alert ("Вы ввели нечисловое значение") Про методы prompt и alert можно почитать на странице 391, про оператор if — на странице 73. null Значение null означает отсутствие какого-либо значения. В JavaScript null рассматривается как ложное. Функция В JavaScript имя функции может быть присвоено в качестве значения какой-либо переменной. function случайное_число () { x = Math.random () } let R = случайное_число document.write (R) Последняя команда в примере выведет на страницу всю конструкцию функции. 28
Для определения (проверки во время отладки) типа переменной существует оператор typeof. typeof(), где  — имя переменной любого типа. 29
СОКРАЩЕННАЯ АРИФМЕТИКА Одной из наиболее частых арифметических операций в JavaScript, как и во многих других языках программирования, является увеличение или уменьшение переменной на единицу. Для этого существуют специальные операторы инкремент и декремент: ++ (увеличивает на 1) -- (уменьшает на 1) Например, var i=5 i++ // i = i + 1 console.log (i) // 6 var x=5 x-console.log (x) // 4 Комбинированные операторы присваивания Можно использовать короткую запись увеличения или уменьшения чисел вместе с оператором присваивания var z = 7 z += 25 console.log (z) // 32 В примере используется сокращенная форма z += 25 вместо полной z = = z + 25 let n = 2 n *= 3 + 5 console.log (n) // 16 В примере после присваивания сначала выполняется сложение, а затем увеличение значения переменной n в 8 раз 30
var a = 2 console.log(--a) // 1 возвращает значение после операции console.log(a) // 1 a=2 console.log(a--) // 2 возвращает значение перед операцией console.log(a) // 1 31
ФУНКЦИИ ПРЕОБРАЗОВАНИЯ Самым легко запоминаемым способом преобразования значений одного типа в другой — использование объектов, отвечающих за свои типы. Что бы мы не дали им в качестве входного значения, они вернут тот тип, за который отвечают. Number (“123”) // 123 Boolean (“true”) // true String (123) // “123” Для преобразования (превращения) строки в целое число предусмотрена функция parseInt. parseInt ( [,]), где  — строка или элемент, возвращающий строку,  — число, задающее основание системы счисления из которой преобразуется строка  в число (по умолчанию 10). Преобразуется  всегда в 10 систему счисления. x="строка" document.write ('преобразованное в число значение ', '<B>', x, '</B>', ' = ' , parseInt(x), "<BR>") x="123строка" document.write ('преобразованное в число значение ', '<B>', x, '</B>', ' = ', parseInt(x), "<BR>") x="строка123" document.write ('преобразованное в число значение ', '<B>', x, '</B>' ,' = ', parseInt(x), "<BR>") x="54.45" document.write ('преобразованное в число значение ', '<B>', x, '</B>', ' = ', parseInt(x), "<BR>") x="-7654321" 32
document.write ('преобразованное в число значение ', '<B>', x, '</B>', ' = ', parseInt(x), "<BR>") x="0x23" document.write ('преобразованное в число значение ', '<B>', x, '</B>', ' = ', parseInt (x,16), "<BR>") x="015" document.write('преобразованное в число значение ', '<B>', x, '</B>', ' = ', parseInt(x,8), "<BR>") x parseInt(x) 3.14 "строка" "123строка" "строка123" "54.45" "-7654321" "0x23" "015" 3 NaN 123 NaN 54 -7654321 35 13 Функция parseFloat возвращает число с плавающей точкой из преобразованной строки. parseFloat (), где  — строка или элемент, возвращающий строку. x="54.45" document.write ('преобразованное в число с плавающей точкой строковое значение ', '<B>', x, '</B>', ' = ', parseFloat (x), "<BR>") x x="54.45" parseFloat (x) 54.45 Метод toString преобразовывает объект  в строку. .toString ([]), где  — основание для представления числовых значений. 33
543.toString() // “543” let x = 1234567; document.write (x.toString().length) // 7 x = 1234567; document.write (x.toString()) // “1234567” x = 119; alert(x.toString(16)) // “77” 10.toString(16)) // “a” Функция eval преобразует строку в исполняемый код JavaScript. eval () eval (“alert ('Hello')”) document.write (eval (‘Number.MAX_VALUE’)) // 1.7976931348623157e+308 let x=5 let str8 = "12*x-3+45" console.log (eval(str8)) // 102 Метод toFixed возвращает округленное до  знаков число  в формате строки. .toFixed () let r = 15.324562362627 r.toFixed(2) // “15.32” let z = 15.3 z.toFixed(2) // “15.30” где ,  — число или элемент, возвращающий число. Функция toExponential возвращает преобразованное в экспоненциальную форму число  c  знаками после запятой. .toExponential (), где ,  — число или элемент, возвращающий число. 34
Функция toPrecision возвращает преобразованное в экспоненциальную форму число  с фиксированной точкой (запятой) и с  значащими цифрами. .toPrecision (), где ,  — число или элемент, возвращающий число. Разработчики языка JS заложили много различных функций в его словарь. Однако их все равно не хватает для решения различных жизненных задач. Но существует возможность разработчикам скриптов с помощью специального механизма добавлять свои функции в проекты. Общий формат описания функции function  ([,, ...]) {  }, где  — имя функции, которое должно состоять только из одного слова, не совпадающего с ключевым словом JS; ,... — необязательные входные аргументы (параметры) функции;  — тело функции, состоящее из последовательности операторов JavaScript, включающей оператор return. Вызвать функцию на выполнение можно написанием ее имени вместе с круглыми скобками. Если есть параметры, то при вызыве функции им нужно дать значения. Оператор return присваивает имени функции значение , где  — значение, выражение или функция. Пример Описание функции function pillars (num_pill, dist, width) { return num_pill * width - dist } Вызов функции pillars (10, 100, 32) // 220 pillars (20, 50, 16) // 270 35
Практическая работа на переменные и значения Задание 1. 8 Напишите функцию, которая может преобразовать число в строку. function numToStr(num) { } numToStr(123) // "123" numToStr(999) // "999" Задание 2. 8 Напишите функцию, которая преобразовывает логическое значение в строку. function booleanToString(b) { } booleanToString(true) // "true" booleanToString(false) // "false" Задание 3. 8 Напишите функцию, которая преобразовывает строку в числовое значение. stringToNumber = function(str) { } stringToNumber("1234") // 1234 36
stringToNumber("605") // 605 stringToNumber("-7") // -7 Задание 4. 8 Напишите функцию, которая всегда возвращает 5. Звучит просто. Но имейте в виду, что вы не можете использовать ни один из следующих символов: 0123456789*+-/ function unusualFive() { } unusualFive() // 5 Задание 5. 8 Компания, в которой вы работаете, только что получила контракт на создание платежного шлюза. Чтобы помочь сдвинуть дело с мертвой точки, вы вызвались создать функцию, которая будет принимать значение с плавающей точкой и возвращать сумму, форматированную в долларах и центах. Необходимо организовать добавление конечных нулей, если они отсутствуют. function formatMoney(amount) { } formatMoney(39.99) // '$39.99' formatMoney(3.1) // '$3.10' formatMoney(3) // '$3.00' Задание 6. 8 37
Создайте функцию, которая принимает 2 целых числа в виде строки в качестве входных данных и выводит сумму (также в виде строки) function sumStr(a,b) { } sumStr("4","5") // "9" sumStr("34","5") // "39" Задание 7. 8 Напишите функцию, которая принимает аргумент и возвращает его квадрат. function square (x) { } square(3) // 9 Задание 8. 8 Звездолет «Энтерпрайз» столкнулся с некоторой проблемой при создании программы для приветствия всех, кто поднимается на борт. Наша задача — исправить код скрипта и заставить программу снова работать! function sayHello(name) { return 'Hello' } sayHello('Mr. Spock') // 'Hello, Mr. Spock' sayHello('Captain Kirk') // 'Hello, Captain Kirk' sayHello('Liutenant Uhura') // 'Hello, Liutenant Uhura' 38
Задание 9. 8 Создайте функцию, которая конвертирует доллары США (USD) в китайские юани (CNY). Вводом является сумма в долларах США в виде целого числа, а выводом должна быть строка, указывающая сумму в юанях, за которой следуют текст "Chinese Yuan". Курс конвертации составляет 6,75 юаней за каждый доллар США. Все числа должны быть представлены в виде строки с 2 знаками после запятой (например, "21.00", а не "21.0" или "21") function usdcny(usd) { } usdcny(15) // '101.25 Chinese Yuan' usdcny(465) // '3138.75 Chinese Yuan' Задание 10. 8 Напишите функцию, которая будет принимать два параметра: переменную и тип, и проверьте, соответствует ли тип переменной заданному типу. Функция будет возвращать true, если типы совпадают, или false в противном случае. function typeValidation(variable, type) { } typeValidation(42, "number") // true typeValidation("42", "number") // false 39
Задание 11. 8 Месси — футболист, забивший голы в трех лигах: • • • ЛаЛига Кубок Испании Чемпионы Напишите функцию, которая будет возвращать общее количество голов Месси во всех трех лигах. function goals (laLigaGoals, copaDelReyGoals, championsLeagueGoals) { } goals(0,0,0) // 0 goals(43, 10, 5) // 58 Задание 12. 8 Вы в походе со своими друзьями далеко от дома, но когда приходит время возвращаться, вы понимаете, что ваше топливо на исходе, а ближайшая заправка находится в 50 милях. Вы знаете, что в среднем ваш автомобиль пробегает около 25 миль на галлон. Осталось 2 галлона. Учитывая эти факторы, напишите функцию, которая сообщает вам, возможно ли добраться до заправки или нет. Функция должна возвращать true, если это возможно, и false если нет. Входные значения всегда положительны. const zeroFuel = (distanceToPump, mpg, fuelLeft) => { } Например, zeroFuel(50, 25, 2) // true zeroFuel(100, 50, 1) // false 40
Задание 13. 8 Животные устраивают пир! Каждое животное приносит одно блюдо. Но только существует одно правило: блюдо должно начинаться и заканчиваться теми же буквами, что и название животного. Например, great blue heron приносит garlic naan, а chickadee – chocolate cake. Напишите функцию feast, которая принимает имя животного и блюдо в качестве аргументов и возвращает true или false, чтобы показать, разрешено ли животному приносить блюдо на праздник или нет. function feast(beast, dish) { } feast("great blue heron", "garlic naan") // true feast("chickadee", "chocolate cake") // true feast("brown bear", "bear claw") // false Задание 14. 8 Хорошо известный факт: все, чего хочет Чак Норрис, он получает. В результате Чаку очень редко приходится употреблять слово «ложь». Менее известен факт, что если что-то является правдой, а Чак не хочет, чтобы это было правдой, Чак может напугать правду своими массивными бицепсами, и она автоматически становится ложью. Задача — быть больше похожим на Чака. Функция должна возвращать значение false, никогда не используя слово false... function ifChuckSaysSo() { } ifChuckSaysSo() // false 41
Задание 15. 8 Напишите функцию, которая преобразует шестнадцатеричное число (заданное в виде строки) в десятичное число. function hexToDec(hexString) { } hexToDec("1") // 1 hexToDec("a") // 10 hexToDec("10") // 16 Задание 16. Напишите функцию, которая проверяет, является ли заданное число целым. function isinteger (x) { } isinteger (1) // true isinteger (5.7) // false Задание 17. 8 Вы спрашиваете маленькую девочку: «Сколько тебе лет?» Она всегда отвечает: «x лет», где x — случайное число от 0 до 9. Напишите функцию, которая возвращает возраст девочки (0–9) в виде целого числа. Входная строка всегда является допустимой. Например, тестовым входным значением может быть «1 год» или «5 лет». Первый символ в строке всегда является числом. function getAge(inputString) { } getAge("4 years old") // 4 42
getAge("9 years old") // 9 getAge("1 year old") // 1 Задание 18. 8 Иногда мне нужно быстро перевести мили в имперские галлоны (mpg) в километры на литр (kpl). Создайте приложение, которое будет отображать количество километров на литр (выходные данные) на основе количества миль на имперский галлон (входные данные). Ваш ответ должен быть точным в пределах 0,01 kpl. • • 1 имперский галлон = 4,54609188 литра 1 миля = 1,609344 километра function converter (mpg) { } converter(10) // 3.54 converter(20) // 7.08 converter(30) // 10.62 43
КОНСТАНТЫ Объявление const делает из переменной величины константу, то есть переменную, значение которой нельзя изменить. Объявление константы должно всегда происходить вместе с заданием ей значения. Константа это неизменяемая переменная. const NAME = ”Василий” const V = 150 Обычно имена констант пишут прописными буквами, если они используется в пределах всего html-документа, в остальных случаях имена содержат только строчные символы. Задание 1. 7 Создайте функцию, которая будет принимать любую сумму денег и разбивать ее на как можно меньшее количество купюр. Функция должна возвращать массив, где каждый элемент в массиве представляет количество купюр определенного типа в следующем порядке: [банкноты по 1 доллару, банкноты по 5 долларов, банкноты по 10 долларов, банкноты по 20 долларов, банкноты по 50 долларов, банкноты по 100 долларов]. Например, можно разделить 365 долларов на 1 купюру по 5 долларов, 1 купюру по 10 долларов, 1 купюру по 50 долларов и 3 купюры по 100 долларов. function giveChange(amount) { } giveChange(365) // [0,1,1,0,1,3] giveChange(217) // [2,1,1,0,0,2] giveChange(8) // [3,1,0,0,0,0] 44
ШАБЛОННЫЕ СТРОКИ Шаблонными литералами называются строки, допускающие использование выражений внутри. С ними можно использовать многострочные литералы и строковую интерполяцию. В спецификациях до ES2015 они назывались «шаблонными строками». Шаблонные литералы заключаются в обратные кавычки ` ` вместо двойных или одинарных. Они могут содержать подстановки, обозначаемые знаком доллара и фигурными скобками. ${выражение} Шаблонные литералы с подстановками удобно использовать в операторах вывода информации. Например, let a=3; let b=7; console.log (`Сумма ${a} + ${b} равна ${a+b}`) // Сумма 3 + 7 равна 10 Расширенной формой шаблонных литералов являются теговые шаблоны. Они позволяют разбирать шаблонные литералы с помощью функции. Первый аргумент такой функции содержит массив строковых значений, а остальные содержат выражения из подстановок. В итоге, функция должна вернуть собранную строку. var человек = 'Степан' var возраст = 2 function пример (строка, человекП, возрастП) { var str0 = строка[0] // "Этот" var str1 = строка[1] // "является" if (возрастП > 60){ возрастП = 'пожилым' } else { возрастП = 'молодым' } return `${str0}${человекП}${str1}${возрастП}` 45
} var output = пример `Этот ${человек} является ${возраст}` alert (output); // Этот Степан является молодым Cуществует метод String.raw(), возвращающий такую же исходную строку, какую вернула бы функция шаблона по умолчанию и строковая конкатенация вместе. var str = String.raw`Сумма 2 + 3 \n${2+3}`; // "Сумма 2 + 3 \n5" Практическая работа на шаблонный литерал Задание 1. 8 Создайте функцию, которая будет возвращать приветствие, используя входные данные. Она должна возвращать: «Привет, <имя> как у вас дела сегодня?». function greet(name) { } greet("Ryan") // "Hello, Ryan how are you doing today?" greet("Shingles") // "Hello, Shingles how are you doing today?" Задание 2. 6 Вы, вероятно, знаете систему лайков из Facebook и других сервисов. Люди могут «лайкать» записи в блоге, фотографии или другие элементы. Мы хотим создать текст, который должен отображаться рядом с таким элементом. Создайте функцию, которая принимает массив, содержащий имена людей, которым нравится элемент. Она должна возвращать отображаемый текст, как показано в примерах: 46
[ ] // "no one likes this" ["Peter"] // "Peter likes this" ["Jacob", "Alex"] // "Jacob and Alex like this" ["Max", "John", "Mark"] // "Max, John and Mark like this" ["Alex", "Jacob", "Mark", "Max"] // "Alex, Jacob and 2 others like this" function likes(names) { } likes([]) // 'no one likes this' likes(['Peter']) // 'Peter likes this' likes(['Jacob', 'Alex']) // 'Jacob and Alex like this' likes(['Max', 'John', 'Mark']) // 'Max, John and Mark like this' likes(['Alex', 'Jacob', 'Mark', 'Max']) // 'Alex, Jacob and 2 others like this' Задание 3. 8 Две строки легко соединить вместе с помощью оператора сложения, например, “строка1” + “строка2”. Другой способ получить желаемый результат – использовать метод concat: string1.concat(string2). Стандарт ES6 предоставил еще один способ соединения строк. Ваша задача — выяснить, что это такое, и написать функцию, которая будет складывать две строки вместе, между двумя строками должен быть пробел. + , .concat() и .join() не разрешены в этом упражнении. Если один из аргументов является числом, код функции должен преобразовать его в строку. function joinStrings(string1, string2) { } joinStrings('string1', 'string2') // 'string1 string2' joinStrings('testing', 'testing') // 'testing testing' joinStrings(134, 234) // '134 234' 47
Задание 4. 8 Создайте функцию sayHello, которая принимает в качестве входных данных имя, город и штат, чтобы поприветствовать человека. Имя представляет собой массив, состоящий из одного или нескольких строковых элементов, которые должны быть объединены вместе с одним пробелом между каждым словом. function sayHello (name, city, state) { } sayHello(['John', 'Smith'], 'Phoenix', 'Arizona') // 'Hello, John Smith! Welcome to Phoenix, Arizona!' sayHello(['Franklin','Delano','Roosevelt'], 'Chicago', 'Illinois') // 'Hello, Franklin Delano Roosevelt! Welcome to Chicago, Illinois!' sayHello(['Wallace','Russel','Osbourne'],'Albany','New York') // 'Hello, Wallace Russel Osbourne! Welcome to Albany, New York!' Задание 5. 8 У вас превосходный сад, и каждый день растениям требуется ровно 40 мм воды. Вы создали отличный фрагмент кода JavaScript для расчета количества воды, которое потребуется растениям, приняв во внимание количество дождевой воды, прогнозируемое на день. Ваш ревнивый сосед взломал ваш компьютер и наполнил ваш код ошибками. Задача – отладить код до того, как растения погибнут! function rainAmount(mm) { if (rainAmount = 40) { return "You need to give your plant " + {rainAmount - 40} + " mm of water" }; if else { 48
return "Your plant has had more than enough water for today!" }; } Задание 6. 8 Филиппу только что исполнилось четыре года, и он хочет знать, сколько ему будет лет в разные годы в будущем, например, в 2090 или 3044 году. Никто не может ответить на бесконечные вопросы Филиппа. Ваша задача — написать функцию, которая принимает два параметра: год рождения и год, по отношению к которому считается количество лет. Поскольку Филипп с каждым днем становится все более любопытным, он может вскоре захотеть узнать, сколько лет прошло до его рождения, поэтому функция должна работать как с датами в будущем, так и с прошлыми датами. Вывод осуществляется в следующем формате: Для дат в будущем: “You are ... year(s) old.". Для дат в прошлом: "You will be born in ... year(s).". Если год рождения равен запрашиваемому году: "You were born this very year!" Троеточия "..." должны быть заменены числом, за которым следует один пробел. Следует учитывать написание year или years, в зависимости от результата. function calculateAge() { } calculateAge(2012, 2016) // "You are 4 years old." calculateAge(1989, 2016) // "You are 27 years old." calculateAge(2000, 2090) // "You are 90 years old." calculateAge(2011, 2012) // "You are 1 year old." calculateAge(2000, 1999) // "You will be born in 1 year." 49
ОБЛАСТЬ ВИДИМОСТИ ПЕРЕМЕННОЙ Оператор var применяется для задания переменной с глобальной областью видимости в пределах всего html-документа, либо внутри функции (если переменная объявлена в теле функции). Оператор let применяется для задания переменной с блочной областью видимости, если объявление содержится внутри блока. Блок ограничивается фигурными скобками. { let a = 2 console.log(a) // 2 a=4 console.log(a) // 4 } console.log(a) // undefined За пределами блока локальная переменная будет иметь неопределенное значение undefined. { var a = 2 console.log(a) // 2 a=4 console.log(a) // 4 } console.log(a) // 4 За пределами блока переменная a будет иметь значение 4. let a = 10 { let a = 2 console.log(a) // 2 a=4 console.log(a) // 4 } 50
console.log(a) // 10 За пределами блока переменная a будет иметь значение 10. let a = 10 { console.log(a) // 10 a=4 console.log(a) // 4 } console.log(a) // 4 В этом примере переменная a является глобальной, так как объявлена за пределами блока. 51
ЛИНЕЙНЫЕ АЛГОРИТМЫ Линейные алгоритмы описывают последовательность пошаговых действий исполнителя. Блок-схема линейного алгоритма Примером линейного алгоритма может служить последовательность действий по вычислению площади треугольника по введенным исходным данным. Формула площади треугольника, как известно из математики, S= 1 ah, 2 где a — основание треугольника, h — высота. Исходными данными в этой задаче являются значения основания и высоты треугольника, чтобы можно было вычислить его площадь. Результат для вывода — это полученная площадь треугольника. Обработка данных в нашей задаче — это вычисление по формуле. 52
// исходные данные let a = 45 let h = 10 // обработка данных let S = 1/2*a*h // вывод результатов document.write ("Площадь треугольника = " + S) Реализованный скриптом алгоритм будет работать для любых исходных данных. В дальнейшем будет рассказано как запрашивать исходные данные у пользователя через диалоговое окно или поля формы. Еще одним важным способом оформления решения является функция. Одно из простых определений функции — это поименнованная последовательность операторов. Операторы заключаются в фигурные скобки. Имя функции дополняется входными переменными, заключенными в круглые скобки. function  ([,, ...]) {  }, где  — имя функции, которое должно состоять только из одного слова, не совпадающего с ключевым словом JS; ,... — необязательные входные аргументы (параметры) функции;  — тело функции, состоящее из последовательности операторов (команд) JavaScript. Вызвать функцию на выполнение можно написанием ее имени вместе с круглыми скобками. Если в теле функции есть оператор return , то функция возвращает значение , где  – значение, выражение или функция. function triangle_square(a, h) { // return "Площадь треугольника = " + 1 / 2 * a * h return `Площадь треугольника = ${1 / 2 * a * h}` } console.log(triangle_square(10, 20)) // 100 53
Практическая работа на линейные алгоритмы Задание 1. Составьте скрипт, который находит частное и произведение максимального и минимального числа Javascript. Задание 2. Выведите скриптом в диалоговое окно четверостишье на 4 строчках. Задание 3. Реализуйте в скрипте линейный алгоритм нахождения площади прямоугольника. Задание 4. Используя диалоговое окно ввода данных (prompt), запросите у пользователя дробное число. Составьте скрипт, который увеличит введенное число в 3 раза. Задание 5. Составьте линейный алгоритм вычисления длины окружности. Ввод исходных данных организуйте через локальные переменные скрипта. вывод результата осуществите через диалоговое окно с шаблонным литералом, комбинируя текст и значения переменных «Длина окружности с радиусом R равна S». Задание 6. 8 Рядом с дорогой стоят столбы. Расстояние между столбами одинаковое и ширина столбов одинаковая. Функция принимает три аргумента: • количество столбов (≥ 2); • расстояние между столбами (10–30 метров); • ширина столба (10–50 сантиметров). Напишите функцию, возвращающую расстояние между первым и последним столбом в сантиметрах (без учета ширины первого и последнего столбов). 54
function pillars(num_pill, dist, width) { } pillars(2, 20, 25) // 2000 pillars(11, 15, 30) // 15270 Задание 7. 8 Бобу нужен быстрый способ вычисления объема параллелипипеда с тремя значениями: длина, ширина и высота параллелипипеда. Напишите функцию, которая поможет Бобу с этим вычислением. class Kata { static getVolumeOfCuboid(length, width, height) { } } Kata.getVolumeOfCuboid(1,2,2) // 4 Kata.getVolumeOfCuboid(6.3,2,5) // 63 Задание 8. 8 Часы показывают h часов, m минут и s секунд после полуночи. Задача состоит в том, чтобы написать функцию, которая возвращает время с полуночи в миллисекундах. function past(h, m, s) { } past(0,1,1) // 61000 past(1,1,1) // 3661000 past(0,0,0) // 0 55
ЦИКЛИЧЕСКИЕ АЛГОРИТМЫ Циклические алгоритмы организуют повторяемость однотипных действий исполнителя. Различают несколько видов циклов. Самыми распространенными являются цикл с параметром, цикл пока (с предусловием) и цикл до (с постусловием). цикл пока цикл до Цикл пока (с предусловием) выполняет операторы javascript до тех пор, пока условие цикла не примет значение «ложь». Другими словами, цикл работает до тех пор, пока условие цикла принимает значение истина. Так же работает и цикл до (с постусловием). Разница между ними в том, что блок операторов в первом случае находится после условия, во втором случае до условия. И, соответственно, цикл до выполнит блок операторов первый раз еще до проверки условия. Цикл с параметром выполняет тело цикла столько раз, сколько раз параметр поменяет свое значение. Параметр — это переменная величина. Ему присваивается начальное значение и указывается конечное, а также приращение при каждом изменении. При каждом выполнении тела цикла сначала сравнивается значение параметра с конечным значением и если оно меньше или равно, то выполняется тело. В противном случает происходит выход из цикла. 56
Цикл с параметром Операторы цикла JavaScript поддерживает все основные виды циклов: цикл пока (while), цикл до (do-while), цикл с параметром (for). Цикл пока (while) выполняет операторы, находящиеся в теле до тех пор, пока условие цикла сохраняет значение истина (true). while () {  }, где  — условие, являющееся логическим выражением; пока его значение истинно, цикл выполняется;  — тело цикла, включающее в себя последовательность операторов JavaScript. Пример var s = 0 while (s < 100) { document.write (s + "<br>") s += 10 } // 0 10 20 30 40 50 60 70 80 90 console.log (s) // 100 57
Цикл do–while очень похож на цикл while. Единственное отличие состоит в том, что в цикле do–while блок кода (тело цикла) выполняется до проверки условия. Поэтому даже если условие становится неверным (false), но тело цикла все равно будет выполнено один раз до этой проверки. Можно смело утверждать, что в данном цикле блок кода будет выполняться всегда как минимум один раз. do {  } while () Пример var i = 0 do { document.write (i + "<br>") i=i+2 } while (i < 20) // 0 2 4 6 8 10 12 14 16 18 console.log (i) // 20 Пример Вывод в консоль случайных чисел в диапазоне от 1 до 10. Если выпадает число 0, то цикл заканчивает свою работу. do { x=Math.round(Math.random()*10) console.log(x) } while (x!=0) Цикл с параметром выполняется до тех пор, пока условие имеет значение истина (true). Параметр цикла имеет приращение, поэтому при каждом проходе цикла значение параметра меняется. Таким образом, цикл for удобен при использовании в блоке кода параметра, например, когда необходимо проанализировать каждый символ строки или каждый элемент массива, или когда нужно накопить сумму или произведение. Параметр может выступать в качестве номера символа строки или номера элемента массива, или очередного слагаемого или множителя. for (; ; ) {  }, где  — начальное значение параметра цикла (если параметров несколько, то они разделяются запятой); 58
 — условие (может включать параметры цикла); пока его значение истинно, цикл выполняется;  — приращение параметра (если параметров несколько, то они и приращения разделяются запятой);  — тело цикла, содержащее команды JavaScript, разделенные символом ";" Любой из параметров может быть пустым. Если тело цикла содержит только одну команду, то фигурные скобки можно опустить. Пример for (let i = 0; i <= 7; i = i + 1) document.write ("<H3>" + i + "</H3>") // 0 1 2 3 4 5 6 7 console.log(i) // undefined for (let i = 1, let j = 10; i < j; i++, j--) document.write ("<p>", i, j "</p>") // 1 10 // 2 9 // 3 8 // 4 7 // 5 6 for (let i = 1, j = 10; i < j; ) { document.write (i) i++ j-} // 1 2 3 4 5 Метод write объекта document выводит на веб-страницу информацию, указанную в качестве аргумента в круглых скобках. Для форматированного вывода можно использовать теги HTML. Существует вариант цикла for для перебора всех свойств объекта JavaScript. for (var  in ) {  }, где  — имя переменной; 59
 — имя объекта JavaScript;  — тело цикла, содержащее команды JavaScript, разделенные символом ";" Пример for (var свойство in location) document.write ("<B>" + свойство + ": </B>" + eval ("location."+ свойство) + "<BR>") Оператор break позволяет досрочно прекратить выполнение цикла. Это бывает необходимо, например, при выполнении некоторого условия, когда дальнейшая проверка условия становится бесполезной или даже вредной. Вопросы и упражнения 1. 2. 3. 4. 5. 6. Почему в параметрах цикла, как правило, меняется значение условия в процессе выполнения цикла? Может ли цикл выполняться бесконечно? Придумайте цикл, который будет выполняться 5 раз. За счет чего условие выполнения цикла меняет свое значение с true на false? Придумайте такое условие для оператора цикла while, чтобы он выполнялся 4 раза. Сколько раз выполнится цикл let i=-100 while (i>=0) { i++ console.log(i) } // 0 let z=2*3 while (z>0) { console.log(z) z-} //6 let i=-10 while (i<0) { console.log(i) i++ } // 10 let n=10 let m=0 while (n>m) { console.log(m) m++ } //10 60 let x=true while (x) { console.log(x) x=false } // 1
7. 8. Придумайте цикл, который выведет в консоль следующий рисунок * ** *** **** ***** Придумайте цикл, который выведет в консоль следующий рисунок ** **** ****** ******** ********** 9. Придумайте цикл, который выведет в консоль 5 раз слово «Привет» Привет Привет Привет Привет Привет 10. Придумайте цикл, который выведет в консоль 5 раз слово «Привет» с номером привета Привет 1 Привет 2 Привет 3 Привет 4 Привет 5 11. Придумайте цикл, который выведет в консоль все четные числа a. от 2 до 20 b. от 30 до 10 c. от 10 до 20 и от 30 до 40 61
Метки, break, continue Оператор break прекращает выполнение текущего цикла или условного оператора. Чаще всего он используется в операторе switch для завершения case, но его также можно использовать для досрочного завершения оператора if или цикла. break const x = Math.round(Math.random()*5); switch(x) { case 1: console.log('Выпало число 1'); break; case 2: console.log('Выпало число 2'); break; case 3: console.log('Выпало число 3'); break; default: console.log ('Выпало число больше 3 или меньше 1') } Дан массив целых чисел. Определите, есть ли в массиве хотя бы одно четное число. const arr = [11, 3, 5, 7, 2, 4, 9, 13] { rezult = "no" for (let el of arr) { if (el % 2 == 0) { rezult = "yes" break } } console.log (rezult) // yes } 62
Оператор continue может использоваться только с циклами, чтобы досрочно завершить текущую итерацию и начать следующую. continue let str = '' for (let i = 0; i < 5; i++) { if (i == 1) continue str = str + i } console.log(str) //0234 console.clear() for (let i = 0; i < 3; i++) { for (let j=0; j < 4; j++) { if (i == 1) continue console.log("i= "+i,"j= "+j) } } // 00 01 02 03 // 20 21 22 23 Метки в JavaScript — это названия, которые дает разработчик кода оператору или блоку кода. С меткой можно использовать команды break или continue. Обычно использование меток необходимо, когда используются вложенные операторы любого типа. :  continue , где  — метка,  — оператор или блок кода loop1: for (let i = 0; i < 3; i++) { loop2: for (let j=0; j < 4; j++) { if (j == 1) continue loop1 console.log("i= "+i, "j= "+j) } } 63
// 00 // 10 // 20 02 03 12 13 22 23 console.clear() loop1: for (let i = 0; i < 3; i++) { loop2: for (let j=0; j < 4; j++) { if (j == 1) continue loop1 console.log("i= "+i,"j= "+j) } } // 00 // 10 // 20 break  console.clear() block1: { console.log("привет"); break block1; console.log("эта строка не будет выведена"); } console.log("мир"); // "привет" // "мир" Практическая работа на цикл Задание 1. Составьте скрипт, выводящий в консоль браузера все числа от 10 до N с шагом 10. Это числа 10, 20, 30 и т. д. Рекомендации. Ввод числа N можно организовать с помощью метода prompt, вывод результата методом log объекта console. Для генерации нужных чисел следует объявить переменную X с начальным значением 64
0. В теле цикла ей следует присваивать значение параметра цикла, который должен меняться от 10 до N с шагом 10. Задание 2. 8 Напишите функцию, которая для заданного числа возвращает таблицу умножения на него. Например, таблица умножения для числа 5 выглядит следующим образом: 1*5=5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25 6 * 5 = 30 7 * 5 = 35 8 * 5 = 40 9 * 5 = 45 10 * 5 = 50 Для перехода на новую строку в таблице можно использовать спецсимвол \n. Переход на новую строку следует добавлять между строками, но в конце его не должно быть. function multiTable(number) { } multiTable(5) // '1 * 5 = 5\n2 * 5 = 10\n3 * 5 = 15\n4 * 5 = 20\n5 * 5 = 25\n6 * 5 = 30\n7 * 5 = 35\n8 * 5 = 40\n9 * 5 = 45\n10 * 5 = 50' multiTable(1) // '1 * 1 = 1\n2 * 1 = 2\n3 * 1 = 3\n4 * 1 = 4\n5 * 1 = 5\n6 * 1 = 6\n7 * 1 = 7\n8 * 1 = 8\n9 * 1 = 9\n10 * 1 = 10' 65
Задание 3. 8 Напишите функцию, которая находит сумму всех чисел от 1 до num. Число num всегда будет целым положительным числом, большим 0. var summation = function (num) { } summation(1) // 1 summation(8) // 36 Задание 4. Составьте скрипт, находящий сумму первых N натуральных чисел. Рекомендации. Ввод числа N можно организовать с помощью метода prompt, вывод результата методом write объекта document. Для накопления суммы нужно объявить переменную Сумма с начальным значением 0. В теле цикла ее следует увеличивать на параметр цикла, который должен меняться от 1 до N с шагом 1. Задание 5. 7 Создайте функцию, которая возвращает сумму последовательности целых чисел. Последовательность определяется 3 неотрицательными значениями: начало, конец, шаг (включительно). Если начальное значение больше конечного, функция должна возвращать 0. const sequenceSum = (begin, end, step) => { } sequenceSum(2, 6, 2) // 12 sequenceSum(1, 5, 1) // 15 sequenceSum(1, 5, 3) // 5 66
Задание 6. 8 Напишите функцию, которая возвращает заданную строку n раз function repeatStr(n, strval) { } Например, repeatStr(6, "А") // "АААААА" repeatStr(5, "Hello") // "HelloHelloHelloHelloHello" Задание 7. 7 Напишите функцию, которая принимает входные данные 4 и 7. Если введено 4, функция должна возвращать 7. Если введено значение 7, функция должна вернуть значение 4. Все остальное, введенное в качестве входных данных, должно возвращать 0. Есть только одна загвоздка: функция не может включать операторы if, операторы switch или тернарный оператор (или функцию eval из-за того, что вы можете обойти требование if, используя его). function fourSeven(n) { } Задание 8. 8 Напишите функцию, возвращающую заданную строку в которой каждый символ повторяется дважды. function doublechar(str) { } Например, doublechar("String") // "SSttrriinngg" doublechar("Hello World") // "HHeelllloo WWoorrlldd" doublechar("1234!_ ") // "11223344!!__ " 67
Задание 9. 8 Учитывая массив логических значений и логический оператор, верните логический результат, основанный на последовательном применении оператора к значениям в массиве. function logicalCalc(array, op) { } logicalCalc([true, true, true, false], "AND") // false logicalCalc([true, true, true, false], "OR") // true logicalCalc([true, true, true, false], "XOR") // true logicalCalc([true, true, false, false], "AND") // false logicalCalc([true, true, false, false], "OR") // true logicalCalc([true, false, false, false], "XOR") // true Задание 10. 7 У мистера Скруджа есть сумма денег "P", которую он хочет вложить. Прежде чем он это сделает, он хочет знать, сколько лет "Y" эта сумма "P" должна храниться в банке, чтобы она составила желаемую сумму денег "D". Сумма хранится в течение "Y" лет в банке, где проценты "I" выплачиваются ежегодно. После уплаты налогов "T" за год новая сумма реинвестируется. Налогом облагается не инвестированная основная сумма, а только начисленные проценты за год. function calculateYears(principal, interest, tax, desired) { } calculateYears(1000, 0.05, 0.18, 1100) // 3 calculateYears(1000,0.01625,0.18,1200) // 14 calculateYears(1000,0.05,0.18,1000) // 0 68
Задание 11. 7 В вашем классе начались уроки по арифметической прогрессии. Поскольку вы также программист, вы решили написать функцию, которая вернет первые n элементов последовательности с заданной общей разницей d и первым элементом a. Обратите внимание, что разница может быть равна нулю! Результатом функции должна быть строка чисел, разделенных запятой и пробелом. function arithmeticSequenceElements(a, d, n) { } arithmeticSequenceElements(1, 2, 5) // "1, 3, 5, 7, 9" arithmeticSequenceElements(1, 0, 5) // "1, 1, 1, 1, 1" arithmeticSequenceElements(1, -3, 10) // "1, -2, -5, -8, -11, -14, -17, -20, -23, -26" Задание 12. 8 О нет, Тимми создал бесконечный цикл! Помогите Тимми найти и исправить ошибку в его незаконченном цикле for! function createArray(number) { var newArray = []; for(var counter = 1; counter <= number;) { newArray.push(counter); } return newArray; } Задание 13. В небольшом городе население p0 = 1000 в начале года. Население постоянно растет на 2 процента каждый год и еще 50 новых людей каждый год переезжают в город жить. Сколько лет необходимо городу, чтобы его население стало больше или равно p >= 1200 жителей? 69
В конце первого года: 1000 + 1000 * 0.02 + 50 => 1070 жителей. В конце второго года: 1070 + 1070 * 0.02 + 50 => 1141 жителей (** число жителей всегда целое **). В конце третьего года: 1141 + 1141 * 0.02 + 50 => 1213. Итого понадобится 3 года. p0 — население в начале года, целое число больше 0; процент — положительное число или с плавающей запятой; aug — количество жителей, которые покидают или пребывают в город, целое число; p — население, которое требуется достичь, целое число больше 0. Функция nbYear должна возвращать количество лет, которое потребуется для достижения населения больше или равно p. nbYear(1500, 5, 100, 5000) // 15 nbYear(1500000, 2.5, 10000, 2000000) // 10 Задание 14. 8 Напишите функцию generateRange, которая принимает три аргумента (start, stop, step) и возвращает диапазон целых чисел от start до stop включительно с шагом step. function generateRange(min, max, step){ } generate_range(1, 15, 20) // [1] generate_range(1, 7, 2) // [1, 3, 5, 7] enerate_range(1, 10, 1) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] Задание 15. 8 ИИ заразил текст символом!! Этот текст теперь полностью мутировал в этот символ. Начиная с исходного текста и заданного символа, вернуть текст после его мутации таким образом, чтобы все символы ис70
ходного текста были заменены этим символом. Если текст или символ пусты, вернуть пустую строку. Никогда не будет случая, чтобы оба были пустыми, поскольку ничего не происходит!! Примечание: символ представляет собой строку длиной 1 или пустую строку. function contamination(text, char){ } contamination("abc","z") // "zzz" contamination("","z") // "" contamination("abc","") // "" contamination("_3ebzgh4","&") // "&&&&&&&&" 71
ВЕТВЯЩИЕСЯ АЛГОРИТМЫ Ветвящийся алгоритм организует выбор последовательности действий исполнителя в зависимости от значения условия. Если условие при выполнении принимает значение истина, то выполняется один набор команд, если условие принимает значение ложь, то выполняется другой набор команд. Блок-схема ветвящегося алгоритма 72
На схеме показано полное ветвление, когда присутствуют обе ветки алгоритма, выходящие из условия. Существуют неполные ветвления, когда из условия выходит только одна ветвь. Условный оператор if () {  } [ else {}] if (x > 0) { alert (“положительное число”) } else { alert (“отрицательное число”) } где  — условие; если его значение true (истина), то выполняется последовательность команд ; если его значение false (ложь), то выполняется последовательность команд ; блок else может быть опущен. JavaScript поддерживает вариант развилки “else-if” if (1) { 1 } else if (2) { 2 } else { 3 } Для составления условных выражений в словаре JavaScript предусмотрены следующие знаки логических операций и функций 73
== === > < >= <= && || ! равно идентично больше меньше больше или равно меньше или равно и или не Оператор == сравнивает аргументы на равенство, а оператор === сравнивает на идентичность. Оператор === не приводит аргументы к одному типу. var xyz = 0 alert (xyz == false) // true alert (xyz === false) // false П р и м е р 1. Напишем скрипт, который по введенному числу определит, является ли оно положительным var число = prompt ("Введите число") if (число > 0) document.write (`<h1>число ${число} является положительным</h1>`) П р и м е р 2. Напишем скрипт, который по введенному числу определит является ли оно четным или нечетным if (число % 2 == 0) document.write (`число ${число} является четным`) else document.write (`число ${число} является нечетным`) П р и м е р 3. Напишем javascript-код в качестве значения параметрасобытия для кнопки. <INPUT TYPE = "button" VALUE = "Щелкни на мне" ONCLICK = "if (document.form1.tf.value < 1) { alert ('Привет!'); }"> 74
Тернарный оператор ?: Тернарный оператор ? возвращает значение , если условие  верно, и значение  в противном случае. x < 16 ? “несовершеннолетний” : “совершеннолетний” Возможны множественные тернарные операции 1 ? 1 : 2 ? 2 : 2 x < 3 ? “младенец” : x > 2 && x < 16 ? “несовершеннолетний” : “совершеннолетний” Оператор множественного перехода switch () { case 1 : 1 break case 2 : 2 break … default: d } где  — переменная или выражение с переменной любого типа, не только логического как у тернарного или условного оператора 1, 2, … — возможные значения , 1, 2, …, d — команды JavaScript. Оператор switch заменяет несколько операторов if. При каждом предусмотренном значении  будет вызываться на выполение последовательность команд . Оператор default является необязательным. Он срабатывает тогда, когда  принимает непредусмотренное значение. 75
Выражение значение 1 действия 1 значение 2 действия 2 значение 3 действия 3 значение 4 действия 4 все остальные значения действия 5 П р и м е р. Моделирование бросания игральной кости function случайное_число () { var x = Math.random () * 5 + 1 return Math.round (x) } var total1 = 0, total2 = 0, total3 = 0, total4 = 0, total5 = 0, total6 = 0 for (var i = 1; i <= 1000; i++) { switch (случайное_число()) { case 1 : total1++ break case 2 : total2++ break case 3 : total3++ break case 4 : total4++ break 76
case 5 : total5++ break case 6 : total6++ } } document.write("<table>") document.writeln("<tr><th>грань</th><th>число выпадений</th>") document.writeln("<tr><td>1</td><td>" + total1 + "</td>") document.writeln("<tr><td>2</td><td>" + total2 + "</td>") document.writeln("<tr><td>3</td><td>" + total3 + "</td>") document.writeln("<tr><td>4</td><td>" + total4 + "</td>") document.writeln("<tr><td>5</td><td>" + total5 + "</td>") document.writeln("<tr><td>6</td><td>" + total6 + "</td>") document.write("</table>") грань число выпадений 1 100 2 179 3 212 4 204 5 221 6 84 Вопросы и упражнения 1. Составьте скрипт, проверяющий введенное число на кратность 3. Рекомендации. Кратность 3 означает, что число делится на 3 без остатка. 77
2. Усовершенствуйте скрипт первого задания таким образом, чтобы еще осуществлялась проверка введенного числа на отрицательность, то есть является ли введенное число отрицательным и кратным 3 одновременно. 3. Разработайте скрипт, который по введенным значениям переменных a и b определяет, является ли сумма этих двух переменных больше 100 и меньше 500. 4. Разработайте скрипт, который по введенному значению переменной x определит: если число x не равно 0, то вывести значение выражения 1/x. 5. Составьте скрипт, находящий сумму первых N натуральных чисел, кратных 5 и не кратных 3. Рекомендации. Ввод числа N можно организовать с помощью метода prompt, вывод результата методом write объекта document. Для накопления суммы нужно объявить переменную Сумма с начальным значением 0. В теле цикла ее следует увеличивать на параметр цикла, который должен меняться от 1 до N с шагом 1, при соблюдении условия кратности параметра 5 и не кратности 3. 6. Составьте скрипт, находящий сумму положительных нечетных чисел, меньших 50. 7. Разработайте скрипт, который по введенному выражению математической функции (на языке JS), находит ее значения на отрезке от a до b (b > a) с шагом h. Рекомендации. Для вычисления значения введенной функции используйте функцию eval. 8. Даны натуральное число n, действительное число a. Вычислить a. an b. a(a + 1) (a + 2) (a + 3) (a + 4)…(a + n – 1) c. a(a – n)(a – 2n) (a – 3n) (a – 4n)…(a – n2) 9. Построить оси координат и отложить на них N пронумерованных единичных отрезков. 10. Построить N концентрических окружностей с шагом z. 78
Практическая работа на условный оператор Задание 1. 8 Напишите функцию, которая принимает два целых числа и возвращает остаток от деления большего значения на меньшее. Деление на ноль должно вернуть NaN. function remainderOf (n, m) { } remainderOf remainderOf remainderOf remainderOf (17, 5) // 2 (13, 72) // 7 (0, -1) // 0 (0, 1) // NaN Задание 2. 8 Тимми и Сара думают, что они влюблены, но там, где они живут, они узнают об этом только после того, как сорвут по цветку каждый. Если у одного из цветов четное количество лепестков, а у другого нечетное, это означает, что они влюблены. Напишите функцию, которая будет принимать количество лепестков каждого цветка и возвращать true, если они влюблены, и false, если нет. function lovefunc (flower1, flower2) { } lovefunc(1,4) // true lovefunc(2,2) // false lovefunc(0,1) // true 79
Задание 3. 8 Дети пьют пунш. Подростки пьют кока-колу. Молодые люди пьют пиво. Взрослые пьют виски. Создайте функцию, которая получает возраст и возвращает то, что пьют люди в этом возрасте. Правила: Дети до 14 лет drink toddy. Подростки младше 18 лет drink coke. Молодые люди моложе 21 года drink beer. Взрослые старше 21 drink whisky. function peopleWithAgeDrink(old) { } peopleWithAgeDrink(22) // 'drink whisky' Задание 4. 8 Напишите функцию для двух игроков в игру «Камень, ножницы, бумага». Функция должна вернуть, какой игрок выиграл! В случае ничьей — «Draw!». const rps = (p1, p2) => { }; Например, rps('scissors','paper') // Player 1 won! rps('scissors','rock') // Player 2 won! rps('paper','paper') // Draw! 80
Задание 5. 8 Лягушка с широким ртом особенно интересуется пищевыми привычками других существ. Она просто не может перестать спрашивать встречных существ, что они любят есть. Но однажды она встречает аллигатора, который просто обожает есть лягушек с широким ртом! Когда она встречает аллигатора, у нее рот становится крошечным. Задача – написать функцию mouth_size, которая принимает один аргумент animal – животное, с которым столкнулась лягушка. Если это аллигатор (без учета регистра), функция возвращает small, в противном случае wide. function mouthSize(animal) { } mouthSize("toucan") // "wide" mouthSize("ant bear") // "wide" mouthSize("alligator") // "small" Задание 6. 8 Напишите функцию, возвращающую сумму всех кратных n, меньших m, где n и m являются натуральными числами. function sumMul (n, m) { } Например, sumMul(2, 9) // 2 + 4 + sumMul(3, 13) // 3 + 6 + sumMul(4, 123) // 4 + 8 + 12 + ... = 1860 sumMul(4, -7) // "INVALID" 81 6 9 + + 8 12 = = 20 30
Задание 7. 8 Создайте функцию, которая отвечает на вопрос «Вы играете на банджо?». Если ваше имя начинается с буквы "R" или строчной буквы "r", вы играете на банджо! Функция принимает имя в качестве единственного аргумента и возвращает одну из следующих строк: name + " играет на банджо" name + " не играет на банджо" function areYouPlayingBanjo(name) { } areYouPlayingBanjo("Adam") // "Adam does not play banjo" areYouPlayingBanjo("Paul") // "Paul does not play banjo" areYouPlayingBanjo("Ringo") // "Ringo plays banjo" areYouPlayingBanjo("bravo") // "bravo does not play banjo" areYouPlayingBanjo("rolf") // "rolf plays banjo" Задание 8. 8 Создайте функцию, которая выдает персонализированное приветствие в зависимости от значений параметров. Функция принимает два параметра: name (имя) и owner (имя владельца). Если имя владельца owner совпадает со значением параметра name, то возвращается приветствие 'Hello boss', в противном случае 'Hello guest'. function greet (name, owner) { } greet('Daniel', 'Daniel') // 'Hello boss' greet('Greg', 'Daniel') // 'Hello guest' 82
Задание 9. 8 Боб работает водителем автобуса. Тем не менее, он стал чрезвычайно популярен среди жителей города. Ему иногда приходится сталкиваться с проблемой нехватки места в автобусе! Он хочет, чтобы вы написали простую программу, сообщающую ему, сможет ли он разместить всех пассажиров. Нужно написать функцию, которая принимает три параметра: cap — это количество человек, которое может вместить автобус, не считая водителя. on — количество людей в автобусе, не считая водителя. wait — это количество людей, ожидающих посадки в автобус. Если места в автобусе достаточно, функция должна вернуть 0, а если нет, вернуть количество пассажиров, которых он не может взять. function enough(cap, on, wait) { } enough(10, 5, 5) // 0 enough(100, 60, 50) // 10 enough(20, 5, 5) // 0 Задание 10. 8 Напишите функцию, которая будет проверять, совпадают ли два заданных символа по регистру. Если какой-либо из символов не является буквой, вернется значение –1. Если оба символа имеют одинаковый регистр, вернется 1. Если оба символа являются буквами, но не имеют одинакового регистра, вернется 0. function sameCase(a, b) { } sameCase ('C', 'B') // 1 83
sameCase ('b', 'a') // 1 sameCase ('A', 's') // 0 sameCase ('c', 'B') // 0 sameCase ('\t', 'Z') // -1 sameCase ('H', ':') // -1 Задание 11. 8 Всем известно классическое правило знакомств «половина вашего возраста плюс семь» , которому следуют многие (включая меня). Это «рекомендуемый» возрастной диапазон для свиданий. Дано целое число (1 <= n <= 100), представляющее возраст человека, вернуть минимальный и максимальный возрастной диапазон. Это уравнение не работает, если возраст <= 14, поэтому, если возраст <= 14, используйте уравнение min = age - 0.10 * age max = age + 0.10 * age Вам следует уменьшить все свои ответы, чтобы они были целыми числами, а не числами с плавающей точкой (которые не отражают возраст). Верните свой ответ в форме "[min]-[max]" function datingRange(age) { } datingRange(17) // "15-20" datingRange(40) // "27-66" datingRange(15) // "14-16" datingRange(35) // "24-56" datingRange(10) // "9-11" 84
Практическая работа на оператор switch-case Задание 1. 8 BMI — величина, позволяющая оценить степень соответствия массы человека и его роста, и тем самым косвенно судить о том, является ли масса недостаточной, нормальной или избыточной. Формула BMI = weight / height2. Напишите функцию, возвращающую BMI в словесной форме по данным веса и роста: если bmi <= 18.5, то "Underweight" если bmi <= 25.0, то "Normal" если bmi <= 30.0, то "Overweight" если bmi > 30, то "Obese" function bmi(weight, height) { } bmi(80, 1.80) // "Normal" Задание 2. 8 Кто помнит свое время на школьном дворе, когда девочки брали цветок и отрывали его лепестки, произнося каждую из следующих фраз каждый раз, когда отрывался лепесток: • • • • • • I love you a little a lot passionately madly not at all 85
Когда был сорван последний лепесток, раздались крики восторга, мечты, нахлынувшие мысли и эмоции. Создайте функцию, которая должна определить, какую фразу девушки сказали бы для цветка с заданным количеством лепестков, где nb_petals > 0. function howMuchILoveYou(nbPetals) { } howMuchILoveYou(7) // "I love you" howMuchILoveYou(3) // "a lot" howMuchILoveYou(6) // "not at all" Задание 3. 8 BOPE — это отряд специального назначения полиции, который обычно проводит операции в фавелах Рио-де-Жанейро. Напишите функцию, которая определяет количество магазинов , которые каждый солдат должен иметь в своей сумке. На входе функция получает вид оружия и количество улиц, которые офицер должен пересечь. На каждой улице офицер стреляет 3 раза. Количество пуль в магазине для разных видов оружия: • • • • PT92 – 17 пуль M4A1 - 30 пуль M16A2 - 30 пуль PSG1 - 5 пуль function magNumber(info) { } magNumber (["PT92", 6]) // 2 (6 улиц по 3 пули в каждой) magNumber (["M4A1", 8]) // 1 magNumber (["PSG1", 31]) // 19 Для округления результатов используйте метод Math.ceil 86
Задание 4. 8 Вы получаете любую карту в качестве аргумента. Задача – вернуть масть этой карты в словестном виде (в нижнем регистре). deck = ['2♣','3♣','4♣','5♣','6♣','7♣','8♣','9♣','10♣','J♣','Q♣','K♣','A♣', '2♦','3♦','4♦','5♦','6♦','7♦','8♦','9♦','10♦','J♦','Q♦','K♦','A♦', '2♥','3♥','4♥','5♥','6♥','7♥','8♥','9♥','10♥','J♥','Q♥','K♥','A♥', '2♠','3♠','4♠','5♠','6♠','7♠','8♠','9♠','10♠','J♠','Q♠','K♠','A♠'] function defineSuit(card) { } defineSuit('Q ') // 'spades' defineSuit('9 ') // 'diamonds' defineSuit('J ') // 'hearts' defineSuit('3 ') // 'clubs' Для вырезки масти карты из строки используйте метод slice(-1). Задание 5. 8 Напишите функцию, которая вычисляет, сколько нужно дать чаевых, исходя из общей суммы счета и услуги. Необходимо учитывать следующие рейтинги для чаевых: Terrible: 0% Poor: 5% Good: 10% Great: 15% Excellent: 20% Рейтинг не чувствителен к регистру. Если получен непризнанный рейтинг, то функции необходимо вернуть: "Rating not recognised". function calculateTip(amount, rating) { 87
} calculateTip(20, "Excellent") // 4 calculateTip(26.95, "good") // 3 Задание 6. 8 В польском алфавите 32 буквы: 9 гласных и 23 согласных. Задача состоит в том, чтобы заменить буквы диакритическими знаками: ą → a, ć → c, ę → e, ł → l, ń → n, ó → o, ś → s, ź → z, ż→z и распечатайте строку без использования польских букв. function correctPolishLetters (string) { } correctPolishLetters("Jędrzej Błądziński") // "Jedrzej Bladzinski" correctPolishLetters("Lech Wałęsa") // "Lech Walesa" correctPolishLetters("Maria Skłodowska-Curie") // "Maria SklodowskaCurie" Задание 7. 8 Дан месяц как целое число от 1 до 12. Создайте функцию, которая вернет квартал года как целое число, к которому он относится. Например: месяц 2 (февраль) является частью первого квартала; месяц 6 88
(июнь) является частью второго квартала; месяц 11 (ноябрь) является частью четвертого квартала. const quarterOf = (month) => { } quarterOf(3) // 1 quarterOf(8) // 3 quarterOf(11) // 4 Задание 8. 8 Создайте функцию finalGrade, которая вычисляет итоговую оценку студента в зависимости от двух параметров: оценки за экзамен и количества выполненных проектов. Эта функция должна принимать два аргумента: оценка за экзамен (от 0 до 100), количество завершенных проектов (от 0 и выше). Эта функция должна возвращать число — итоговую оценку. Существует четыре типа итоговых оценок: • • • • 100, если оценка за экзамен превышает 90 или если количество выполненных проектов превышает 10; 90, если оценка за экзамен превышает 75 и если количество выполненных проектов составляет минимум 5; 75, если оценка за экзамен превышает 50 и если количество выполненных проектов составляет минимум 2; 0, в других случаях function finalGrade (exam, projects) { } finalGrade(100, 12) // 100 finalGrade(85, 5) // 90 89
Задание 9. 7 Создайте функцию-калькулятор, которая принимает строку с точками и знаком арифметического действия между ними. Точки и арифметический оператор будут разделены пробелом. Функция будет возвращать строку, содержащую столько точек, сколько получается при выполнении арифметического оператора. Если результат равен 0, то результат пустая строка. Когда дело доходит до вычитания, первое число всегда будет больше или равно второго. Арифметические операторы + Сложение - Вычитание * Умножение // Целочисленное деление function dotCalculator (equation) { } dotCalculator ("..... + ...............") // "...................." dotCalculator ("..... - ...") // ".." dotCalculator ("..... * ...") // "..............." Задание 10. 7 Даны два числа и арифметический оператор (его название в виде строки). Напишите код функции, которая возвращает результат выполнения оператора над числами. Числа будут целыми положительными числами, и a всегда будет первым числом в операции, а b всегда вторым. Четыре оператора — это "add", "subtract", "divide", "multiply" («сложение», «вычитание», «деление», «умножение»). function arithmetic(a, b, operator) { } arithmetic(1, 2, "add") // 3 90
arithmetic(8, 2, "subtract") // 6 arithmetic(5, 2, "multiply") // 10 Задание 11. 8 Напишите функцию, которая возвращает день недели в соответствии с введенным номером: 1 returns "Sunday" 2 returns "Monday" 3 returns "Tuesday" 4 returns "Wednesday" 5 returns "Thursday" 6 returns "Friday" 7 returns "Saturday" В противном случае возвращается сообщение “Wrong, please enter a number between 1 and 7" (Неверно, пожалуйста, введите число от 1 до 7). function whatday(num) { } whatday(1) // 'Sunday' whatday(2) // 'Monday' whatday(8) // 'Wrong, please enter a number between 1 and 7' Задание 12. 8 Напишите функцию, которая получает на вход строку и выдает выходные данные в соответствии со следующей таблицей: Ввод "Jabroni" "School Counselor" "Programmer" Вывод "Patron Tequila" "Anything with Alcohol" "Hipster Craft Beer" 91
Ввод "Bike Gang Member" "Politician" "Rapper" иначе Вывод "Moonshine" "Your tax dollars" "Cristal" "Beer" Если входные данные для функции не являются значениями в таблице, то возвращаемое значение должно быть "Beer ". Исходные данные могут быть в любом регистре. function getDrinkByProfession(param){ } getDrinkByProfession("jabrOni") // "Patron Tequila" getDrinkByProfession("scHOOl counselor") // "Anything with Alcohol" getDrinkByProfession("prOgramMer") // "Hipster Craft Beer" Задание 13. 8 О, нет! Функция Timmy Evalobject не работает. Она использует Switch/Cases для оценки заданных свойств объекта, можете ли вы исправить функцию Тимми? function evalObject(value){ var result = 0; switch(value.operation){ case'+': result = value.a + value.b; case'-': result = value.a - value.b; case'/': result = value.a / value.b; case'*': result = value.a * value.b; case'%': result = value.a % value.b; case'^': result = Math.pow(value.a, value.b); } return result; } 92
Задание 14. 8 Функция не возвращает правильные значения. Можете ли вы понять, почему? function getPlanetName(id) { var name; switch (id) { case 1: name = 'Mercury' case 2: name = 'Venus' case 3: name = 'Earth' case 4: name = 'Mars' case 5: name = 'Jupiter' case 6: name = 'Saturn' case 7: name = 'Uranus' case 8: name = 'Neptune' } return name; } Задание 15. 8 Вы получили сообщение Whatsup от неизвестного номера. Может ли это быть от этой девочки/мальчика с иностранным акцентом, которого вы встретили вчера вечером? Напишите простую функцию, чтобы 93
проверить, содержит ли строка слово Hallo на разных языках. Это языки возможных людей, которых вы встретили накануне вечером: • • • • • • • hello – english ciao – italian salut – french hallo – german hola – spanish ahoj – czech republic czesc – polish function validateHello (greetings) { } validateHello('ahoj') // true validateHello('meh') // false Практическая работа на тернарный оператор Задание 1. 8 Число n — входной параметр функции. Код функции должен определить, является ли переданное число n четным или нет. Функция должна возвращать либо значение true, либо значение false. Числа могут быть положительными или отрицательными, целыми числами или числами с плавающей запятой. function testEven(n) { } testEven(0) // true testEven(0.5) // false testEven(-4) // true 94
Задание 2. 8 Функция получает массив целых чисел и возвращает сумму всех положительных чисел массива. function positiveSum(arr) { } positiveSum([1,2,3,4,5]) // 15 positiveSum([1,-2,3,4,5]) // 13 positiveSum([]) // 0 Задание 3. 8 У меня есть кошка и собака. Я получил их одновременно с котенком (щенком). Это было много лет назад. Определите их соответствующий возраст на сегодняшний день как массив [человеческие годы, кошачьи годы, собачьи годы]. Человеческие года >= 1 и могут быть только целые числа. Кошачьи Годы 15 кошачьих лет за первый год человеческих +9 кошачьих лет на второй год человеческих +4 кошачьих года за каждый последующий год Собачьи Годы 15 собачьих лет за первый год человеческих +9 собачьих лет за второй год человеческих +5 собачьих лет за каждый последующий год var humanYearsCatYearsDogYears = function(humanYears) { } 95
humanYearsCatYearsDogYears(1) // [1,15,15] humanYearsCatYearsDogYears(2) // [2,24,24] humanYearsCatYearsDogYears(10) // [10,56,64] Задание 4. 8 Даны 2 строки a и b, функция вернет строку вида short + long + short, с более короткой строкой снаружи и более длинной строкой внутри. Строки не могут быть одинаковой длины, но они могут быть пустыми (нулевой длины). function solution(a, b) { } solution('45', '1') // '1451' solution('13', '200') // '1320013' solution('Soon', 'Me') // 'MeSoonMe' Задание 5. 8 Ваш друг приглашает вас на плавучий понтон примерно в 1 км от пляжа. На понтоне есть огромная горка, которая сбрасывает вас прямо в океан, недалеко от лестницы, используемой для подъема. Когда вы ныряете с горки в воду, вы видите акулу, парящую в темноте под понтоном. Вам нужно выяснить, доберется ли до вас акула, прежде чем вы сможете добраться до понтона. Когда вы производите мысленные вычисления в воде, вы либо замираете, либо плывете, когда понимаете, что можете добраться до понтона быстрее акулы. Даны 5 переменных: sharkDistance — расстояние от акулы до понтона. Акула съест вас, если доберется до вас до того, как вы доберетесь до понтона. sharkSpeed — скорость в метрах в секунду, с которой акула может двигаться. 96
pontoonDistance — расстояние до понтона от человека в метрах. youSpeed — скорость в метрах в секунду, с которой человек может плавать. dolphin — логическое значение, если true, уменьшается скорость плавания акулы вдвое, поскольку дельфин нападет на нее. Если человеку удастся добраться до понтона, функция должна вернуть "Alive!", если нет — вернуть "Shark Bait!". function shark (pontoonDistance, sharkDistance, youSpeed, sharkSpeed, dolphin) { } shark(12, 50, 4, 8, true) // "Alive!" shark(7, 55, 4, 16, true) // "Alive!" shark(24, 0, 4, 8, true) // "Shark Bait!" Задание 6. 8 Вам даны длина и ширина 4-стороннего многоугольника. Многоугольник может быть либо прямоугольником, либо квадратом. Если это квадрат, верните его площадь. Если это прямоугольник, верните его периметр. const areaOrPerimeter = function(l , w) { } areaOrPerimeter(4 , 4) // 16 areaOrPerimeter(6 , 10) // 32 Задание 7. 8 Напишите функцию, которая преобразовывает логическое значение в строку “Yes” или “No”. function boolToWord (bool) { 97
} boolToWord(true) // 'Yes' boolToWord(false) // 'No' Задание 8. 8 Мужские сперматозоиды у человека и других млекопитающих гетерогаметны и содержат один из двух типов половых хромосом. Они либо X, либо Y. Однако женские гаметы или яйцеклетки содержат только Х-половую хромосому и являются гомогаметными. Cперматозоид определяет пол индивидуума. Если сперматозоид, содержащий Х-хромосому, оплодотворяет яйцеклетку, полученная в результате зигота будет XX или женской. Если сперматозоид содержит Y-хромосому, то полученная в результате зигота будет XY или мужской. Напишите функцию, которая сможет определить будет ли пол потомства мужским или женским, основываясь на X или Y-хромосоме, присутствующей в сперме мужчины. Если сперматозоид содержит Х-хромосому, функция возвращает "Congratulations! You're going to have a daughter.”. Если сперма содержит Y-хромосому: "Congratulations! You're going to have a son.”. function chromosomeCheck(sperm) { } chromosomeCheck('XY') // "Congratulations! You're going to have a son." chromosomeCheck('XX') // "Congratulations! You're going to have a daughter." Задание 9. 8 Функция принимает два аргумента: текущий возраст отца, текущий возраст его сына. Функция возвращает, сколько лет назад отец был в 98
два раза старше своего сына (или через сколько лет он будет в два раза старше). function twiceAsOld(dadYearsOld, sonYearsOld) { } twiceAsOld(36,7) // 22 twiceAsOld(55,30) // 5 twiceAsOld(42,21) // 0 twiceAsOld(22,1) // 20 twiceAsOld(29,0) // 29 Задание 10. 8 В некоторых языках сценариев, таких как PHP, существует логический оператор называемый Exclusive Or (Исключительный Или). Он возвращает true, если одно из двух логических выражений равно true, в противном случае false. Задача — определить функцию xor(a, b), где a и b — два логических выражения, которые должны быть вычислены. Функция xor должна возвращать true, если одно из двух выражений имеет значение true, в противном случае false. function xor(a, b) { } xor(false, false) // false xor(true, false) // true xor(false, true) // true xor(true, true) // false Задание 11. 8 Напишите функцию, которая умножает заданное число на восемь, если оно четное, и на девять в противном случае. 99
function simpleMultiplication(number) { } simpleMultiplication(2) // 16 simpleMultiplication(1) // 9 simpleMultiplication(8) // 64 simpleMultiplication(4) // 32 Задание 12. 8 Напишите функцию с именем setAlarm, которая получает два параметра. Первый параметр, employed, имеет значение true всякий раз, когда вы работаете, а второй параметр, vacation, имеет значение true всякий раз, когда вы находитесь в отпуске. Функция должна возвращать значение true, если вы работаете, а не находитесь в отпуске (потому что именно при таких обстоятельствах вам необходимо установить будильник). В противном случае она должна возвращать значение false. function setAlarm(employed, vacation){ } setAlarm(true, true) // false setAlarm(false,true) // false setAlarm(true, false) // true Задание 13. 8 Когда весной цветет японская вишня, ее называют «сакура», и ею очень восхищаются. Лепестки начинают опадать в конце апреля. Предположим, что скорость падения лепестка составляет 5 сантиметров в секунду (5 см/с), и лепестку требуется 80 секунд, чтобы достичь земли с определенной ветки. Напишите функцию, которая принимает скорость (в см/с) лепестка в качестве входных данных и возвращает время, необходимое для того, чтобы он достиг земли с той же ветки. 100
function sakuraFall(v) { } sakuraFall(5) // 80 sakuraFall(10) // 40 sakuraFall(-1) // 0 Задание 14. 7 Две красные бусины помещаются между каждыми двумя синими бусинками. Есть N синих бусин. Посмотрев на приведенную ниже схему, определите количество красных бусин. @ @@ @ @@ @ @@ @ @@ @ @@ @ Нашите код функции count_red_beads(n) так, чтобы он возвращал количество красных шариков. Если синих шариков меньше 2, функция вернет 0. function countRedBeads(n) { } countRedBeads(0) // 0 countRedBeads(1) // 0 countRedBeads(3) // 4 countRedBeads(5) // 8 Задание 15. 8 Ваши одноклассники попросили вас скопировать для них некоторые документы. Вы знаете, что есть "n" одноклассников, а в документах есть "m" страниц. Задача — подсчитать, сколько пустых страниц вам нужно. Напишите для решения задачи функцию. Если n < 0 или m < 0, функция вернет 0, в противном случае число необходимых страниц. function paperwork(n, m) { } 101
paperwork(5,5) // 25 paperwork(5,-5) // 0 paperwork(-5,-5) // 0 Задание 16. 8 Есть функция describeAge, которая принимает параметр age (положительное целое число) и выполняет следующее: function describeAge(age) { if (age <= 12) { return "You're a(n) kid"; } else if (age >= 13 && age <= 17) { return "You're a(n) teenager"; } else if (age >= 18 && age <= 64) { return "You're a(n) adult"; } else { return "You're a(n) elderly"; } } Задача — максимально сократить код. Ограничение — не более 137 символов. Задание 17. 8 Функция saleHotdogs принимает параметр n — количество хот-догов, которое купит клиент. Разные количества хотдогов имеют разные цены (см. следующую таблицу), верните, сколько денег потратит клиент, чтобы купить n хот-догов. число хотдогов цена за штуку n<5 100 n >= 5 and n < 10 95 n >= 10 90 102
function saleHotdogs(n) { } saleHotdogs(1) // 100 saleHotdogs(4) // 400 saleHotdogs(5) // 475 103
МНОГООБРАЗИЕ ФУНКЦИЙ Многие структурные языки программирования поддерживают разработку процедур и функций для введения в язык новых команд и функций соответственно. С точки зрения языка команда — это указание компьютеру совершить какое-либо действие, функция — это слово, возвращающее какое-либо значение, явно или неявно зависящее от значения аргумента. Функции могут выступать в качестве параметров команд или могут быть элементом выражения. Язык JavaScript также поддерживает внедрение команд и функций, но разработчики языка сэкономили на инструментах разработки. И в том и в другом случае разработка оформляется как функция, но лишь оператор return, включенный в тело функции делает ее таковой воистину. function  ([,...]) {  }, где  — имя функции, которое должно состоять только из одного слова; , ... — необязательные входные аргументы (параметры) функции;  — тело функции, состоящее из последовательности операторов (команд) JavaScript. Вызвать функцию на выполнение можно написанием ее имени вместе с круглыми скобками и значениями аргументов либо непосредственно в скрипте, либо в теле другой функции, либо как обработчик события (пример смотри на странице 12). Вызов функции В объектно-ориентированном программировании все функции рассматриваются как методы объектов. Если кажется, что функция не принадлежит ни одному объекту, то в JavaScript всегда есть глобальный объект по умолчанию window — это окно браузера, в котором отображается html-документ. Можно считать, что функция по умолчанию принадлежит html-странице. myFunction() и window.myFunction() — это одна и та же функция. 104
Функции вместе с локальными переменными как инструмент разработки дают возможность при решении сложных задач разбивать их на простые подзадачи, на каждую из которых можно написать автономную функцию и затем использовать их как кирпичики в постройке всего дома, то есть в общем решении задачи. П р и м е р 1. Функция создает оператор приветствие. Вызов функции осуществляется в скрипте function приветствие () { let строка='Доброе время суток! \r\n ' строка += 'Мы рады приветствовать Вас на нашем сайте' alert (строка) } приветствие () П р и м е р 2. Функция создает слово-функцию случайное_целое, возвращающую случайное целое число в диапазоне от 1 до 5. Оператор r e t u r n  присваивает имени функции значение своего параметра . О методах объекта Math смотри на странице 128. function случайное_целое () { let x = Math.random () * 5 + 1 return Math.round (x) } document.write (“1 испытание: ”, случайное_целое(), '<br>') document.write (“2 испытание: ”, случайное_целое(), '<br>') document.write (“3 испытание: ”, случайное_целое(), '<br>') console.log (случайное_целое()) 105
П р и м е р 3. Функция с параметром function факториал (n) { let факт = 1 for (i = 1; i <= n; i++) факт = факт * i return факт } document.write ("1! = ",факториал(1),"<br>") document.write ("2! = ",факториал(2),"<br>") document.write ("3! = ",факториал(3),"<br>") document.write ("4! = ",факториал(4),"<br>") document.write ("5! = ",факториал(5),"<br>") П р и м е р 4. Функция с двумя параметрами function кратное (число, делитель) { if (число % делитель == 0) return true else return false } 106
document.write ("11 кратное 5 ? = ",кратное(11,5),"<br>") document.write ("15 кратное 5 ? = ",кратное(15,5),"<br>") П р и м е р 5. Функция с совокупностью параметров Парематр rest … в аргументах функции собирает совокупность значений в одну переменную. function maximum (...a) { return Math.max(...a) } console.log(maximum (5, 9, 7, 8)) // 9 П р и м е р 6. Вызов функции из другой функции function все_кратные_3 (начало_отрезка, конец_отрезка) { for (i = начало_отрезка; i <= конец_отрезка; i++) { if (кратное (i,3)) document.write ("число",i," кратно 3 <br>") } } все_кратные_3 (1,15) П р и м е р 7. Досрочный выход из цикла function простое (число) { for (i=2; i < число; i++) { if (число%i == 0) return false 107
} return true } document.write ("8 простое? = ",простое(8),"<br>") document.write ("5 простое? = ",простое(5),"<br>") П р и м е р 8. Рекурсивные функции function факториал_рек (n) { if (n==1) return 1 return n*факториал_рек (n-1) } for (i=1; i<=5; i++) { document.write (i, "! = ", факториал_рек (i), "<br>") } Таблица значений стека n 4 4*3! 24 3 3*2! 6 2 2*1! 2 1 1! 1 Написать код функции, проверяющей, является ли заданное число степенью двойки. function st2 (n) { if (n == 1) return true if (parseInt(n) != n) return false return st2 (n/2) } 108
console.log (st2 (7)) // false console.log(st2(8)) // true Написать код функции, возвращающей сумму цифр заданного целого числа function num (N) { if (parseInt (N/10) == 0) return N return (N%10) + num (parseInt(N/10)) } console.log (num(123)) // 6 Написать код функции, возвращающей сумму всех элементов массива function Sum(newArr1, i, sum) { // console.log("arr", newArr1[i]) sum += newArr1[i]; if (i == newArr1.length - 1) return sum; i++; return Sum(newArr1, i, sum); } console.log(Sum([7, 5, 6, -3, -2, 8, -5], 0, 0)) // 16 П р и м е р 9. Локальная переменная (область видимости) В спецификации ES-2015 предусмотрены способы объявления переменных через let и const помимо var. Область видимости переменной let — это блок, заключенный в фигурные скобки {...}. Однако в функции как и раньше можно объявлять переменную через var и ее значение будент доступно только в пределах данной функции. function локал_пер () { var лп='Привет из функции' document.write ("функция локал_пер: ", лп, "<br>") } локал_пер () document.write ("скрипт: ", лп, "<br>") 109
Область видимости глобальных переменных простирается на весь html-документ, тогда как область видимости локальных переменных ограничивается только блоком, в котором она определена. Область видимости — это строки кода, где доступно текущее значение переменной. В примере 8 создается локальная переменная лп, значение которой может быть выведено только из тела функции. Внешний вызов будет проигнорирован браузером. В следующем примере создается в скрипте глобальная переменная s, значение которой увеличивается на 1 при каждом вызове функции глоб_Пер П р и м е р 10. Глобальная переменная var s = 0 function глоб_Пер () { s++ } глоб_Пер () document.write ("скрипт: ",s,"<br>") глоб_Пер () document.write ("скрипт: ",s,"<br>") 110
Анонимные функции В JavaScript можно создавать анонимные функции, то есть функции без имени. Анонимные функции могут выступать в качестве значения переменной, таким же как строка или число. Поэтому функции можно присваивать переменным, элементам массива и свойствам объектов, а так же передавать в качестве аргументов другим функциям. var  = function ([, ...]) {  },  — имя переменной, элемента массива, свойства объекта; ,... — необязательные входные аргументы (параметры) функции;  — тело функции, состоящее из последовательности операторов (команд) JavaScript. К анонимной функции можно обращаться по имени . где Анонимные функциии называют еще функциями-выражениями. Функция, определяемая в качестве функции-выражения, в спецификации языка называется «Function Expression» (сокращенно FE). В отличие от именованной функции «Function Declaration» (FD), определения FE не поднимаются вверх, поэтому их нельзя вызывать до того момента, пока интерпретатор не достиг строки с определением функции. Пример1 console.log (случайное_целое()) // случайное_целое is not a function var случайное_целое = function () { return Math.round(Math.random()*100) } console.log (случайное_целое()) // 98 Пример2 var приветствие2 = function () { строка='Доброе время суток! \r\n Мы рады приветствовать Вас на нашем сайте' alert (строка) } приветствие2 () 111
Пример3 var x = prompt ("Введите значение x"); if (x > 0) вывод = function() { document.write("x больше 0") } else вывод = function() {document.write("x меньше или равно 0")} вывод() В примерах создается функция, а затем переменной присваивается ссылка на нее. Вызов функции на исполнение осуществляется через имя переменной с круглыми скобками, в которых могут быть параметры. При этом вызвать анонимные функции можно только после их описания. Задание Придайте функции кратное анонимный вид function кратное (число, делитель) { if (число % делитель == 0) return true else return false } Анонимная функция как обработчик события Выше был рассмотрен способ вызова функции обработки события (параграф «События») путем добавления соответствующего атрибута в тег html-элемента. Существует еще один способ вызова обработчика события непосредственно в скрипте через обращение к элементу по его идентификатору id с использованием анонимной функции. . = function () {  }, где  — идентификатор элемента,  — имя события,  — тело обработчика. Пример <input id="кнопка" type="button" value="Нажми меня"> 112
<script> кнопка.onclick = function() { alert( 'Привет нажиматель' ) } </script> Задание1 Создайте обработчик события для элемента img с помощью анонимной функции вместо атрибутов-событий. <IMG SRC=“smile.gif” onMouseOver=”смени_изо ()” onMouseOut=“верни_изо ()”> Задание2 Разработайте скрипт с обработчиками событий так, чтобы в единой совокупности чекбоксов (не менее 5) можно было выбирать только два из них. Стрелочные функции В ES2015 появились стрелочные функции. В описании стрелочной функции ключевое слово function убирается и добавляется стрелка после перечисления аргументов. Например, анонимную функцию xxx = function (x) { return x * x * x } можно заменить стрелочной xxx = (x) => x * x * x Если функция возвращает результат выражения, то return и фигурные скобки тоже можно не писать. Cтрелку нельзя переносить на новую строку. Если аргумент один, то круглые скобки необязательны, а вот если их несколько или ни одного — то скобки требуются. Стрелочные функции очень удобны при работе с массивами в таких методах как map, reduce, filter, every и some (переборные методы массива). Также стрелочные функции полезны в виде функций обратного вызова. В обычной функции значение this связывается с элементом, по которому произошел клик, а в стрелочной функции значением this будет объект window. 113
Задание Перепишите функцию случайное_целое из обычного вида в стрелочный вид. function случайное_целое (x) { return Math.round(Math.random()*x) } Функции высшего порядка Функции обратного вызова Функцию, которая передается в качестве аргумента другой функции называют функцией обратного вызова или callback-функцией. В JavaScript функции — это объекты класса Function, создаваемые конструктором Function. Поэтому функции могут принимать другие функции в качестве аргументов, а также функции могут возвращать функции в качестве результата. Функции, которые это умеют, называются функциями высшего порядка. Обратный вызов позволяет в функции исполнять код, который задается в аргументах. Этот код может быть определен в других местах программного кода и может быть недоступным для прямого вызова из этой функции. П р и м е р 1. function xy (x1,y1,callback) { document.write ('для чисел ' + x1 + ' и '+ y1) callback (x1,y1) } xy (5,7, function (x,y) {s=x+y;document.write ('сумма = ' + s)}) // 12 xy (5,7, function (x,y) {p=x*y;document.write ('произведение = ' + p)}) // 35 В примере показано использование обратной функции с параметрами. При вызове основной функции xy создается обратная функция и сразу выполняется. 114
П р и м е р 2. Напишем функцию, которая принимает массив (про массивы смотрите параграф «Массивы») и предикат и возвращает истину, если в массиве все без исключения элементы удовлетворяют предикату (условию). let arrPredicat = (a,p) => { for (let i = 0; i < a.length; i++) { if (!p(a[i])) {return false} } return true } let arr=[2,4,1,6,8] console.log (arrPredicat(arr, function (x) {return (x%2==0)})) // false let arr=[2,4,6,8] console.log (arrPredicat(arr, function (x) {return (x%2==0)})) // true console.log (arrPredicat (arr, function (x) {return (x > 0)})) // true П р и м е р 3. Напишем код функции с входным аргументом в виде колбэкфункции, преобразующей каждый элемент исходного массива. function mapForEach(arr, fn) { const newArray = []; for(let i = 0; i < arr.length; i++) { newArray.push(fn(arr[i])) } return newArray; } Пусть имеется массив строк. Создадим на его основе массив с числами, каждое из которых представляет собой длину строки, хранящейся в каждом элементе исходного массива. const strArray = ['JavaScript', 'Python', 'PHP', 'Java', 'C']; const lenArray = mapForEach(strArray, function(item) { return item.length }) console.log(lenArray) // [ 10, 6, 3, 4, 1 ] 115
Пусть имеется массив строк. Создадим на его основе массив с теми же строками, но перевернутыми в обратном порядке. const revArray = mapForEach(strArray, function(item) { return item.split("").reverse().join("") }) console.log(revArray) // [ "tpircSavaJ", "nohtyP", "PHP", "avaJ", "C" ] П р и м е р 4. 7 Напишите общую цепочку функций, которая принимает начальное значение первой функции и массив функций. Входными данными для каждой функции являются выходные данные предыдущей функции (за исключением первой функции, которая принимает начальное значение в качестве входных данных). Вернуть нужно окончательное значение после завершения выполнения цепочки. function chain(v, fns) { return fns.reduce(function(v, fn) { return fn(v) }, v) } function add(num) { return num + 1 } function mult(num) { return num * 30 } chain(2, [add, mult]) // 90 П р и м е р 5. 7 Напишем функцию factory, которая принимает число в качестве параметра и возвращает другую функцию. Возвращаемая функция прини116
мает массив чисел в качестве своего параметра и возвращать массив этих чисел, умноженный на число, которое было передано в первую функцию. В приведенном ниже примере 5 — это число, переданное в первую функцию, которая возвращает функцию, принимающую массив и умножающую все элементы в нем на пять. var fives = factory(5) var myArray = [1, 2, 3] fives(myArray) // [5, 10, 15] function factory(x) { return function (arr) { let newArr=[] for (i=0; i< arr.length; i++) { newArr.push (arr[i]*x) } return newArr } } Функция как объект Существует еще один способ создания функции — через конструктор.  = new Function (,[,, ...]), где  — имя функции, ,,,… — строковые аргументы, сначала идут параметры, на последнем месте — тело функции, которое тоже выступает строкой. Если аргумент всего один — то это тело функции. Пример среднее = new Function('a','b','c','return (a+b+c)/3') alert(среднее(1,2,3)) // 2 117
Самовызываемые функции (self-invoking function) Анонимные функции можно сделать самовызывающими и немедленно срабатывающими. Они называются аббревиатурой IIFE (Immediately Invoked Function Expression). Самовызывающее выражение запускается автоматически, без вызова. Функции-выражения будут выполняться автоматически, если за выражением следуют круглые скобки (). (function () { console.log("Привет! Я запустилась сама!") }) () Если эту функцию присвоить переменной, то ее значение для данного примера будет undefined, но если самовызывающая функция будет возвращать значение, то оно может быть присвоено переменной let s = (function () { return "Я вернула значение" }) () console.log(s) // Я вернула значение Если возвращаемое значение функция, то к переменной s добавляются круглые скобки при ее вызове. let s = (function () { return function () { return "Я из вложенной функции" } }) () console.log(s()) // Я из вложенной функции Особенность использования самовызывающихся функций состоит в том, что их код выполняется только один раз, а его результат можно сохранить во «внешней среде» (без объявления глобальных переменных). Замыкания (Closures) Переменные в JavaScript принадлежат либо к локальной области видимости, либо к глобальной области. Глобальные переменные можно сделать локальными (частными/private) с помощью замыканий. 118
Функция получает доступ ко всем переменным, определенным внутри функции, например: function myFunc() { let a = 4 return a * a } Но функция также может обращаться к переменным, определенным вне функции, например: let a = 4 function myFunc() { return a * a } В последнем примере a — глобальная переменная. На веб-странице глобальные переменные принадлежат странице. Глобальные переменные могут использоваться и изменяться всеми остальными скриптами на странице. В первом примере a — локальная переменная. Локальную переменную можно использовать только внутри функции, в которой она определена. Она скрыта от других функций и другого кода сценариев. Глобальные и локальные переменные с одинаковым именем — это разные переменные. Изменение одной не приводит к изменению другой. Переменные, созданные без ключевого слова объявления (var, let или const), всегда являются глобальными, даже если они созданы внутри функции. Глобальные переменные действуют до тех пор, пока страница не будет удалена, например, когда вы переходите на другую страницу или закрываете окно. Локальные переменные имеют короткий срок жизни. Они создаются при вызове функции и удаляются после ее завершения. Предположим, что мы хотим использовать переменную для подсчета чего-либо и хотим, чтобы этот счетчик был доступен всем функциям. Мы можем использовать глобальную переменную и функцию для увеличения счетчика. let counter = 0 function add() { counter += 1 119
} add() // 1 add() // 2 add() // 3 В приведенном выше решении есть проблема: любой код на странице может изменить счетчик без вызова add(). Счетчик должен быть локальным для функции add(), чтобы предотвратить его изменение другим кодом. function add() { let counter = 0 counter += 1 return counter } add() // 1 add() // 1 add() // 1 Этот вариант не работает, потому что локальный счетчик каждый раз сбрасывается, когда вызывается функция. В JavaScript можно в теле функции объявлять другие функции. Такие функции называются вложенными или внутренними. Внутренняя функция JavaScript может решить проблему счетчика. Все функции имеют доступ к глобальной области видимости. Фактически, в JavaScript все функции имеют доступ к области над ними. Вложенные функции также имеют доступ к области над ними. В примере внутренняя функция plus() имеет доступ к переменной счетчика в родительской функции function add() { let counter = 0 function plus() {counter += 1} plus() return counter } add() // 1 add() // 1 add() // 1 plus() // plus is not defined 120
Решить проблему счетчика можно, если получить доступ к вложенной функции plus() за пределеми родительской функции. Кроме того, необходимо найти способ выполнить инициализацию переменной counter = 0 только один раз. Для этого нужно замыкание. const add = function () { let counter = 0; return function () { counter += 1; return counter; } }() add() // 1 add() // 2 add() // 3 Переменной add присваивается возвращаемое значение самовызывающей анонимной функции. Функция самовызова запускается только один раз. Она устанавливает счетчик в ноль и возвращает функциональное выражение. Таким образом переменная add становится функцией. Замечательно то, что она может получить доступ к счетчику в родительской области. Это называется замыканием JavaScript. Это позволяет функции иметь «частные» переменные. Счетчик защищен областью действия анонимной самовызываемой функции. Замыкание — это функция, имеющая доступ к родительской области видимости переменных даже после закрытия родительской функции. Замыкания — это «вложенные» функции, которые «замыкают» на себя переменные и аргументы функции, внутри которой определены. Примеры применения замыканий 1. Создание функций, имеющих своё изменяемое состояние. 2. Создание функций, в свою очередь тоже создающих функции. 3. Привязка функции к определённому контексту. 4. Защита данных (инкапсуляция). 5. Придание приватности методам и свойствам объекта. https://maxello.gitbooks.io/jsnote/content/05_functions_scopes/zamikaniya_v_javascript.html 121
Фабричная функция Фабричная функция аналогична функциям-конструкторам или функциям класса, но вместо использования new для создания объекта фабричные функции просто создают объект и возвращают его. Фабричные функции — очень полезный инструмент в JavaScript. Фабричные функции в JavaScript похожи на функции-конструкторы или функции класса, но они не требуют использования ключевого слова this для внутренних значений или использования ключевого слова new при создании экземпляров новых объектов. Фабричные функции могут содержать внутренние значения, методы и т. д., как обычные функции. Фабричные функции отличаются от обычных тем, что они всегда возвращают объект, который будет содержать любое значение, метод и т. д. Если у нас сложная логика и нам приходится снова и снова создавать несколько объектов с одной и той же логикой, мы можем один раз написать логику в функции и использовать эту функцию как фабрику для создания наших объектов. Это точно так же, как реальная фабрика, производящая продукцию. function createRobot(name) { return { name: name, talk: function () { console.log('My name is ' + name + ', the robot.') } } } const robo1 = createRobot('Chitti') robo1.talk() const robo2 = createRobot('Chitti 2.O Upgraded') robo2.talk() var Person = function (name, age) { var person = {} person.name = name person.age = age person.greeting = function () { 122
return ( 'Hello I am ' + person.name + '. I am ' + person.age + ' years old. ' ) } return person } var person1 = Person('Abhishek', 20) console.log(person1.greeting()) var person2 = Person('Raj', 25) console.log(person2.greeting()) Практическая работа на фабричные функции Задание 1. 7 Я новичок в программировании, поэтому не знаю, что не так с моим кодом. Свойство objMethod должно вызываться функцией myFunction. Можете ли вы исправить синтаксис, чтобы myFunction снова работала? Пожалуйста, проверьте такие вещи, как скобки, запятые и регистр букв. ВАЖНО: возврата только «строки» недостаточно. Нам необходимо использовать точечную нотацию объекта. function myFunction() { var MyObject = { objProperty: "string" objMethod: function() { return myObject.objProperty; } } return myObject.Objmethod(); 123
} myFunction().objMethod(), 'string' Задание 2. 7 Определите пользователя фабричной функции, которая принимает следующие параметры в следующем порядке: • • • • • • • firstName lastName age gender employed occupation married Названия ключей объекта должны совпадать с названиями параметров, упомянутых выше. Объект должен также иметь следующие методы say Name, который возвращает полное имя человека (например, "John Doe") introduce, который возвращает строку следующего формата: "Hello, my name is <FULL_NAME>. I am <AGE> years old. I am a <GENDER>." Каждое предложение отделяется от следующего ровно ДВУМЯ пробельными символами. function person(/* parameters */) { } var john = person("John", "Doe", 18, "male", false, null, true); john.firstName // "John" john.lastName // "Doe" john.age // 18 john.gender // "male" john.employed // false john.occupation // null john.married // true 124
john.sayName() // "John Doe" john.introduce() // "Hello, my name is John Doe. I am 18 years old. I am a male." var cathy = person("Cathy", "Destexhe", 16, "female", true, "Designer", false) cathy.firstName // "Cathy" cathy.lastName // "Destexhe" cathy.age // 16 cathy.gender // "female" cathy.employed // true cathy.occupation // "Designer" cathy.married // false cathy.sayName() // "Cathy Destexhe" cathy.introduce() // "Hello, my name is Cathy Destexhe. I am 16 years old. I am a female." Задание 3. 7 Мы хотим создать функцию-конструктор NameMe, которая принимает имя и фамилию в качестве параметров. Функция объединяет имя и фамилию и сохраняет значение в свойстве name. Мы уже реализовали эту функцию, но при запуске кода свойство «name» доступно, а «firstName» и «lastName» — нет. Все свойства должны быть доступны. Можете ли вы найти ошибку? function NameMe(first, last) { this.firstName = first; this.lastName = last; return {name: this.firstName + ' ' + this.lastName}; } var n = new NameMe('John', 'Doe'); n.firstName //Expected: John n.lastName //Expected: Doe n.name //Expected: John Doe 125
Практическая работа на замыкания Задание 1. 8 Почему GreetingAbe() на самом деле не приветствует Эйба? Доработайте код, чтобы он выполнялся правильно. let name = 'Abe' const greetAbe = () => 'Hello, ' + name + '!' name = 'Ben' const greetBen = () => 'Hello, ' + name + '!' greetAbe() // 'Hello, Abe!' greetBen() // 'Hello, Ben!' Задание 2. Создайте функцию, которая создает таймер обратного отсчета. Каждый вызов функции уменьшает значение таймера на 1 секунду и возвращает оставшееся время. Если время истекло, функция возвращает сообщение «Время вышло!». 1. 2. 3. Создайте функцию createTimer, которая принимает начальное значение времени в секундах и возвращает другую функцию. Возвращаемая функция должна уменьшать значение времени на 1 секунду при каждом вызове и возвращать оставшееся время. Создайте кнопку на странице, при нажатии на которую будет вызываться функция таймера и значение оставшегося времени будет отображаться на странице. function createTimer(initialTime) { } const timer = createTimer(10) 126
Задание 3. Создайте функцию, которая генерирует уникальные идентификаторы. Каждый вызов функции должен возвращать новый уникальный идентификатор. 1. 2. 3. Создайте функцию createIdGenerator, которая возвращает другую функцию. Возвращаемая функция должна увеличивать внутренний счетчик и возвращать строку в формате id-1, id-2, и так далее. Создайте кнопку на странице, при нажатии на которую будет генерироваться новый уникальный идентификатор и отображаться на странице. function createIdGenerator() { } const generateId = createIdGenerator() Задание 4. 7 Определите функцию-счетчик, которая возвращает функцию, возвращающую возрастающее значение. Первое значение должно быть равно 1. Вам придется использовать замыкания. function counter() { } const counterOne = counter() const counterTwo = counter() counterOne()) // 1 counterOne()) // 2 counterTwo() // 1 counterTwo()) // 2 Задание 5. 7 127
Это простое упражнение для понимания особенности языка JavaScript, называемой замыканием. Функция buildFun вернет массив функций. Единственный параметр, принимаемый функцией buildFun, — это количество элементов возвращаемого массива N. Желаемый результат заключается в том, что после выполнения всех функций в массиве должны быть возвращены числа от 0 до N. function buildFun(n) { } Практическая работа на функции Задание 1. Разработайте функцию maximum2 (a, b), возвращающую максимальное число из двух заданных. Усовершенствуйте функцию таким образом, чтобы она находила максимальное число из трех заданных maximum3 (a, b, c). Задание 2. Разработайте стрелочную функцию sign (x), которая возвращает знак числа x. Если x > 0, то возвращается 1, если x < 0, то возвращается –1, при x = 0 возвращается 0. Задание 3. Разработайте анонимную функцию трех аргументов (a, b, c), возвращающую среднее арифметическое аргументов. Присвойте функцию переменной с именем avg. Задание 4. Разработайте функцию суммаНечетных (a, b), возвращающую сумму всех нечетных чисел из диапазона от a до b (a < b). Для проверки текущего числа на нечетность создайте функцию нечетное (x). Задание 5. Напишите функцию rndAb (a,b), возвращающую случайное целое число в диапазоне от a до b. 128
Задание 6. Напишите функцию div (x, y), дающую целую часть от деления числа x на число y. Запрещено использовать функцию toFixed, parseInt и свойства объекта Math. Задание 7. Дано рациональное число. Напишите функцию okr (x,d), возвращающую округленное число x до d знаков после запятой. Запрещено использовать функцию toFixed и свойства объекта Math. Разрешено использовать функцию parseInt. Задание 8. Напишите функцию dtri (x,y,l), рисующую в элементе canvas треугольник по заданным координатам одной из вершин и длине стороны. Напишите новую функцию figura (n), которая будет рисовать на холсте любой ряд из n треугольников. Вызывайте в ней функцию dtri. Задание 9. Напишите функцию rndColor (), возвращающую случайное значение в диапазоне от #000000 до #FFFFFF в шестнадшатеричном формате. Используйте для перевода десятичных чисел в 16-ричный формат функцию toString(16). Количество различных чисел в данном диапазоне 16 777 215. Задание 10. Напишите функцию сектор (x, y, start, end, radius), выводящую на холст (canvas) сектор круга — дугу с радисами на концах. Переменные x и y — координаты точки, откуда выходят радиусы сектора. Используя сектор и rndAb (из задания 5), нарисуйте в любом месте холста N секторов случайного размера и радиуса. 129
Добавьте случайности в задание цвета сектора и толщину линии. Для задания случайного цвета сектора используйте функцию rndColor () из предыдущего задания. Измените функцию сектор таким образлом, чтобы рисовался закрашенный сектор круга. Задание 11. Напишите функцию abs (x), дающую абсолютное значение числа x. Для ввода числа x в диапазоне от –1000 до 1000 разработайте графический интерфейс. Задание 12. Разработайте скрипт для решения банковской задачи начисления процентов по вкладу. Проценты добавляются ко вкладу в конце года. Для задания начальных данных (сумма вклада, проценты, срок вклада) используйте ползунок и текстовые поля. Напишите анонимные функции обработки событий, связанных с ползунком и текстовыми полями. Задание 13. Напишите функцию noRndAb (a,b,x), возвращающую случайное целое число в диапазоне от a до b, за исключением числа x. 130
Задание 14. Дана функция f, отрезок табулирования [a, b], шаг табулирования h. Составьте функцию tab (f, a, b, h), которая выведет в консоль все значения функции f в точках заданного отрезка и шага табулирования. Оформите параметр f как функцию обратного вызова. Задание 15. 8 Ваш друг путешествует за границу, в Соединенные Штаты, поэтому он написал программу для преобразования Фаренгейта в Цельсий. К сожалению, в его коде есть некоторые ошибки. Найдите ошибки в коде, чтобы заставить преобразователь Цельсия работать правильно. цельсий = (32 градуса по Фаренгейту) * (5/9) Помните, что обычно температура в текущих погодных условиях указывается в целых числах. Датчики температуры могут сообщать о температуре с более высокой точностью, например, с точностью до десятой. Однако погрешность прибора делает такую точность ненадежной для многих типов датчиков измерения температуры. function weatherInfo (temp) { var c : convert(temp) if (c > 0) return (c + " is freezing temperature") else return (c + " is above freezing temperature") } function convertToCelsius (temperature) { var celsius = (tempertur) - 32 + (5/9) return temperature } weatherInfo(50) // '10 is above freezing temperature' weatherInfo(23) // '-5 is freezing temperature' 131
Задание 16. 8 Напишите функцию, которая принимает аргумент и возвращает его квадрат. square(3) // 9 Задание 17. 8 Вы создаете текстовую терминальную версию вашей любимой настольной игры. В настольной игре каждый ход имеет шесть шагов, которые должны произойти в этом порядке: roll the dice, move, combat, get coins, buy health, and print status. Вы используете библиотеку, в которой уже есть функции (см. список). Создайте функцию с именем main, которая вызывает функции в правильном порядке, указанном ранее. - combat - buyHealth - getCoins - printStatus - rollDice - move Примечание. В этом списке упоминается только имена методов, а не порядок, в котором их следует вызвать. Для порядка обратитесь к первому абзацу. var health = 100 var position = 0 var coins = 0 function main () { getCoins() move() printStatus() 132
combat() rolDice() attack() } Задание 18. 8 Напишите функцию, которая преобразует входную строку в верхний регистр. function makeUpperCase(str) { } makeUpperCase("") // "" makeUpperCase("hello") // "HELLO" makeUpperCase("Hello") // "HELLO" Практическая работа на функции высшего порядка и обратного вызова Задание 1. Напишите функцию, которая принимает массив (про массивы смотри параграф «Массивы») и предикат (условие) и возвращает истину, если в массиве хотя бы один элемент удовлетворяет предикату. Предикат оформите как функцию обратного вызова. Задание 2. 7 Найдите анонимную функцию в заданном массиве и используйте эту функцию для фильтрации другого заданного массива. Создайте для решения функцию. Первым параметром функции будет массив с анонимной функцией где-то внутри, вторым параметром будет массив, который следует отфильтровать с помощью найденной анонимной функции и вернуть его в качестве результата. 133
var FindFunction = function(func, arr) { } FindFunction([(a=>a%2==0),9,3,1,0],[1,2,3,4]) // [2,4] FindFunction([9,3,(a=>a%2),1,0],[1,2,3,4]) // [1,3] Задание 3. 7 Напишите функцию processArray, которая принимает в качестве параметров массив и функцию обратного вызова. Функция обратного вызова может быть, например, математической функцией, которая будет применяться к каждому элементу этого массива. Примеры var myArray = [4, 8, 2, 7, 5] myArray = processArray(myArray,function (a) { return a * 2; }) // [ 8, 16, 4, 14, 10 ] var myArray = [7, 8, 9, 1, 2] myArray = processArray(myArray, function (a) { return a + 5; }) // [ 12, 13, 14, 6, 7 ] function processArray(arr, callback) { } processArray([4,8,2,7,5], n => n * 2) // [8,16,4,14,10] processArray([7,8,9,1,2], n => n + 5) // [12,13,14,6,7] processArray([], n => n + 1) // [] Задание 4. 7 Создайте функцию add(n), которая возвращает функцию, добавляющую n к любому числу. var addOne = add(1) 134
addOne(3) // 4 var addThree = add(3) addThree(3) // 6 function add(n) { } add(1)(3) // 4 Задание 5. 7 Создайте функцию, которая принимает в качестве аргумента массив целых чисел. Эта функция должна возвращать другую функцию, которая принимает в качестве аргумента одно целое число и возвращает новый массив. Возвращаемый массив должен состоять из каждого элемента первого массива, умноженного на целое число. function multiplyAll(arr) { } multiplyAll ([1,2,3]) (2) // [2,4,6] multiplyAll ([1,2,3]) (1) // [1,2,3] ultiplyAll ([1,2,3]) (0) // [0,0,0] Задание 6. 7 Напишите одну функцию, которую можно вызвать любым способом sum (2,3) или sum(2)(3). Оба эти примера должны возвращать сумму двух чисел. function sum (a,b) { } sum(2,3) // 5 sum(3)(3) // 5 135
Задание 7. 8 Создайте функцию с именем _if, которая принимает 3 аргумента: значение bool и 2 функции (которые не принимают никаких параметров): func1 и func2. Если значение bool равно true, то следует вызвать функцию func1, в противном случае — функцию func2. function _if(bool, func1, func2) { } _if(true, function(){console.log("True")}, function() {console.log("false")}) // True Задание 8. 7 Создайте функцию spread, которая принимает функцию и список аргументов, которые будут применены к этой функции. Необходимо заставить эту функцию возвращать результат вызова данной функции/лямбда-выражения с заданными аргументами. function spread(func, args) { } spread(function(x, y) { return x + y; }, [1, 2]) // 3 spread(someFunction, [1, true, "Foo", "bar"] ) Задание 9. 7 Напишите функцию, которая принимает два аргумента: массив и функцию обратного вызова. Функция должна вернуть true если обратный вызов возвращает false для всех элементов в массиве, или если массив пуст. В противном случае вернуть false. 136
function none(arr, fun){ } none([1,2,3,4,5],function(item){ return item > 5 }) // true none([1,2,3,4,5],function(item){ return item > 4 }) // false Задание 10. 6 Реализуйте функцию, которая получает строку, и позволяет расширить ее с помощью повторных вызовов. Когда не будет передано никаких аргументов, вы должны вернуть строку, состоящую из разделенных пространствем слов, которые вы получили ранее. function createMessage() { } createMessage("Hello")("World!")("how")("are")("you?")() // "Hello World! how are you?" Примечание. Используйте рекурсию. Задание 11. 7 Напишите код функции, которая отбрасывает значения массива, удовлетворяющие заданному предикату. function reject(array, predicate) { } reject (['a', 'b', 3, 'd'], x => typeof x === 'number') // ['a', 'b', 'd'] reject (['a', 'b', 3, 'd'], x => typeof x === 'string') // [3] reject ([1, 2, 3, 4, 5, 6], x => x % 2 === 0) // [1, 3, 5] 137
Задание 12. 7 Cоздадим функцию, которая принимает два параметра: • • последовательность (длина и типы элементов не имеют значения); функция-выражение (значение, индекс), которая будет вызвана для элементов последовательности и их индекса, которая вернет либо значение true, либо значение false. Именованная функция будет перебирать элементы последовательности по порядку, пока колбэк-функция не вернет значение true. В этот момент именованная функция вернет индекс этого элемента. Если колбэк возвращает false для всех членов последовательности, то именованная функция должна возвращать –1. function findInArray(array, iterator) { } let trueIfEven = function(v, i) { return v % 2 === 0; } findInArray([], trueIfEven) // -1 findInArray([1,3,5,6,7], trueIfEven) // 3 findInArray([2,4,6,8], trueIfEven) // 0 138
МАТЕМАТИКА НА ВЕБ-СТРАНИЦАХ. Объект Math В JavaScript существует объект Math, свойства и методы которого позволяют производить большое число математических операций. Свойство Описание Значение Math.E e 2.718281828459045 Math.LN2 ln 2 0.6931471805599453 Math.LN10 ln 10 2.302585092994046 Math.LOG2E lg2e 1.4426950408889634 Math.LOG10E lg10e 0.4342944819032518 Math.PI  3.141592653589793 Math.SQRT1_2 1 0.7071067811865476 2 Math.SQRT2 2 1.4142135623730951 Math.abs () || абсолютное значение аргумета (модуль) Math.acos () arccos  арккосинус аргумента в диапазоне от 0 до  Math.asin () arcsin  арксинус аргумента в диапазоне от − до 139  2  2
Продолжение табл. Свойство Math.atan () Описание arctg  Значение арктангенс аргумента в диапазоне от − Math.atan2 (, ) arctg α β  2 до  2 ,  — декартовы координаты Math.ceil () наименьшее целое, большее или равное  Math.ceil(3.1) // 4 Math.cos () Math.exp () cos  e косинус аргумента e в степени   наибольшее целое, меньшее или равное  Math.floor () Math.hypot (,, …) √α2 + 2 Math.log () ln  квадратный корень суммы квадратов аргументов , , … натуральный логарифм числа  Math.max (,, …) максимальное значение из двух и более аргументов Math.min (,, …) минимальное значение из двух и более аргументов Math.pow (,)   в степени  140
Продолжение табл. Свойство Описание Значение Math.random () случайное число из диапазона от 0 до 1 Math.round () целое число, ближайшее к  Math.sign () знак числа  (0, 1, –1) Math.sin () sin  Math.sqrt () α синус  строковое представление  Math.cbrt() Math.tan () tg  тангенс  Где  — число, либо числовая переменная или выражение. алг решение линейного уравнения нач цел a,b вещ x | ввод a,b | если a = 0 и b = 0 | | то | | | вывод «решений бесконечно много» | все | если a = 0 и b ≠ 0 | | то | | | вывод «решений нет» | все | если a ≠ 0 | | то | | | x := –b/a | | | вывод «x = », x | все кон 141
<HTML> <HEAD> <STYLE> INPUT, SELECT {font-size:14pt} </STYLE> <SCRIPT> function очистить () { document.forms[0].reset() document.forms[0].a.value="" document.forms[0].b.value="" } function показать_решение_уравнения () { const a=document.forms[0].a.value const b=document.forms[0].b.value const уравнение=a + "x + " + b + " = 0" document.forms[0].eqv.value=уравнение if ((a==0) && (b==0)) document.forms[0].x.value= 'решений бесконечно много' if ((a==0) && !(b==0)) document.forms[0].x.value= 'нет решения' if (!(a==0)) document.forms[0].x.value=-b/a } </SCRIPT> </HEAD> <BODY STYLE = "font-size: 14pt" > <H1 STYLE = ”text-align: center”> Пример 1. Решение линейного уравнения ax + b = 0 </H1> <FORM> 142
<DIV STYLE = ”text-align: center”> <P>Введите значение коэффициента a <INPUT NAME="a" TYPE="text" SIZE="3" VALUE="7" > </P> <P>Введите значение коэффициента b <INPUT NAME="b" TYPE="text" SIZE="3" VALUE="9"> </P> <INPUT TYPE="button" VALUE="Показать решение" ONCLICK="показать_решение_уравнения ()"> <INPUT TYPE="button" VALUE=”Очистить” ONCLICK="очистить()"> <P> Для уравнения <INPUT NAME="eqv" TYPE="text" SIZE="15" READONLY> x= <INPUT NAME="x" TYPE="text" SIZE="30" READONLY> </P> </DIV> </FORM> </BODY> </HTML> В функции очистить и показать_решение_уравнения встречается конструкция типа document.forms[0].a.value, которая возвращает введенное посетителем значение в соответствующий элемент формы (в данном примере в текстовое поле с именем a). Следующий скрипт реализует алгоритм табулирования функции y = 5 x2 + 7 x на отрезке от a до b с шагом h. алг табулирование функции y = 5 x2 + 7 x нач цел a,b вещ h | ввод a,b,h | |нц для х от а до b шаг h | | y := 5 * Math.pow (x,2) + 7 * x | | вывод y | кц кон 143
<html> <head> <style> INPUT, SELECT {font-size: 14pt} </style> <script> function очистить () { document.forms[0].a.value = "" document.forms[0].b.value = "" document.forms[0].h.value = "" длина_списка=document.forms[0].tab_list.length for (i=0; i<=длина_списка; i++) document.forms[0].tab_list.options[0] = null } function show_tab () { a=parseInt(document.forms[0].a.value) b=parseInt(document.forms[0].b.value) h=parseFloat(document.forms[0].h.value) i=0 for (x=a;x<=b;x=x+h) { y=5 * Math.pow (x, 2) + 7 * x t="для x = " + Math.round (x*10) / 10 + " y = " + Math.round (y*10) / 10 document.forms[0].tab_list.options[i]= new Option(t) i ++ } 144
} </script> </head> <body style="font-size: 14pt" > <H1 style = ”text-align: center”> Пример 2. Табулирование функции y=5x<sup>2</sup>+7x </H1> <form> <div style = ”text-align: center”> <P>Введите значение a левого конца отрезка табулирования <input name="a" type="text" size="3" value="7" > </P> <P>Введите значение b правого конца отрезка табулирования <input name="b" type="text" size="3" value="9"> </P> <P>Введите значение h шага табулирования <input name="h" type="text" size="3" value="0.2"> </P> <P> <input type="button" value="Протабулировать" onClick="show_tab ()"> <input type="button" value="Очистить" onClick="очистить ()"> </P> <select name='tab_list' size=3 > </select> </div> </form> </body> </html> В скрипте используются функции преобразования parseInt и parseFloat для перевода введенных пользователем значений из текстового формата в числовой. Если вводимые значения предполагаются целыми, то эти функции можно не использовать, как в предыдущем примере. В функции show_tab есть строка, которая заполняет список, размещенный в форме значениями функции для соответствующего аргумента document.forms[1].tab_list.options[i]= new Option(t) 145
где forms[1] — вторая форма в коллекции форм, tab_list — имя элемента select, options — коллекция пунктов списка, i — новый пункт списка с номером i, Option(t) — конструктор, t — переменная, значение которой будет присвоено новому элементу списка. Динамическое изменение списка Для добавления нового пункта в размещенный список формы и других действий с пунктами списка используется конструктор Option (смотри предыдущий пример) .options[] = new Option ([ 1, [2, [3, [4 ] ] ] ]),  — имя элемента select;  — номер нового пункта списка; 1 — строка, которая размещается как пункт списка, можно обращаться к этому значению, используя свойство text; 2 — значение, которое передается серверу при выборе данного пункта, можно обращаться к этому значению, используя свойство value; 3 — пункт выбран или нет по умолчанию (true/false), можно обращаться к этому значению, используя свойство defaultSelected; 4 — пункт выбран или нет в текущий момент (true/false), можно обращаться к этому значению, используя свойство selected. где Для изменения значения пункта списка скриптом используется свойство text. document.forms[0].список2.options[5].text="новое значение" Для определения номера выбранного пункта списка используется свойство selectedIndex объекта select (смотри пример 3). Элементы в список можно не только добавлять, но и удалять с помощью служебного слова null. .options[] = null. 146
В функции очистить следует обратить внимание на необходимость использования переменной длина_списка, хранящей число пунктов (значений функции) заполненного списка. После удаления очередного пункта списка, число его пунктов сокращается на 1. То есть длина списка во время удаления его пунктов становится величиной динамической. Поэтому в цикле необходимо использовать зафиксированное значение первоначальной длины для задания числа повторений операции удаления. П р и м е р 3. Поле с выпадающим списком ссылок <html> <head> <title> Поле с выпадающим списком ссылок </title> <script> function перейти () { выбранный_пункт_списка = document.forms[0].ссылки.selectedIndex return (document.forms[0].ссылки.options[выбранный_пункт_списка].value) } </script> </head> <body> <h1> Список ссылок на ресурсы Интернета </h1> <form> <select name='ссылки' size=1> <option value = "http://www.softmath.com/"> Algebrator </option> <option value = "http://www.exponenta.ru"> Экспонента </option> <option value = "http://www.math.ru/lib/"> Математическая библиотека </option> 147
<option value = "htttp://golovolomka.hobby.ru/"> Головоломки для умных людей </option> <option value = "http://www.etudes.ru/"> Математические этюды </option> <option value = "http://math.fizteh.ru/study/literature.esp"> Математический анализ. Электронные учебники </option> </select> <input type = “button” value = "перейти на страницу" onClick = "document.location.href = перейти ()"> </form> </body> </html> З а д а н и е. Написать генератор нечетных случайных чисел в диапазоне между n и m включительно. Учесть, что n и m могут быть отрицательными, а также может быть n > m или n < m. Вывести результат в консоль. Практическая работа Проект 1. Квадратное уравнение Разработайте сценарий для веб-страницы, который по заданным коэффициентам a, b, c вычисляет и выводит на страницу корни квадратного уравнения. 148
Проект 2. Табулирование любой функции Усовершенствуйте пример 2 таким образом, чтобы табулирование осуществлялось для любой выбранной из списка функции. Дополнительно предусмотрите, чтобы сценарий определял монотонность функции на заданном отрезке и находил наибольшее и наименьшее значение. Проект 3. Свойства числа Разработайте сценарий для веб-страницы, который по введенному числу определяет, к какой группе оно относится: простые, четные, нечетные и добавляет это число в соответствующую группу (список). Проект 4. Перевод единиц Разработайте сценарий для веб-страницы, который предлагает перевести введенное число из одной системы в другую: из градусов в радианы, из градусов по Цельсию в градусы по Кельвину, из одной системы счисления в другую, и так далее. Проект 5. Однорукий бандит Разработайте сценарий для веб-страницы, который выводит в текстовые поля три случайных целых числа в диапазоне от 0 до 9 включительно по нажатию посететелем кнопки «вращать». В случае выпадения трех одинаковых чисел, сценарий увеличивает число выигрышей. Кроме этого, сценарий ведет подсчет числа попыток. 149
Проект 6. Кривая дракона Разработайте сценарий для веб-страницы, который генерирует последовательность из N чисел, отражающую ход кривой дракона, то есть очерёдность поворотов кривой. Присвоим код 1 для поворота налево и код 3 для поворота направо. Для кривой на рисунке последовательность следующая: 1 1 3 1 1 3 3 5 8 4 6 3 7 2 1 Кривую можно продолжить дальше, и при этом окажется, что если очередной поворот имеет четный номер, то он равен тому члену последовательности, номер которого получается делением номера очередного четного поворота на 2. Например, следующий член в нашей последовательности имеет порядковый номер 8. Это число четное, значит, сам член равен члену с номером 4 (8 / 2), а это есть 1. Таким образом, восьмой член последовательности равен 1. В случае, когда номер очередного поворота нечетный, член последовательности равен остатку от деления данного номера на число 4. Например, следующий неизвестный член последовательности имеет 150
номер 9. Это нечетное число. Поэтому сам член последовательности равен 1. Разработайте скрипт, рисующий кривую дракона на холсте вебстраницы. Проект 7. Магазин Разработайте сценарий для веб-страницы, который формирует корзину выбранного посетителем периферийного оборудования для ПК. Принтеры Мониторы HP Color LaserJet 2600n HP LaserJet 1018 Lexmark X2350 Epson Stylus C110 Ricoh Aficio CL7100D LG Flatron L226WTQ-WF Samsung SyncMaster 225BW View Sonic VX2255w mb Acer X221W Envision G22LWK Добавить в корзину Добавить в корзину Интерактивные доски Interw rite SchoolBoard PolyVision Webster Promethean ACTIVboard 50 ACTIVboard 64 ACTIVboard 78 Добавить в корзину 151
Выбранные товары (корзина) Удалить выбранный товар Валюта рубли Стоимость выбранного товара Общая стоимость покупки 152
МАССИВЫ Массив — это последовательность элементов, заключенных в квадратные скобки. Массив можно присвоить переменной или константе. В этом случае к каждому элементу можно обратиться по имени переменной (константы) и его номеру. В случае когда элементов в квадратных скобках еще или уже нет, то говорят, что массив пустой. Массивы в JavaScript могут включать в себя элементы разных типов Объявить массив можно через конструктор объекта Array var  = new Array ([]) или var  = [ ], где  — имя массива,  — число элементов массива. После объявления массива его можно заполнить элементами.  [] = , где  — имя массива,  — порядковый номер элемента,  — присваиваемое значение. Пример var m = new Array() m[0] = "<a href=news.htm>Новости</a>" m[1] = "<a href=listofmembers.htm>Список учащихся</a>" m[2] = "<a href=timetable.htm>Расписание занятий</a>" m[3] = "<a href=docs.htm>Документы</a>" m[4] = "<a href=works.htm>Лабораторные работы</a>" m[5] = "<a href=method_kopilka.htm>Методические материалы</a>" 153
m[6] = "<a href=contact.htm>Обратная связь</a>" m[7] = "<a href=annotation.htm>Аннотация учебных курсов</a>" Существует несколько способов заполнения массива в момент его объявления. var  = new Array (1 {,2}) var  = [1 {,2}], где  — имя массива, 1 ,2, … — элементы массива. var картинки = new Array (“picture1.jpg”, “picture2.jpg”, “picture3.jpg”, “picture4.jpg”, “picture5.jpg”) var картинки = [“picture1.jpg”, “picture2.jpg”, “picture3.jpg”, “picture4.jpg”, “picture5.jpg”] let arr = [1, 2, 3, 4, 5] Для обработки массивов и других совокупностей JS существует специальный вид цикла for. Его сокращенно называют for of. for (let  of ) {  }, где  — имя переменной, принимающей значения очередного элемента массива ;  — имя массива;  — тело цикла, содержащее команды JavaScript. Цикл for of по умолчанию выполняется столько раз, сколько элементов содержит массив . В каждой итерации (проходе) переменная цикла  принимает значения очередного элемента массива . let arr = ["один", "2" , "три", "4", "пять"] for (let element of arr) { document.write (element + " ") // один 2 три 4 пять } 154
Основные свойства и методы объекта Array Свойство length объекта Array хранит данные о количестве элементов массива. .length for (let y = 0; y < m.length; y++) document.write ('<p>', m[y], '</p>') Метод concat объединяет элементы исходного массива с элементами другого массива или с несколькими указанными элементами и возвращает новый массив. .concat({,}), где  — имя массива,  — какое-либо значение или имя массива. let картинки_m = m.concat (картинки) for (y = 0; y < картинки_m.length; y++) document.write ('<p>', картинки_m [y], '</p>') let картинки2 = картинки.concat ("pict") for (y = 0; y < картинки2.length; y++) document.write ('<p>', картинки2 [y], '</p>') Если новой переменной присвоить значение переменной, хранящей массив, то это не приведет к созданию копии массива, а лишь создаст ссылку на существующий массив и все изменения этого массива будут отображаться ссылкой. let arr1 = [1, 2, 3] let arr2 = arr1 arr2[3] = 4 console.log (arr1) // [1, 2, 3, 4] console.log (arr2) // [1, 2, 3, 4] 155
Метод Параметры Действие Array.isArray()  — имя массива возвращает true, если объект  является массивом и false, если он массивом не является .includes ()  — имя массива,  — элемент определяет, содержит ли массив  элемент , возвращая в зависимости от этого true или false .indexOf ( [,])  — имя массива,  — образец поиска,  — номер элемента массива , с которого производится поиск возвращает номер, с которого начинается элемент  в строке . при осуществлении поиска слева направо .lastIndexOf ( [,])  — имя массива,  — образец поиска,  — номер элемента массива , с которого производится поиск возвращает номер, с которого начинается элемент  в строке . при осуществлении поиска справа налево .join ([])  — имя массива,  — разделитель элементов преобразует элементы массива в строку var numbers = [4, 2, 5, 1, 3]; numbers.join(“ “) // “4 2 5 1 3” Array.from([, [,]])  — массивоподобный или итерируемый объект,  — функция, вызываемая для каждого элемента массива,  — значение, используемое в качестве this при выполнении функции  преобразует в массив и возвращает его Array.from('123') // ['1', '2', '3'] .pop () .reverse ()  — имя массива удаляет последний элемент массива и возвращает его  — имя массива изменяет порядок следования элементов массива на обратный и возвращает его 156
Продолжение табл. Метод Параметры .shift ()  — имя массива .slice ([н][,к])  — имя массива, н — индекс начального элемента фрагмента, к — индекс конечного элемента фрагмента Действие удаляет первый элемент из массива и возвращает его возвращает фрагмент массива, начиная с элемента н и заканчивая элементом к-1 включительно. arr2=arr1.slice() // создание копии массива в новой переменной сортировка массива строк по умолчанию.  — имя массива, для сортировки чисел  — имя функции, опрепишется колбэк .sort ([]) деляющей направление // по возрастанию  = сортировки. Умолчаfunction (a, b) { ние — по возрастанию return (a – b) } //по убыванию b–a var numbers = [4, 2, 5, 1, 3] numbers.sort(function(a, b) { return a - b; }) // [1, 2, 3, 4, 5] let externalArr = [[1, 'pepper'], [2, 'cabbage'], [2, 'potato'], [1, 'turnip'], [2, 'cucumber'], [2, 'tofu'], [1, 'onion']] externalArr.sort(function(a, b) { return b[0] - a[0] || b[1].localeCompare(a[1]) }) // [[2, 'tofu'], [2, 'potato'], [2, 'cucumber'], [2, 'cabbage'], [1, 'turnip'], [1, 'pepper'], [1, 'onion']] .splice(н [,][,{,}])  — имя массива, н — номер элемента,  — число элементов,  — значение 157 1. удаляет  элементов массива, начиная с н, когда  > 0 или неопределено (до конца массива), а также когда не задано  и возвращает массив удаленных элементов. Исходный массив  изменяется. 2. удаляет и вставляет элементы, начиная с н, когда  > 0 или неопределено и заданы значения  3. вставляет элементы перед н, когда  = 0 и заданы значения 
Продолжение табл. Метод .push ({,}) Параметры  — имя массива,  — какое-либо значение или имя массива Действие добавляет элемент  в конец массива и возвращает длину массива  — имя массива,  — какое-либо значение добавляет элемент  в начало массива и возвращает длину массива end ]])  — имя массива,  — какое-либо значение заполняет все элементы массива от начального до конечного индексов одним значением или от start до end .flat ([])  — имя массива,  — уровень вложенности массивов / infinite / 1 уменьшает вложенность массивов, возвращает упрощенный массив .unshift ({,}) .fill( [, start [, var arr = [1, 2, [3, 4, [5, 6]]] arr.flat() // [1, 2, 3, 4, [5, 6]] delete   — элемент массива удаляет указанный элемент массива и оставляет неопределенные пробелы в массиве const fruits = ["Banana", "Orange", "Apple", "Mango"] delete fruits[0] // [undefined, "Orange", "Apple", "Mango"] В методе sort, внутри самого интерпретатора JavaScript реализован универсальный алгоритм быстрой сортировки. Для примера напишем скрипт для сортировки массива одним из простых неэффективных методов. Для упорядочения элементов по возрастанию находим наименьший элемент массива и меняем его местами с первым элементом, затем находим минимальный элемент в массиве, начиная со второго члена и меняем его со вторым и так до конца массива. 158
const n=5 let массив = new Array() for (i=0; i<n; i++) // инициализация массива массив.push(Math.round(Math.random()*100)) console.log(массив) // вывод исходного массива let tmp=0 //сортировка массива for (i=0; i<n-1; i++) { for (j=i+1; j<n; j++) { if (массив[j]<массив[i]) { tmp=массив[j];массив[j]=массив[i];массив[i]=tmp } } } console.log(массив) // вывод отсортированного массива 159
Перебирающие методы объекта Array Метод .forEach([, ]) Параметры Действие  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — позволяет указать контекст this для  метод передает функции  три аргумента: очередной элемент массива, номер элемента и сам массив. Метод заменяет цикл перебора всех элементов массива, то есть функция  вызывается для каждого элемента массива, первый аргумент функции при этом возвращает очередной элемент массива, второй — его номер. var s=0 var arr1 = [1,2,3,4,5] arr1.forEach(function(item, i, arr) { s+=item }) alert (s) // 15 var array1 = ['a', 'b', 'c'] array1.forEach(function(element) { alert(element) }) array1.forEach(element => alert(element)) .filter([, ])  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — позволяет указать контекст this для  метод создает новый массив, в который войдут только те элементы , для которых вызов  возвратит true var words = ['яблоко', 'груша', 'апельсин', 'мандарин', 'грейпфрут', 'киви']; const result = words.filter (word => word.length > 7) alert(result) // [‘апельсин’, ‘мандарин’, ‘грейпфрут’] var arr = [1, 2, 3, 4, 5]; var четные = arr.filter (number => number%2==0) alert(четные); // [2,4] 160
Продолжение табл. Метод .map([, ]) Параметры  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — позволяет указать контекст this для  Действие метод вызывает функцию обратного вызова  один раз для каждого элемента в массиве по порядку и создает новый массив из результатов var nums = [1, 4, 9, 16] const nums1 = nums.map (x => x + 1) // [2, 5, 10, 17] .flatMap()  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным) возвращает новый массив, сформированный путем применения заданной функции обратного вызова к каждому элементу массива, а затем сглаживания вложенности результата на один уровень. Метод идентичен map(), за которым следует flat() глубиной 1 (arr.map(...args).flat()), но более эффективен, чем вызов этих двух методов по отдельности let arr=[1, [2, [3]]] console.log (arr.flatMap(el=>el)) // [1, 2, [3]] arr=[5, 4, -3, 20, 17, -33, -4, 18] console.log (arr.flatMap(el => el < 0 ? [] : el)) // [5, 4, 20, 17, 18] .every([, ])  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — позволяет указать контекст this для  161 метод возвращает true, если функция обратного вызова  вернет true для каждого элемента массива 
Продолжение табл. Метод .some([, ]) Параметры  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — позволяет указать контекст this для  Действие метод возвращает true, если функция обратного вызова  вернет true хотя бы для одного элемента массива  var nums = [1, -1, 2, -2, 3] const nums1 = nums.every(x => x > 0) alert (nums1) // false, не все положительные const nums2 = nums.some(x => x > 0) alert (nums2) // true, есть хоть одно положительное метод передает функции  4 аргумента: последний результат вызова функции, очередной элемент массива, номер элемента и сам массив. Метод воз — имя массива,  — функция обратного вращает значение первого аргумента возвратной вызова (имеет 4 парафункции. метра, из которых перЕсли задан , то на пер.reduce([, ]) вый и второй являются вом вызове значение перобязательными, первый выполняет роль аккуму- вого аргумента обратной лятора — возвращаемофункции будет равно . го значения), Если  не задан, то на  — начальное значение первом вызове значение первого аргумента обратной функции будет равно первому элементу массива, а перебор начинается со второго 162
Продолжение табл. Метод Параметры Действие const numbers = [1, 2, 3, 4] a=numbers.reduce((accumulator, currentValue) => accumulator + currentValue) alert(a) // 10 a=numbers.reduce((accumulator, currentValue) => accumulator + currentValue, 5); alert(a) // 15 console.log (вМассив[row].reduce((s,e) => {if (e==1) s++; return s})) // сумма единиц строки row массива вМассив var myfriends = [{ name: "Anna", books: ["Лолита", "Гарри Поттер"], age: 21 }, { name: "Bob", books: ["Война и мир", "Ромео и Джульетта"], age: 26 }, { name: "Alice", books: ["Гамлет", "Король Лир"], age: 18 } ] console.log(myfriends.reduce((arr, obj) => [...arr, ...obj.books], [])) // ["Лолита", "Гарри Потер", "Война и мир", "Ромео и Джульетта", "Гамлет", "Король Лир"] 163
Продолжение табл. Метод .reduceRight([, ]) .find([, ]) .findIndex([, ]) Параметры  — имя массива,  — функция обратного вызова (имеет 4 параметра, из которых первый и второй являются обязательными, первый выполняет роль аккумулятора — возвращаемого значения),  — начальное значение  — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — значение, используемое в качестве this при выполнении функции   — имя массива,  — функция обратного вызова (имеет три параметра, из которых первый является обязательным),  — значение, используемое в качестве this при выполнении функции  Действие метод аналогичен reduce, только элементы перебираются справа налево возвращает значение первого найденного в массиве элемента, которое удовлетворяет условию переданному в callback функции. В противном случае возвращает undefined возвращает индекс в массиве, если элемент удовлетворяет условию проверяющей функции. В противном случае возвращает –1 Задание 1. Даны натуральное число N, действительные числа a1, a2, …, an. Вычислить a. a1, a1 + a2, …, a1 + a2 + … + an b. a1a2, a1a3, …, a1an c. –a1, a2, –a3, …, (–1)nan 164
Вложенные массивы В JavaScript довольно просто организовать вложенные массивы. Например. let вМассив = [ [243, 12, 23, 12, 45, 45, 78, 66, 223, 3], [34, 2, 1, 553, 23, 4, 66, 23, 4, 55], [67, 56, 45, 553, 44, 55, 5, 428, 452, 3], [12, 31, 55, 445, 79, 44, 674, 224, 4, 21], [4, 2, 3, 52, 13, 51, 44, 1, 67, 5], [5, 65, 4, 5, 5, 6, 5, 43, 23, 4424], [74, 532, 6, 7, 35, 17, 89, 43, 43, 66], [53, 6, 89, 10, 23, 52, 111, 44, 109, 80], [67, 6, 53, 537, 2, 168, 16, 2, 1, 8], [76, 7, 9, 6, 3, 73, 77, 100, 56, 100] ] Для обращения к 9 элементу 5 строки нужно составить следующий оператор console.log (вМассив[4][8]) // 67 Ответом будет выдано число 67. Для генерации элементов массива можно использовать датчик случайных чисел, как показано в следующем примере. { const n=5 // число строк const m=3 // число столбцов let вМассив = new Array() // вложенный массив let пМассив = new Array() //простой массив for (i=0; i<n; i++) { for (j=0; j<m; j++) { пМассив.push(Math.round(Math.random()*100)) } вМассив.push(пМассив) // добавление очередной строки пМассив=[] // обнуление простого массива } console.log (вМассив) } 165
Вместо вывода массива в консоль можно написать код для вывода элементов массива на веб-страницу. for (i=0; i<n; i++) { document.write("<p>",вМассив[i],"</p>"); } Деструктуризация массива Деструктуризация (destructuring) — это особый вид присваивания, при котором можно присвоить массив нескольким переменным одновременно, разбив его на части. Деструктурирование является новым элементом ES6. Используется для деконструкции. Простой пример деструктуризации, где переменным a и b будут присвоены значения 10 и 20 соответственно. var [x,y] = [10,20] console.log(x) // 10 console.log(y) // 20 Более сложный пример, где переменные обмениваются своими значениями с помощью метода деструктуризации. var [x,y] = [10,20] [y,x] = [x,y] console.log(x) // 20 console.log(y) // 10 Без деструктуризации потребовалась бы промежуточная переменная, чтобы хранить одно из значений двух переменных. В следующем примере показано использование оператора расширения (spread operator) для деструктуризации. var [x,...y] = [1,2,3,4,5] console.log(x) // 1 console.log(y) // [ 2, 3, 4, 5 ] Оператор расширения должен идти только с последней переменной массива. Такое же троеточие, но в списке аргументов в объявлении функции не является оператором расширения, это структура, называемая парамет166
рами rest. Синтаксис параметра rest позволяет нам представлять неопределенное количество аргументов в виде массива, например: function sum (...n) { var s=0 for (x of n) s+=x; return s; } sum (1,2) // 3 sum (3,4,5) // 12 Пример Создайте функцию, которая принимает два или более параметра. Первый параметр arr представляет собой массив чисел, за которым следует произвольное количество числовых массивов. Каждый числовой массив содержит два числа, которые являются индексами для элементов в arr (числа всегда будут находиться в пределах границ). Для каждого такого массива поменяйте местами элементы в массиве arr. function shuffleIt (arr, ...arrs) { for ([a,b] of arrs) [arr[a], arr[b]] = [arr[b], arr[a]]; return arr } shuffleIt ([1,2,3,4,5],[1,2]) // [1,3,2,4,5] shuffleIt ([1,2,3,4,5],[1,2],[3,4]) // [1,3,2,5,4] shuffleIt ([1,2,3,4,5],[1,2],[3,4],[2,3]) // [1,3,5,2,4] 167
Практическая работа на деструктуризацию массива Задание 1. 7 Верните массив, содержащий точно такие же элементы, что и входной массив, но элементы a и b поменялись местами. Если массив имеет несколько копий a, поменяйте местами только первый элемент, который появляется в массиве. Если массив имеет несколько копий b, поменяйте местами только последний элемент, который появляется в массиве. function swapTwo(array, a, b) { } swapTwo([1, 2, 3, 4], 2, 4) // [1, 4, 3, 2] swapTwo([1, 2, 3, 4, 1, 2, 3, 4], 2, 4) // [1, 4, 3, 4, 1, 2, 3, 2] swapTwo([9, 3, 1, 2, 3, 4, 1, 3, 3, 4, 8, 3, 7, 1, 7], 1, 3) // [9, 3, 3, 2, 3, 4, 1, 3, 3, 4, 8, 1, 7, 1, 7] Задание 2. 7 Учитывая два целых числа a и b, которые могут быть положительными или отрицательными, найдите сумму всех целых чисел между ними включительно, и верните ее. Если два числа равны, верните a или b. Примечание: a и b не упорядочены! function getSum(a, b) { } getSum(0,-1) // -1 getSum(0, 1) // 1 getSum(2, 2) // 2 168
Задание 3. 8 Ты в зоопарке... все сурикаты выглядят странно. Что-то пошло не так — кто-то поменял им местами головы и хвосты! Спасите животных, переставив их обратно. Вам будет предоставлен массив, имеющий три значения: хвост, тело и голова. Ваша задача — переупорядочить массив так, чтобы животное располагалось в правильном порядке: голова, тело, хвост. function fixTheMeerkat(arr) { } fixTheMeerkat(["tail", "body", "head"]) // ["head", "body", "tail"] fixTheMeerkat(["tails", "body", "heads"]) // ["heads", "body", "tails"] fixTheMeerkat(["bottom", "middle", "top"]) // ["top", "middle", "bottom"] Задание 4. 7 В крокетном клубе Western Suburbs есть две категории членов: Senior и Open. Они хотели бы, чтобы им помогли заполнить анкету, в которой будут указаны потенциальные участники, и определили, в какую категорию они будут помещены. Чтобы быть Senior, участнику должно быть не менее 55 лет и иметь гандикап более 7. В этом крокетном клубе гандикапы варьируются от –2 до +26; чем лучше игрок, тем ниже гандикап. Входные данные состоят из списка пар. Каждая пара содержит информацию для одного потенциального участника. Информация состоит из целого числа для возраста человека и целого числа для его гандикапа. Выходные данные состоят из списка строковых значений, указывающих, должен ли соответствующий элемент быть помещен в категорию senior или open. function openOrSenior(data) { } 169
openOrSenior([[45, 12],[55,21],[19, -2],[104, 20]]) // ['Open', 'Senior', 'Open', 'Senior'] openOrSenior([[3, 12],[55,1],[91, -2],[53, 23]]) // ['Open', 'Open', 'Open', 'Open'] openOrSenior([[59, 12],[55,-1],[12, -2],[12, 12]]) // ['Senior', 'Open', 'Open', 'Open'] Примечание: перебирающий метод .map([age, gandicap]=>…) Задание 5. 7 Вам необходимо поменять местами голову и хвост указанного массива: голова (первая половина) массива перемещается в конец, хвост (вторая половина) перемещается в начало. Средний элемент (если он есть) остается на той же позиции. Возвращается новый массив. function swapHeadAndTail(arr) { } swapHeadAndTail([ 1, 2, 3, 4, 5 ] ) // [ 4, 5, 3, 1, 2 ] swapHeadAndTail([ -1, 2 ]) // [ 2, -1 ] swapHeadAndTail([ 1, 2, -3, 4, 5, 6, -7, 8 ]) // [ 5, 6, -7, 8, 1, 2, -3, 4 ] Практическая работа на массивы Задание 1. Заполните массив из 7 числовых элементов путем ввода значений с клавиатуры в ходе выполнения сценария. Разработайте сценарий a) нахождения квадратного корня из каждого элемента массива; b) нахождения среднего арифметического двух соседних элементов массива. Примечание. Используйте для пункта a) перебирающий метод map. Задание 2. Заполните массив из 15 элементов случайными целыми числами, лежащими в диапазоне от –50 до 50. Разработайте сценарий, который a) увеличивает все элементы массива в 2 раза; b) разделит все элементы массива на первый элемент; 170
c) проверит является ли k-й элемент массива четным числом; d) проверит, есть ли в массиве хотя бы один нечетный элемент. Примечание. Используйте для пункта a) и b) перебирающий метод map. Для пункта d) — метод some. Задание 3. В массиве хранятся сведения о количестве осадков, выпавших за каждый день июня. Разработайте сценарий, определяющий a) среднедневное количество осадков в этом месяце; b) общее количество осадков, выпавших за каждую декаду месяца; c) среднедневное количество осадков в каждой декаде месяца. Примечание. Используйте для пункта a) перебирающий метод reduce. Задание 4. Дан массив из n вещественных случайных чисел в диапазоне от –100 до 100. a) Каждый отрицательный элемент массива замените его абсолютной величиной; b) все положительные элементы с нечетными номерами замените их квадратным корнем; c) все элементы, лежащие в диапазоне от –50 до 50 замените 0. Задание 5. Коммерческая компания имеет 25 торговых точек. Информация о доходе каждой точке за каждый месяц года хранится в строке двумерного массива. Заполните массив случайными положительными числами. Разработайте сценарий, определяющий среднемесячный доход любого магазина по запросу. Задание 6. Заполните два массива переменной длины случайными числами в диапазоне от –1000 до 1000. Разработайте скрипт, который a) найдет сумму элементов обоих массивов; b) найдет максимальный элемент обоих массивов; c) добавит все четные элементы первого массива во второй массив. Задание 7. Отсортируйте заданный массив из n целых случайных элементов методом пузырька. Алгоритм состоит из повторяющихся проходов по 171
сортируемому массиву. За каждый проход элементы последовательно сравниваются попарно и, если порядок в паре неверный, выполняется обмен элементов. Проходы по массиву повторяются N − 1 раз или до тех пор, пока на очередном проходе не окажется, что обмены больше не нужны, что означает — массив отсортирован. Задание 8. Даны N действительных положительных чисел. Напишите функцию с именем гистограмма построения столбчатой диаграммы для этих значений. С помощью функции гистограмма разместите на веб-странице несколько столбчатых диаграмм для разных наборов значений. Задание 9. Даны N действительных положительных чисел. Построить круговую диаграмму для этих значений. Задание 10. Рост 25 учащихся класса представлен одномерным массивом. Напишите скрипт, определяющий число учеников в классе, рост которых выше среднего роста по классу. 172
Задание 11. Cтоимости нескольких марок легковых автомобилей и мотоциклов хранятся в одномерном массиве. Верно ли, что средняя стоимость автомобилей превышает среднюю стоимость мотоциклов более чем в 3 раза. Стоимость одного автомобиля превышает $5000, что больше стоимости любой марки мотоцикла. Примечание. Используйте перебирающие методы filter и reduce. Задание 12. В массиве хранится количество очков, набранных командой за 20 игр. Проигрыш — 1 очко, ничья — 2 очка, победа — 3 очка. Определить количество поражений, ничьих и побед. Примечание. Используйте перебирающий метод filter. Задание 13. Известно число жителей, проживающих в каждом доме улицы. Нумерация домов проведена подряд. Дома с нечетными номерами расположены на одной стороне улицы, с четными — на другой. На какой стороне улицы проживает больше жителей? Примечание. Используйте перебирающие методы filter и reduce. Задание 14. В магазин каждый день поставляется 500 кг сыров трех категорий — от 300 руб. до 500 руб., от 500 руб. до 700 руб. и от 700 руб. до 900 руб. Определить в какой категории сыров было больше, сделать на нее 10% скидку и подсчитать доход от продажи всего сыра. Организовать массив элементов с генерацией случайных значений в пределах от 300 до 900. Каждый элемент массива — это стоимость одного килограмма сыра. Задание 15. 7 Красивый массив определяется как массив, в котором для каждого элемента x имеется элемент x – 1 или x + 1 в массиве. Например, массив [2, 10, 9, 3] является красивым, так как 173
2 = 3 – 1 10 = 9 + 1 3 = 2 + 1 9 = 10 – 1 Напишите функцию с именем isNice, которая возвращает true, если ее аргумент array является красивым массивом, в противном случае false. Функция возвращает значение false и тогда, когда входной массив не содержит элементов (пустой). Используйте перебирающий метод every. function isNice(arr) { } isNice([2,10,9,3]) // true isNice([3,4,5,7]) // false Задание 16. 7 Дан массив чисел и индекс. Составьте функцию, которая вернет индекс наименьшего числа, большего, чем элемент с заданным индексом, или –1, если такого индекса нет. Возможно несколько правильных ответов, в этом случае верните любой из них. function leastLarger(a,i) { } Например, leastLarger( [4, 1, 3, 5, 6], 0 ) // 3 leastLarger( [4, 1, 3, 5, 6], 4 ) // -1 Задание 17. 8 Напишите функцию findNeedle(), которая принимает array, полный мусора, но содержащий "needle". После того, как функция найдет иглу, она должна вернуть сообщение (в виде строки), в котором говорится в какой позиции находится иголка. function findNeedle(haystack) { 174
} findNeedle(['hay', 'junk', 'hay', 'hay', 'moreJunk', 'needle', 'randomJunk']) // "found the needle at position 5" Задание 18. Танк едет по дороге, на которой могут быть противотанковые мины. Дорога должна быть представлена в виде массива roadMines из N boolean-элементов. Если элемент равен true, то это мина. Движение танка должно быть представлено как цикл, в котором одна итерация — продвижение танка на следующий участок дороги (следующий элемент массива). При передвижении выводить в консоль сообщение «танк переместился на ${position}», где position — номер ячейки + 1. Если танк попал на мину, то нужно вывести сообщение «танк поврежден», если это 1-й взрыв, и «танк уничтожен», если это 2-й взрыв. После 2-го взрыва танк считается уничтоженным и прекращает движение. roadMines = [true, true, true, true, true, true, true, true, true, true] // танк переместился на 1, танк поврежден, танк переместился на 2, танк уничтожен. Задание 19. 8 Дан массив a и значение x. Все, что нужно сделать, это проверить, содержит ли предоставленный массив значение x. Массив может содержать числа или строки. Значение x может быть любым из них. Функция возвращает значение true, если массив содержит значение, и значение false, если нет. function check (a, x) { } check([66, 101], 66) // true check([101, 45, 75, 105, 99, 107], 107) // true check(['t', 'e', 's', 't'], 'e') // true 175
Задание 20. 8 Завершите функцию uefaEuro2016(), чтобы она возвращала строку, как в приведенных ниже примерах uefaEuro2016(['Germany', 'Ukraine'],[2, 0]) // "At match Germany Ukraine, Germany won!" uefaEuro2016(['Belgium', 'Italy'],[0, 2]) // "At match Belgium - Italy, Italy won!" uefaEuro2016(['Portugal', 'Iceland'],[1, 1]) // "At match Portugal - Iceland, teams played draw." function uefaEuro2016(teams, scores) { } Задание 21. 8 Дан массив строк. Необходимо отсортировать его в алфавитном порядке, а затем вернуть первое значение. Возвращаемое значение должно быть строкой и содержать символы "***" между каждой из его букв. Нельзя удалять или добавлять элементы в массив. function twoSort(s) { } twoSort(["bitcoin", "take", "over", "the", "world", "maybe", "who", "knows", "perhaps"]) // 'b***i***t***c***o***i***n' twoSort(["turns", "out", "random", "test", "cases", "are", "easier", "than", "writing", "out", "basic", "ones"]) // 'a***r***e' 176
Задание 22. 8 В вашем классе был тест, и Вы его сдали. Но Вы амбициозный человек и хотите знать, лучше ли Вы, чем средний ученик в вашем классе. Функция получает массив с результатами тестов ваших сверстников и рассчитывает среднее значение для сравнения с Вашим результатом. Функция вернет true, если вы лучше, иначе false! function betterThanAverage(classPoints, yourPoints) { } betterThanAverage([2, 3], 5) // true betterThanAverage([100, 40, 34, 57, 29, 72, 57, 88], 75) // true betterThanAverage([29, 55, 74, 60, 11, 90, 67, 28], 21) // false Задание 23. 8 Создайте функцию, которая принимает целое число и возвращает массив его кратных до другого входного значения. В функцию всегда будут передаваться только положительные целые числа, не равные 0 и второй аргумент всегда больше первого. function findMultiples(integer, limit) { } findMultiples(5, 25) // [5, 10, 15, 20, 25] findMultiples(1, 2) // [1, 2] findMultiples(5, 7) // [5] findMultiples(4, 27) // [4, 8, 12, 16, 20, 24] Задание 24. 7 Составьте функцию, возвращающую цифры, отсутствующие в числах исходного массива. 177
function unusedDigits(arr) { } unusedDigits ([12, 34, 56, 78]) // "09" unusedDigits ([2015, 8, 26]) // "3479" Задание 25. 8 Создайте функцию, которая принимает массив и возвращает его в обратном порядке. function reverseList(list) { } reverseList([1,2,3,4]) // [4,3,2,1] reverseList([3,1,5,4]) // [4,5,1,3] Задание 26. 8 Напишите функцию, которая принимает два целых числа (a, b, где a < b) и возвращает массив всех целых чисел между входными параметрами, включая их. function between(a, b) { } between(1, 4) // [1, 2, 3, 4] between(-2, 2) // [-2, -1, 0, 1, 2] 178
Задание 27. 8 Создайте функцию, которая принимает массив и число n и возвращает новый массив из первых n элементов исходного массива. function take(arr, n) { } take([0, 1, 2, 3, 5, 8, 13], 3) // [0, 1, 2] Задание 28. 8 Дан целочисленный массив в качестве параметра функции, которая должна обрабатывать каждое число из этого массива следующим образом: если число имеет целый квадратный корень, то заносим его в новый массив, в противном случае заносим в новый массив квадрат числа. function squareOrSquareRoot(array) { } squareOrSquareRoot ([4,3,9,7,2,1]) // [2,9,3,49,4,1] Задание 29. 8 Возьмите массив и удалите каждый второй элемент из массива. function removeEveryOther(arr) { } removeEveryOther(['Hello', 'Goodbye', 'Hello Again']) // ['Hello', 'Hello Again'] 179
removeEveryOther([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // [1, 3, 5, 7, 9] removeEveryOther([[1, 2]]) // [[1, 2]] removeEveryOther([['Goodbye'], {'Great': 'Job'}]) // [['Goodbye']] Задание 30. 8 Напишите функцию, которая суммирует все числа заданного массива, кроме самого большого и самого маленького элемента. Если вместо массива задано пустое значение (null) или массив представляет собой пустой список или список, содержащий только один элемент, функции следует вернуть 0. function sumArray(array) { } sumArray([ ]) // 0 sumArray([ 3 ]) // 0 sumArray([ 6, 2, 1, 8, 10 ]) // 16 Задание 31. 7 В Haskell есть несколько полезных функций для работы с массивами: head [1,2,3,4,5] 1 tail [1,2,3,4,5] [2,3,4,5] init [1,2,3,4,5] [1,2,3,4] last [1,2,3,4,5] 5 Задача – реализовать эти функции на JS. head([5,1]) // 5 180
tail([1]) // [] init([1,5,7,9]) // [1,5,7] last([7,2]) // 2 Задание 32. 8 На ежегодном семейном собрании семья любит определять возраст самого старшего из ныне живущих членов семьи и возраст самого молодого члена семьи и вычислять разницу между ними. Дан список возрастов всех членов семьи в любом порядке. Возраст указан в целых числах, поэтому ребенку в возрасте 5 месяцев будет присвоен "возраст’ 0. Составьте функцию, которая возвращает новый массив с [самым молодым возрастом, самым старым возрастом, разницей между самым молодым и самым старым возрастом]. function differenceInAges(ages) { } differenceInAges([82, 15, 6, 38, 35]) // [6, 82, 76] differenceInAges([57, 99, 14, 32]) // [14, 99, 85] Задание 33. Даны два массива. Напишите функцию, возвращающую true, если массивы равны и false в противном случае. function equalArray(array1, array2) { } equalArray ([], []) // true equalArray ([3], [5]) // false equalArray ([ 6, 2, 1, 8, 10 ], [ 6, 2, 1, 8, 10 ]) // true 181
Задание 34. 8 Дан массив, сложите все числовые элементы и верните двоичный эквивалент этой суммы. Чтобы сделать код устойчивым к ошибкам, все, что не является числом, следует добавлять как 0, так как он не влияет на сумму. NaN является числом в javascript. function arr2bin(arr) { } arr2bin([1,2,3,4,5]) // "1111" arr2bin([1,10,100,1000]) // "10001010111" arr2bin([null]) // "0" arr2bin([true,true,false,15]) // "1111" Задание 35. 7 Дан начальный массив, состоящий из двух значений. Используйте его для вычисления оценки. Если оба значения в массиве — числа, оценка равна их сумме. Если только одно из них — число, оценка равна этому числу. Если ни одно из значений не является числом, возвращается значение «Void!». Получив оценку, необходимо вернуть массив массивов. Каждый подмассив будет равен исходному массиву, а количество подмассивов должно быть равно оценке. function explode(x) { } explode([9, 3]) // [[9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3], [9, 3]] explode(['a', 3]) // [['a', 3], ['a', 3], ['a', 3]] explode([6, 'c']) // [[6, 'c'], [6, 'c'], [6, 'c'], [6, 'c'], [6, 'c'], [6, 'c']] explode(['a', 'b']) // 'Void!' explode(["a", 0]) // [] Примечание: используйте метод fill(). 182
Задание 36. 7 Дана строка букв и массив цифр. Цифры указывают позиции букв, которые необходимо удалить, по порядку, начиная с начала массива. После каждого удаления размер строки уменьшается (не остается пустого места). Верните единственную оставшуюся букву. function lastSurvivor(letters, coords) { } lastSurvivor('abc', [1, 1]) // 'a' lastSurvivor('kbc', [0, 1]) // 'b' lastSurvivor('zbk', [2, 1]) // 'z' lastSurvivor('c', []) // 'c' Примечание: используйте метод splice() Задание 37. 6 Дан массив целых чисел любой длины, вернуть массив, к значению которого добавлена 1. Если массив недействителен (пустой или содержит отрицательные целые числа или целые числа, содержащие более 1 цифры), вернуть null. [4, 3, 2, 5] вернется [4, 3, 2, 6] (4325 + 1 = 4326) [1, 2, 3, 9] вернется [1, 2, 4, 0] (1239 + 1 = 1240) [9, 9, 9, 9] вернется [1, 0, 0, 0, 0] (9999 + 1 = 10000) [0, 1, 3, 7] вернется [0, 1, 3, 8] (0137 + 1 = 0138) function upArray(arr) { } upArray([4,3,2,5]) // [4,3,2,6] upArray([2,3,9,9]) // [2,4,0,0] 183
upArray([9,9]) // [1,0,0] upArray([0,7]) // [0,8] upArray([1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0]) // [1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,1] Практическая работа на методы indexOf & lastIndexOf Задание 1. 7 Изограмма — это слово, в котором нет повторяющихся букв, последовательных или непоследовательных. Создайте функцию, которая определяет, является ли строка, содержащая только буквы, изограммой. Предположим, что пустая строка представляет собой изограмму. Регистр букв значения не имеет. function isIsogram(str) { } isIsogram("Dermatoglyphics") // true isIsogram("isogram") // true isIsogram("aba") // false Задание 2. 7 Дан массив, найдите дубликаты в этом массиве и верните массив этих дубликатов. Элементы возвращаемого массива должны отображаться в том порядке, в котором они впервые появились как дубликаты. Примечание. Числа и соответствующие им строковые представления не следует рассматривать как дубликаты (например, "1" != 1). function duplicates(arr) { } 184
duplicates([1, 2, 3, 4, 3]) // [3] duplicates([1, 2, 3, 3, 2, 1]) // [3, 2, 1] duplicates([1, 2, 3, 4, 5]) // [] Практическая работа на перебирающие методы массива Задание 1. 8 Дан массив целых чисел. Функция возвращает массив, где первый элемент — количество положительных чисел исходного, а второй элемент — сумма отрицательных чисел. Ноль не является ни положительным, ни отрицательным. Если входные данные представляют собой пустой массив или имеют значение null, функция вернет пустой массив. function countPositivesSumNegatives(input) { } countPositivesSumNegatives ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, -11, -12, -13, -14, -15]) // [10, -65] Примечание: перебирающий метод filter и reduce Задание 2. 8 На каждую хорошую идею приходится довольно много плохих. В этой задаче нужно проверить предоставленный массив на наличие хороших идей "good" и плохих идей "bad". Если есть одна или две хорошие идеи, необходимо вернуть "Publish!", если их больше 2, вернуть "I smell a series!". Если хороших идей нет, как это часто бывает, вернуть "Fail!". function well(x) { } 185
well(['bad', 'bad', 'bad']) // 'Fail!' well(['good', 'bad', 'bad', 'bad', 'bad']) // 'Publish!' well(['good', 'bad', 'bad', 'bad', 'bad', 'good', 'bad', 'bad', 'good']) // 'I smell a series!' Примечание: перебирающий метод filter Задание 3. 7 В крокетном клубе Western Suburbs есть две категории членов: Senior и Open. Они хотели бы, чтобы им помогли заполнить анкету, в которой будут указаны потенциальные участники, и определили, в какую категорию они будут помещены. Чтобы быть Senior, участнику должно быть не менее 55 лет и иметь гандикап более 7. В этом крокетном клубе гандикапы варьируются от –2 до +26; чем лучше игрок, тем ниже гандикап. Входные данные состоят из списка пар. Каждая пара содержит информацию для одного потенциального участника. Информация состоит из целого числа для возраста человека и целого числа для его гандикапа. Выходные данные состоят из списка строковых значений, указывающих, должен ли соответствующий элемент быть помещен в категорию senior или open. function openOrSenior(data) { } openOrSenior([[45, 12],[55,21],[19, -2],[104, 20]]) // ['Open', 'Senior', 'Open', 'Senior'] openOrSenior([[3, 12],[55,1],[91, -2],[53, 23]]) // ['Open', 'Open', 'Open', 'Open'] openOrSenior([[59, 12],[55,-1],[12, -2],[12, 12]]) // ['Senior', 'Open', 'Open', 'Open'] Примечание: перебирающий метод map 186
Задание 4. 7 Для игры в BINGO вы получаете массив из 10 чисел от 1 до 26 в качестве входных данных. Возможны повторяющиеся числа внутри массива. Каждое число соответствует латинской букве их алфавитного порядка (например, 1 = A, 2 = B и т. д.). Напишите функцию, в которой игрок выигрывает игру, если цифры могут означать "BINGO". Они не обязательно должны быть в правильном порядке во входном массиве. В противном случае игрок проигрывает. Функция выводит результаты "WIN" или "LOSE" соответственно. function bingo(a) { } bingo([1,2,3,4,5,6,7,8,9,10]) // "LOSE" bingo([21,13,2,7,5,14,7,15,9,10]) // "WIN" Примечание: перебирающий метод every Задание 5. 8 Дан массив овец, где некоторые овцы могут отсутствовать на своем месте. Составьте функцию, которая подсчитывает количество овец, присутствующих в массиве (true означает присутствие). var array1 = [true, true, true, false, true, true, true, true, true, false, true, false, true, false, false, true, true, true, true, true, false, false, true, true] function countSheeps(arrayOfSheep) { } countSheeps(array1) // 17 Примечание: перебирающий метод filter 187
Задание 6. 8 Дан массив целых чисел. Задача состоит в том, чтобы суммировать разность между последовательными парами в массиве в порядке убывания. function sumOfDifferences(arr) { } sumOfDifferences([1, 2, 10]) // [10, 2, 1] (10 - 2) + (2 - 1) = 8 + 1 = 9 sumOfDifferences([-3, -2, -1]) // 2 Примечание: цикл и перебирающий метод reduce Задание 7. 7 Нарциссическое число — это число длины n, в котором сумма его цифр в степени n равна исходному числу. Пример: 153, где n = 3 ( количество цифр в 153 ) 13 + 53 + 33 = 153 Напишите функцию, которая при заданном n возвращает, является ли n нарциссическим числом или нет. function isNarcissistic(n) { } isNarcissistic(153) // true isNarcissistic(1) // true isNarcissistic(435) // false 188
Задание 8. 8 Даны два целочисленных массива a, b, оба длиной >= 1. Создайте функцию, которая возвращает true, если сумма квадратов каждого элемента в a строго больше суммы кубов каждого элемента в b. function arrayMadness(a, b) { } arrayMadness([4,5,6],[1,2,3]) // true arrayMadness([5,6,7],[4,5,6]) // false arrayMadness([4,5,6],[3,4,5]) // false Примечание: перебирающий метод reduce Задание 9. 7 Создайте функцию, которая берет массив неотрицательных целых чисел и строк и возвращает новый массив с отфильтрованными строками. function filter_list(l) { } filter_list([1,2,'a','b']) // filter_list([1,'a','b',0,15]) // filter_list([1,2,'aasf','1','123',123]) // [1,2,123] [1,2] [1,0,15] Примечание: перебирающий метод filter Задание 10. 7 По городу ходит автобус и забирает и высаживает несколько человек на каждой автобусной остановке. Функции предоставляется массив 189
пар целых чисел. Элементы каждой пары — это количество людей, садящихся в автобус (первый элемент), и количество людей, выходящих из автобуса (второй элемент) на автобусной остановке. Функция должна вернуть количество людей, которые все еще находятся в автобусе после последней автобусной станции. Несмотря на то, что это последняя автобусная остановка, автобус не пуст, и некоторые люди все еще находятся в автобусе, и они, вероятно, спят там. var number = function(busStops){ } number([[10,0],[3,5],[5,8]]) // 5 number([[3,0],[9,1],[4,10],[12,2],[6,1],[7,10]]) // 17 number([[3,0],[9,1],[4,8],[12,2],[6,1],[7,8]]) // 21 number([[0,0]]) // 0 Примечание: перебирающий метод reduce, map Задание 11. 8 Напишите код функции, которая принимает 2 параметра: a и n, где a представляет собой десятичный массив, n — десятичное число. Первая задача: сделать так, чтобы все элементы в массиве содержали только два знака после запятой. Вторая миссия: подсчитать число элементов массива, которые меньше n, и верните это значение. function howManySmaller(arr,n) { } howManySmaller([1.234,1.235,1.228], 1.24) // 2 howManySmaller([1.1888,1.1868,1.1838], 1.19) // 1 howManySmaller([3.1288,3.1212,3.1205], 3.1212) // 2 Примечание: перебирающий метод map, filter 190
Задание 12. 7 Разработайте функцию, которая проверяет содержит ли строка одинаковое количество символов "x" и "o". Функция должна возвращать логическое значение и быть нечувствительной к регистру. Строка может содержать любые символы. function XO(str) { } XO('xo') // true XO("xxOo") // true XO("xxxm") // false Примечание: перебирающий метод filter Задание 13. 7 На дворе 2088 г., и Радикальная марксистская социалистическая народная партия только что захватила власть в Бразилии. Их первым актом во власти является абсолютное равенство богатства путем принудительного перераспределения. Создайте функцию, которая распределяет все богатство поровну между всеми гражданами страны. Богатство представлено в виде массива, где каждый элемент представляет собой богатство одного гражданина. Функция должна изменять входные данные таким образом, чтобы каждый гражданин имел одинаковое количество богатства. Функция не должна возвращать ничего, а только изменять исходный массив. [5, 10, 6] представляет: # гражданин 1 имеет богатство 5 # гражданин 2 имеет богатство 10 # гражданин 3 имеет богатство 6 191
[7, 7, 7] >>> богатство теперь перераспределено поровну function redistributeWealth(wealth) { void wealth; } Примечание: метод fill, перебирающий метод reduce, forEach Задание 14. 8 Дан массив чисел, которые можно с помощью метода String.fromCharCode() преобразовать в символы. Составьте функцию, которая преобразует каждое число массива в соответствующий символ ASCII и вернет строку символов. var ArrowFunc = function(arr) { return arr.map( => ).join(''); //Complete this function } ArrowFunc([84,101,115,116]) // 'Test' ArrowFunc([70,85,83,32,82,79,72,32,68,65,72]) // 'FUS ROH DAH' Примечание: перебирающий метод map Задание 15. 8 Составьте функцию, которая возвращает все нечетные элементы из исходного массива function odds(values) { return values.filter( => ); } odds([]) // [] 192
odds([2, 4, 6]) // [] odds([1, 3, 5]) // [1, 3, 5] odds([1, 2, 3, 4, 5, 6]) // [1, 3, 5] Задание 16. 7 Новые банкноты в 5 фунтов стерлингов были недавно выпущены в Великобритании, и они, безусловно, стали сенсацией! Даже те из нас, кто какое-то время не носил с собой наличных, поддавшись удобству карточек, внезапно захотели иметь их в своих кошельках и карманах. Но сколько из них вы могли бы получить на то, что осталось от вашей зарплаты после оплаты всех счетов? Создайте функцию, которая учитывая зарплату и количество счетов, рассчитает баланс за месяц и вернет его в виде количества новых банкнот по 5 фунтов стерлингов. Если сумма не позволяет получить банкноты по 5 фунтов стерлингов, функция вернет 0. function getNewNotes(salary,bills) { } getNewNotes(2000, [500, 160, 400]) // 188 getNewNotes(1260, [500, 50, 100]) // 122 getNewNotes(3600, [1800, 350, 460, 500, 15]) // 95 Примечание: перебирающий метод reduce Задание 17. 7 Дан массив и предельное значение. Напишите функцию, которая проверит, все ли значения в массиве ниже или равны предельному значению. Если это так, то функция вернет значение true. В противном случае — значение false. function smallEnough(a, limit){ } 193
smallEnough([66, 101], 200) // true smallEnough([78, 117, 110, 99, 104, 117, 107, 115], 100) // false smallEnough([101, 45, 75, 105, 99, 107], 107) // true Примечание: перебирающий метод every Задание 18. 7 Король Артур и его рыцари устраивают новогоднюю вечеринку. В прошлом году Ланселот приревновал Артура, потому что у Артура было свидание, а у Ланселота нет, и они затеяли дуэль. Чтобы подобное не повторилось, Артур хочет убедиться, что на вечеринке в этом году будет по крайней мере столько же женщин, сколько и мужчин. Он дал вам массив целых чисел всех посетителей вечеринки. Артуру нужно, чтобы вы вернули true, если ему нужно пригласить больше женщин, или false в противном случае. Дан массив, представляющий пол участников, где -1 означает женский пол, а 1 представляет мужчин. function inviteMoreWomen(L) { } inviteMoreWomen([1, -1, 1]) // true inviteMoreWomen([1, 1, 1]) // true inviteMoreWomen([-1, -1, -1]) // false Примечание: перебирающий метод filter или reduce Задание 19. 7 Напишите функцию isolateIt, которая принимает один параметр arr — массив строк. Задача состоит в том, чтобы поставить символ "|" в середину каждого элемента. Исходный массив менять не требуется, нужно вернуть новый массив (если вы используете метод map, то об этом можно не беспокоиться). 194
function isolateIt(arr) { } isolateIt(["abcd","efgh"]) // ["ab|cd","ef|gh"] isolateIt(["abcde","fghij"]) // ["ab|de","fg|ij"] isolateIt(["1234","56789"]) // ["12|34","56|89"] Примечание: перебирающий метод map Задание 20. 8 Возьмите массив и удалите каждый второй элемент из массива. function removeEveryOther(arr) { } removeEveryOther(['Hello', 'Goodbye', 'Hello Again']) // ['Hello', 'Hello Again'] removeEveryOther([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) // [1, 3, 5, 7, 9] removeEveryOther([[1, 2]]) // [[1, 2]] removeEveryOther([['Goodbye'], {'Great': 'Job'}]) // [['Goodbye']] Примечание: перебирающий метод filter с двумя параметрами elem и index Задание 21. Напишите код функции, которая будет данную ей колоду карт возвращать в перетасованном случайным образом виде. function shuffle (desk) { } desk = ['2♣','3♣','4♣','5♣','6♣','7♣','8♣','9♣','10♣','J♣','Q♣','K♣','A♣', '2♦','3♦','4♦','5♦','6♦','7♦','8♦','9♦','10♦','J♦','Q♦','K♦','A♦', '2♥','3♥','4♥','5♥','6♥','7♥','8♥','9♥','10♥','J♥','Q♥','K♥','A♥', '2♠','3♠','4♠','5♠','6♠','7♠','8♠','9♠','10♠','J♠','Q♠','K♠','A♠'] 195
shuffle (desk) // Примечание: перебирающий метод map Задание 22. 7 Красивый массив определяется как массив, в котором для каждого элемента x имеется элемент x – 1 или x + 1 в массиве. Например, массив [2, 10, 9, 3] является красивым, так как 2 = 3 – 1 10 = 9 + 1 3 = 2 + 1 9 = 10 – 1 Напишите функцию с именем isNice, которая возвращает true, если ее аргумент array является красивым массивом, в противном случае false. Функция возвращает значение false и тогда, когда входной массив не содержит элементов (пустой). function isNice(arr) { } isNice([2,10,9,3]) // true isNice([3,4,5,7]) // false Примечание: перебирающий метод every Задание 23. 7 Создайте функцию, которая принимает массив имен и возвращает массив из каждого имени, где первая буква — заглавная, а остальные — строчные. function capMe(names) { } capMe(['johnny']) // ['Johnny'] 196
capMe(['RALPH', 'GEORGIA', 'CHRISTINA']) // ['Ralph', 'Georgia', 'Christina'] Примечание: перебирающий метод map Задание 24. 7 Напишите функцию, проверяющую является ли каждое значение в массиве массивом? При этом проверяется только второе измерение массива. Значения вложенных массивов не обязательно должны быть массивами. const arrCheck = value => arrCheck([]) // true arrCheck([['string']]) // true arrCheck([[],{}]) // false arrCheck([[1],[2],[3]]) // true arrCheck(['A', 'R', 'R', 'A', 'Y']) // false Примечание: перебирающий метод every и метод isArray Дополнительные задачи в онлайн тренажере codeWars 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. Sum of Minimums! (map, reduce) Odd or Even? (reduce и тернарный оператор) Filter out the geese Multiple of index filter with index Arguments to Binary addition (reduce) Convert an array of strings to array of numbers (map) Sum of Odd Cubed Numbers Help the Fruit Guy (map) Check three and two (filter) Distance from the average Square(n) Sum 8 (reduce) Invert values 8 (map) Square Every Digit (map, reduce/join) 197
Практическая работа на двумерные массивы Задание 1. 7 Окрестности ячейки (в матрице) — это ячейки, которые находятся рядом с ней. Существует два популярных типа: • • Moore neighborhood — это восемь ячеек, которые окружают данную ячейку; Von Neumann neighborhood — это четыре ячейки, которые имеют общую границу с данной ячейкой. Учитывая тип окрестности ("moore" или "von_neumann"), 2D-матрицу (массив массивов) и пару координат, напишите функцию, возвращающую массив соседей данной ячейки. Порядок элементов в выходном списке не имеет значения. Если входные индексы находятся за пределами матрицы, функции следует вернуть пустой массив. Если матрица пуста, функции следует так же вернуть пустой массив. function getNeighbourhood(type, matrix, coordinates) { } const matrix = [ [0, 1, 2], [3, 4, 5], [6, 7, 8], ] getNeighbourhood(['moore', matrix, [1, 1]]) // [0, 1, 2, 3, 5, 6, 7, 8] getNeighbourhood(['moore', matrix, [0, 0]]) // [1, 3, 4] getNeighbourhood(['von_neumann', matrix, [1, 1]]) // [1, 3, 5, 7] Задание 2. В зрительном зале 25 рядов по 45 мест. Информация о проданных билетах хранится в двумерном массиве, номера строк которого соответствуют рядам зрительного зала, а номера столбцов номерам мест. Если билет продан, в массив заносится единица, если нет — ноль. Заполните массив нулями и единицами случайным образом. Разработайте сце198
нарий, определяющий число проданных билетов в том или ином ряду по запросу. Задание 3. Заполните двумерный массив размером 10 на 10 случайным образом вещественными числами в диапазоне от –1000 до 1000. Разработайте скрипт, который определяет: a) сумму отрицательных элементов 5-ой строки массива; b) сумму элементов 4 столбца массива, меньших k; c) количество ненулевых элементов второго столбца, меньших s. Задание 4. Заполните двумерный массив размером m на n случайным образом вещественными числами в диапазоне от –10 000 до 10 000. Разработайте сценарий, который определяет: a) максимальное значение среди элементов любой заданной строки; примечание: уместно использование оператора расширения; b) минимальное значение среди элементов любого заданного столбца; c) координаты (положение) минимального и максимального элемента всего массива. Задание 5. Дана челочисленная квадратная матрица размером N. Заменить в ней все элементы, расположенные на главной диагонале и выше нее нулями. 10 21 32 44 51 60 65 13 49 12 16 81 77 43 23 58 54 28 87 56 53 85 25 75 75 35 78 97 24 70 87 54 23 87 65 89 0 0 0 0 0 0 65 0 0 0 0 0 77 43 0 0 0 0 87 56 53 0 0 0 75 35 78 97 0 0 87 54 23 87 65 0 199
Задание 6. 7 Похоже, на каждую хорошую идею ката приходится несколько плохих! В этом задании нужно проверить предоставленный двумерный массив (x) на наличие хороших идей (good) и плохих идей (bad). Если есть одна или две хорошие идеи, верните «Publish!», если их больше двух, верните «I smell a series!». Если хороших идей нет, как это часто бывает, верните «Fail!». Подмассивы могут иметь разную длину. Решение не должно учитывать регистр (т.е. good, GOOD и gOOd считаются хорошей идеей). Входные данные не должны быть строками. function well(x){ } well([['bad', 'bAd', 'bad'], ['bad', 'bAd', 'bad'], ['bad', 'bAd', 'bad']]) // 'Fail!' well([['gOOd', 'bad', 'BAD', 'bad', 'bad'], ['bad', 'bAd', 'bad'], ['GOOD', 'bad', 'bad', 'bAd']]) // 'Publish!' well([['gOOd', 'bAd', 'BAD', 'bad', 'bad', 'GOOD'], ['bad'], ['gOOd', 'BAD']]) // 'I smell a series!' Примечание: метод filter и flat Практическая работа на вложенные циклы Задание 1. 6 Дан массив целых чисел, составьте функцию, которая находит в нем число, встречающееся нечетное число раз. В массиве всегда будет только одно такое число. function findOdd(A) { } 200
findOdd([20,1,-1,2,-2,3,3,5,5,1,2,4,20,4,-1,-2,5]) // 5 findOdd([1,1,2,-2,5,2,4,4,-1,-2,5]) // -1 findOdd([1,1,1,1,1,1,10,1,1,1,1]) // 10 Задание 2. 6 Напишите функцию persistence, которая принимает положительное число num и возвращает его мультипликативную стойкость, которая представляет собой количество раз, которое позволяет умножать все цифры в num, пока в результате не будет достигнуто единственной цифры. 39 // 3 (так как 3*9 = 27, 2*7 = 14, 1*4 = 4, 4) 999 // 4 (так как 9*9*9 = 729, 7*2*9 = 126, 1*2*6 = 12, 1*2 = 2) 4 // 0 function persistence(num) { } persistence(39) // 3 persistence(25) // 2 persistence(999) // 4 Задание 3. 7 Даны два массива строк a1 и a2. Пусть x — любая строка в первом массиве, а y — любая строка во втором массиве. Найти max(abs(длина(x) − длина(y))) Если a1 или a2 пустой, верните значение -1. function mxdiflg(a1, a2) { } 201
var s1 = ["hoqq", "bbllkw", "oox", "ejjuyyy", "plmiis", "xxxzgpsssa", "xxwwkktt", "znnnnfqknaz", "qqquuhii", "dvvvwz"] var s2 = ["cccooommaaqqoxii", "gggqaffhhh", "tttoowwwmmww"] mxdiflg(s1, s2) // 13 Задание 4. 7 Вы — разработчик, работающий над веб-сайтом, на главной странице которого имеется большой счетчик, с гордостью отображающий количество довольных клиентов, загрузивших программное обеспечение вашей компании. Вам поручено добавить визуальный динамический эффект к этому счетчику, чтобы сделать его более интересным. Вместо того, чтобы просто отображать значение счетчика сразу же при загрузке страницы, необходимо создать эффект циклического прохождения каждой цифры через предыдущие числа, прежде чем остановиться на фактическом значении. В качестве шага к достижению цели вы решили создать функцию, которая будет создавать многомерный массив на основе значения счетчика скачиваний. Каждый элемент массива представляет собой отдельную цифру счетчика попаданий и будет включать все числа, стоящие перед ним, начиная с 0. Функция принимает один аргумент, который является строкой из четырех цифр, представляющей количество скачиваний. Функция должна возвращать многомерный массив, содержащий четыре внутренних массива. Последнее значение в каждом внутреннем массиве должно быть фактическим значением, которое будет отображаться. Значения, возвращаемые в массиве, должны быть числового типа. function counterEffect(hitCount) { } counterEffect("1250") // [[0,1],[0,1,2],[0,1,2,3,4,5],[0]] 202
counterEffect("0050") // [[0],[0],[0,1,2,3,4,5],[0]] counterEffect("0000") // [[0],[0],[0],[0]] Задание 5. 7 Дано целое число n (n >= 0) и цифра d (0 <= d <= 9). Напишите функцию, возводящую в квадрат все числа между 0 и n и возвращающую количество цифр d, встречающихся в квадратах чисел. Например, nbdig (10, 1) // 4, так как квадраты чисел 0, 1, 4, 9, 16, 25, 36, 49, 64, 81, 100. В них 1 встречается в числах: 1, 16, 81, 100. nb_dig(25, 1) // 11, так как квадраты чисел 1, 16, 81, 100, 121, 144, 169, 196, 361, 441. Задание 6. 7 Дан треугольник последовательных нечетных чисел Вычислите сумму чисел в n-м ряду. function rowSumOddNumbers(n) { } rowSumOddNumbers(1) // 1 rowSumOddNumbers(42) // 74088 203
Задание 7. 7 Запрограммируйте функцию sumAverage(arr) где arr — это массив, содержащий массивы, заполненные числами. Сначала определите среднее значение каждого массива, а затем верните сумму всех средних значений. Все числа будут меньше 100 и больше –100. Массив arr будет содержать максимум 50 массивов. После вычисления всех средних значений сложите их вместе, а затем округлите в меньшую сторону. const sumAverage = (arr) => { } sumAverage([[3, 4, 1, 3, 5, 1, 4], [21, 54, 33, 21, 77]]) // 44 sumAverage([[-4, 3, -8, -2], [2, 9, 1, -5], [-7, -2, -6, -4]]) // -6 Задание 8. 6 Дан массив целых чисел. Задача — найти в нем индекс N, при котором сумма целых чисел слева от N равна сумме целых чисел справа от N. Если нет индекса, который бы это сделал, верните –1. Пустые массивы в этой задаче равны 0. Индекс 0 — это место, где левая и правая стороны равны. Если дан массив с несколькими ответами, верните наименьший правильный индекс. function findEvenIndex(arr) { } findEvenIndex ([1,2,3,4,3,2,1]) // 3 findEvenIndex ([1,100,50,-51,1,1]) // 1 findEvenIndex ([1,2,3,4,5,6]) // -1 findEvenIndex ([20,10,30,10,10,15,35]) // 3 findEvenIndex ([20,10,-80,10,10,15,35]) // 0 findEvenIndex ([10,-80,10,10,15,35,20]) // 6 findEvenIndex ([8,8]) // -1 findEvenIndex ([8,0]) // 0 findEvenIndex ([0,8]) // 1 204
Задание 9. 6 Напишите функцию, которая принимает массив чисел (целых чисел для тестов) и целевое число. Она должна найти два разных элемента массива, которые при сложении дают целевое значение. Индексы этих элементов должны быть возвращены в виде массива, например: [index1, index2]. function twoSum(numbers, target) { } twoSum ([1, 2, 3], 4) // [0, 2] twoSum ([3, 2, 4], 6) // [1, 2] Задание 10. 6 Задача — составить таблицу умножения N×N, размер которой указан в параметре функции. function multiplicationTable(size) { } multiplicationTable (3) // [[1, 2, 3], [2, 4, 6], [3, 6, 9]] Задание 11. 7 Городской шериф не любит нечетные номера и хочет, чтобы все семьи с нечетными номерами покинули город! В городе могут скапливаться толпы, и люди часто смешиваются с другими людьми и семьями. Однако вы можете определить, к какой семье принадлежит человек, по номеру на футболке. Ваша задача, как помощника шерифа, — найти все семьи с нечетными номерами и выселить их из города! 205
Задача. Дан массив чисел. Каждое число повторяется определенное количество раз. Удалите все числа, повторяющиеся нечетное количество раз, сохранив все остальное как есть. function oddOnesOut(nums) { } oddOnesOut ([1, 2, 3, 1, 3, 3]) // [1, 1] oddOnesOut ([75, 68, 75, 47, 68]) // [75, 68, 75, 68] oddOnesOut ([100, 100, 5, 5, 100, 50, 68, 50, 68, 50, 68, 5, 100]) // [100, 100, 100, 100] Примечание: метод filter Практическая работа на сортировку Задание 1. 7 Напишите функцию, которая принимает массив строк в качестве аргумента и возвращает отсортированный массив, содержащий одни и те же строки, упорядоченные от кратчайшего к самому длинному. Все строки в массиве разной длины. function sortByLength (array) { } sortByLength(["Beg", "Life", "I", "To"]) // ["I", "To", "Beg", "Life"] sortByLength(["", "Moderately", "Brains", "Pizza"]) // ["", "Pizza", "Brains", "Moderately"] sortByLength(["Longer", "Longest", "Short"]) // ["Short", "Longer", "Longest"] 206
Задание 2. 7 Дана последовательность размеров прямоугольников (ширина и длина) и кругов (радиус). Задача функции — вернуть новую последовательность измерений, отсортированных по возрастанию их площади. const array = [ [4.23, 6.43], 1.23, 3.444, [1.342, 3.212] ] // [ rectangle, circle, circle, rectangle ] sortByArea(array) => [ [ 1.342, 3.212 ], 1.23, [ 4.23, 6.43 ], 3.444 ] function sortByArea(array) { } sortByArea([ [2, 5], 6 ]) // [ [2, 5], 6 ] sortByArea([]) // [] Задание 3. 7 Дан массив целых чисел нечетной длины, в котором все числа одинаковы, за исключением одного единственного числа. Напишите функцию, которая принимает такой массив и возвращает это единственное число. Входной данные предполагаются валидными. [1, 1, 2] ==> 2 [17, 17, 3, 17, 17, 17, 17] ==> 3 function stray(numbers) { } stray([1, 1, 2]) // 2 stray([1, 2, 1]) // 2 stray([2, 1, 1]) // 2 207
Задание 4. 6 Задача — отсортировать заданную строку слов. Каждое слово в строке содержит одно число. Это число обозначает позицию, которую слово должно занимать в результате. Числа могут быть от 1 до 9. Таким образом, первым словом будет слово с числом 1. Если входная строка пуста, верните пустую строку. Слова во входной строке содержат только допустимые числа. function order(words) { } order("is2 Thi1s T4est 3a") // "Thi1s is2 3a T4est" order("4of Fo1r pe6ople g3ood th5e the2") // "Fo1r the2 g3ood 4of th5e pe6ople" order("") // "" Задание 5. 7 Дан массив/список целых чисел. Найдите N-й наименьший элемент в массиве. function nthSmallest(arr, pos) { } nthSmallest([3,1,2], 2) // 2 nthSmallest([15,20,7,10,4,3], 3) // 7 nthSmallest([-5,-1,-6,-18], 4) // -1 208
Задание 6. 7 Дана упорядоченная последовательность чисел от 1 до N. Из неe могли удалить одно число, а затем оставшиеся числа перемешали. Найдите вычеркнутое число. Если из начального массива не было удалено ни одного числа, функция должна вернуть 0. function findDeletedNumber(arr, mixArr) { } findDeletedNumber([1,2,3,4,5], [3,4,1,5]) // 2 findDeletedNumber([1,2,3,4,5,6,7,8,9], [1,9,7,4,6,2,3,8]) // 5 findDeletedNumber([1,2,3,4,5,6,7,8,9], [5,7,6,9,4,8,1,2,3]) // 0 Задание 7. 7 По заданному числу определите, аккуратно оно или нет. Аккуратное число — это число, цифры которого расположены в неубывающем порядке . function tidyNumber(n) { } tidyNumber(12) // true tidyNumber(102) // false tidyNumber(9672) // false Задание 8. 7 Имея строку слов, необходимо вернуть массив слов, отсортированных в алфавитном порядке по последнему символу в каждом слове. Если два слова имеют одинаковую последнюю букву, возвращаемый массив 209
должен отображать их в том порядке, в котором они появились в заданной строке. function last(x) { } last('man i need a taxi up to ubud') // ['a', 'need', 'ubud', 'i', 'taxi', 'man', 'to', 'up'] last('what time are we climbing up the volcano') // ['time', 'are', 'we', 'the', 'climbing', 'volcano', 'up', 'what'] last('take me to semynak') // ['take', 'me', 'semynak', 'to'] 210
ОПЕРАТОР РАСШИРЕНИЯ В ES2015 появился оператор расширения (…), который позволяет разделять доступные для перебора значения. При вставке массива в другой массив получается вложенный массив, но если необходимо добавить не сам массив, а лишь его элементы (содержимое), то быстрее всего это сделать с помощью оператора расширения. { let м1 = [31, 14] let м2 = [19, 12, м1, 15, 16] console.log(м2) // [19, 12, [31, 14], 15, 16] let м2 = [19, 12, ...м1, 15, 16]; console.log(м2) ) // [19, 12, 31, 14, 15, 16] } Часть методов математического объекта Math имееют в качестве аргументов только числа. Оператор расширения может позволить использовать массивы в качестве аргументов этих методов. Например, метод max находит максимальное из нескольких чисел. С оператором расширения можно находить максимальное из элементов массива. { var массив = [12, 14, 18, 26, -10] var max = Math.max(...массив) console.log (max) // 26 } Копирование массивов невозможно простым присваиванием имени массива новой переменной. Таким образом можно присвоить только ссылку на массив, что означает одновременное изменение значений у обеих переменных при изменении значения у любой из них. Оператор расширения позволяет создать реальную копию массива. { let массив1 = ['a', 'b', 'c'] let массив2 = [...массив1] console.log(массив2) // ['a', 'b', 'c'] } 211
Слияние нескольких массивов также удобно осуществлять оператором расшинения. { let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; let arr3 = [6, 7, 8]; arr1 = [...arr1, ...arr2, ...arr3]; console.log(arr1) // [0, 1, 2, 3, 4, 5, 6, 7, 8] } С помощью оператора расширения можно преобразовать строку в массив символов. { let строка = "столешница" let массивБукв = [...строка] console.log (массивБукв) // ["с", "т", "о", "л", "е", "ш", "н", "и", "ц", "а"] } Оператор расширения может разделять значения, а собирать их в массив умеет параметр rest, который также обозначается троеточием перед именем переменной, стоящей в параметрах описания функции. Например, в функции средняяЗарплата при отсутствии описанных аргументов, параметр rest соберет все значения в массив. function средняяЗарплата (...работники) { let сумма=0 for (i=0;i<работники.length;i++) { сумма+=работники[i] } return (сумма/работники.length) } alert (средняяЗарплата(100, 200, 300, 400, 500)) // 300 212
Практическая работа на оператор расширения и rest параметры Задание 1. 8 Задача состоит в том, чтобы создать две функции (maximum и minimum), которые получают массив целых чисел в качестве входных данных и возвращают, соответственно, наибольшее и наименьшее число в нем. var min = function(list) { } var max = function(list) { } min([-52, 56, 30, 29, -54, 0, -110]) // -110 min([42, 54, 65, 87, 0]) // 0 max([4,6,2,1,9,63,-134,566]) // 566 Задание 2. 7 Создайте функцию, которая при наличии триплета возвращает индекс числового элемента, который должен находиться по значению между двумя соседними элементами. function gimme (triplet) { } gimme ([-5, -10, -14]) // 1 gimme ([-2, -3, -1]) // 0 gimme ([2.1, 3.2, 1.4]) // 0 gimme ([5.9, 10.4, 14.2]) // 1 213
Задание 3. 7 Напишите функцию, которая возвращает наименьшее значение массива или индекс этого значения. Первый параметр функции — массив чисел, второй параметр функции укажет, должна ли она возвращать значение или индекс ('value' или 'index') элемента массива. function min(arr, toReturn) { } min([1,2,3,4,5], 'value') // 1 min([1,2,3,4,5], 'index') // 0 Задание 4. 7 Мой дедушка всегда предсказывал, какими старыми станут люди, и прямо перед смертью он раскрыл свой секрет! В честь памяти моего дедушки мы напишем функцию, используя его формулу! Составьте массив возрастов, в которых умер каждый из ваших прадедов. • • • • Умножьте каждое число само на себя. Сложите все числа вместе. Извлеките квадратный корень из результата. Разделите результат на два. Конечный результат должен быть округлен в меньшую сторону до ближайшего целого числа. function predictAge(age1,age2,age3,age4,age5,age6,age7,age8) { } predictAge(65,60,75,55,60,63,64,45) // 86 214
Задание 5. 7 Напишите код функции, возвращающей сумму всех своих аргументов. Аргументы функции — любое количество чисел. function sum() { } sum(1) // 1 sum(1, 2) // 3 sum(12, 1, 1, 1, 1, 1, 1) // 18 Задание 6. 7 Дан двумерный массив целых чисел. Напишите функцию, которая возвращает плоскую версию массива со всеми целыми числами в отсортированном (по возрастанию) порядке. [[3, 2, 1], [4, 6, 5], [], [9, 7, 8]] => [1, 2, 3, 4, 5, 6, 7, 8, 9] function flattenAndSort(array) { } flattenAndSort([]) // [] flattenAndSort([[], [1]]) // [1] flattenAndSort([[1, 3, 5], [100], [2, 4, 6]]) // [1, 2, 3, 4, 5, 6, 100] flattenAndSort([[3, 2, 1], [7, 9, 8], [6, 4, 5]]) // [1, 2, 3, 4, 5, 6, 7, 8, 9] Задание 7. 7 Напишите функцию, которая возвращает количество полученных ею аргументов. 215
args_count(100) // 1 args_count(100, 2, 3) // 3 args_count() // 0 Задание 8. 7 Напишите функцию с именем numbers. Функция должна возвращать значение true, если все передаваемые ей параметры имеют тип integer или float. В противном случае функция должна возвращать значение false. Функция должна принимать любое количество параметров. numbers(1, 4, 3, 2, 5) // true numbers(1, "a", 3) // false numbers(1, 3, None) // false numbers(1.23, 5.6, 3.2) // true Задание 9. 6 Завершите решение так, чтобы оно возвращало true, если функция содержит повторяющиеся значения аргументов и false в противном случае. В функцию можно передать любое количество аргументов. Передаваемые значения массива только строки или числа. function solution() { } solution(1, 2, 3, 1, 2) // true solution() // false solution(1, 1) // true solution(1, 0) // false solution('a', 'b') // false solution('a', 'b', 'a') // true solution(1, 2, 42, 3, 4, 5, 42) // true solution('a', 'b', 'c', 'd') // false 216
СТРОКИ. Объект String Определение и примеры строки рассмотрены на странице 26 данного учебного пособия. В JavaScript существует объект String и каждая строковая переменная может создаваться через вызов конструктора var  = new String(), где  — имя строковой переменной,  — строковое значение. var строка1 = new String (‘Черепаха изучает информатику’) Но строковую переменную не обязательно создавать через конструктор, можно также как и числовые переменные. Над строками, как и над числами, можно совершать операцию сложения. Для этого используется тот же знак “+”. В результате сложения строк получается одна строка, состоящая из всех слагаемых членов. Для обработки строк подходит тот же цикл forof, что и для перебора элементов массива. При его использовании со строками получается перебор всех символов строки. let str = "abbrakadabbra" let newstr = "" for (let letter of str) { newstr += letter + letter } console.log (newstr) // aabbbbrraakkaaddaabbbbrraa Свойства или методы Параметры Значение или действие .length  — имя строковой переменной возвращает длину строки, т. е. число символов строки .search ()  — имя строковой переменной,  — подстрока, образец поиска или регулярное выражение возвращает номер, с которого начинается подстрока  в строке . при осуществлении поиска слева направо или –1 при отсутствии совпадения 217
Продолжение табл. Свойства или методы Параметры Значение или действие .indexOf ( [,])  — имя строковой переменной,  — подстрока, образец поиска,  — номер элемента строки , с которого производится поиск возвращает номер, с которого начинается подстрока  в строке . при осуществлении поиска слева направо .lastIndexOf ( [,])  — имя строковой переменной,  — подстрока, образец поиска,  — номер элемента строки , с которого производится поиск возвращает номер, с которого начинается подстрока  в строке . при осуществлении поиска справа налево. Если образец не найден, возвращается значение –1 str10="gg" nc=str10.lastIndexOf(".") console.log (nc) // -1 .repeat() .at ([])  []  — имя строковой переменной,  — число повторений строки  возвращает новую строку, содержащую  копий строки   — имя строковой переменной,  — индекс элемента строки , по умолчанию 0, –1 указывает на последний символ возвращает символ строки  с индексом  ECMAScript 2015 let text = "JavaScript"; let character = text.at(0) // “J” .charAt ()  — имя строковой переменной,  — номер элемента строки  218 возвращает символ строки  с номером 
Продолжение табл. Свойства или методы Параметры Значение или действие str4="Иванов Петр Семёнович" strarray4=str4.split(" ") f1=strarray4[0] f2=strarray4[1].charAt(0) + "." f3=strarray4[2].charAt(0) + "." console.log (f1,f2,f3) // Иванов П.С. .charCodeAt ()  — имя строковой переменной,  — номер элемента строки  возвращает код символа строки  с номером  String.fromCha rCode (1 [{,2}]) 1, 2, … — число, числовая переменная или функция возвращает строку из символов по кодам 1, 2, … .slice (н [,к])  — имя строковой переменной, н — номер начального элемента фрагмента строки , к — номер конечного элемента фрагмента строки  возвращает подстроку строки  с позиции н до позиции к-1. Если к не указан, то до конца строки . Отрицательное значение к ведет отсчет от конца строки str="gg.gif" nc=str.lastIndexOf(".") // 2 newstr=str.slice(0,nc) // gg console.log (str) // gg.gif .split ( [,])  — имя строковой переменной,  — символ-разделить слов (подстрок) в строке   — максимальное число элементов 219 возвращает массив из подстрок строки , разделенных символом . Число элементов массива равно . Если  не указан, то в массив войдут все подстроки. В качестве  может стоять регулярное выражение
Продолжение табл. Свойства или методы Параметры Значение или действие //написать скрипт, который выводит в консоль браузера первое слово заданной символьной строки str9="Однажды в студёную зимнюю пору" strarray9=str9.split(" ") console.log(strarray9[0]) // Однажды .substr ( [,])  — имя строковой переменной,  — номер начального элемента фрагмента строки ,  — число символов подстроки возвращает подстроку строки , начиная с позиции  длиной . Если  не указан, то с позиции  до конца строки  .substring (н [,к])  — имя строковой переменной, н — номер начального элемента фрагмента строки , к — номер конечного элемента фрагмента строки  возвращает подстроку строки  от позиции н до к-1. Если к не указан, то до конца строки  .toLowerCase () переводит все символы строки  в нижний регистр .toUpperCase () переводит все символы строки  в верхний регистр .trim() возвращает строку с вырезанными на концах пробельными символами (пробел, табуляция, неразрывный пробел и все символы конца строки — LF, CR и прочие) .trimEnd() возвращает строку с удаленными пробелами в конце строки, не меняет исходную строку .trimStart() возвращает строку с удаленными пробелами в начале строки, не меняет исходную строку .replace (, ) возвращает строку , в которой заменено первое вхождение подстроки  на строку . В качестве  может стоять регулярное выражение (см. следующий параграф). В качестве  может быть использована функция для замены найденного образца 220
Продолжение табл. Свойства или методы Параметры Значение или действие “example”.replace("e", "@") // @xample “example”.replace(/e/g, x=>x.toUpperCase()) // ExamplE let s="stop Making spongebob Memes!" s.replace(/./gi, (x,i) => i%2 ? x.toLowerCase() : x.toUpperCase() ) // 'StOp mAkInG SpOnGeBoB MeMeS!' .replaceAll (, ) возвращает строку , в которой заменено каждое вхождение подстроки  на строку . В качестве  может стоять регулярное выражение (см. следующий параграф). В качестве  может быть использована функция для замены найденного образца строка = “Здесь должен располагаться Ваш текст Здесь должен располагаться Ваш текст Здесь текст должен текст текст располагаться Ваш располагаться” строка.replaceAll ("Ваш", "наш") // Здесь должен располагаться наш текст Здесь должен располагаться наш текст Здесь текст должен текст текст располагаться наш располагаться .startsWith( [,]) возвращает булевое значение в зависимости от того, начинается ли строка  символами . Необязательный параметр  (длина строки) позволяет искать внутри строки, обрезая ее по диапазону, по умолчанию равен длине строки .endsWith( [,]) возвращает булевое значение в зависимости от того, заканчивается ли строка  символами . Необязательный параметр  (длина строки) позволяет искать внутри строки, обрезая ее по диапазону, по умолчанию равен длине строки .padStart( [,]) заполняет текущую строку  другой строкой  (по умолчанию пробел) столько раз, чтобы итоговая строка достигала длины . Заполнение осуществляется в начале текущей строки 221
Продолжение табл. Свойства или методы Параметры Значение или действие 'abc'.padStart(10, "kuku") // "kukukukabc" .padEnd( [,]) заполняет текущую строку  другой строкой  (по умолчанию пробел) столько раз, чтобы итоговая строка достигала длины . Заполнение осуществляется в конце текущей строки "7".padEnd(4,"a") // "7aaa" Примеры // найти число вхождений буквы «а» в заданном тексте let количество_а = 0 const текст = "Здесь должен располагаться Ваш текст" for (let i = 0; i < текст.length; i++) { if (текст.charAt(i) == "а") количество_а++ } console.log (количество_а) // 4 // вывести на веб-страницу все слова строки в столбик let массив = текст.split (" ") for (let i of массив) { document.write ("<h3>"+i+"</h3>") } //Здесь //должен //располагаться //Ваш //текст // заменить расширение файла на заданное новое расширение str10="qq.work.xml" f="tmp" nc=str10.lastIndexOf(".") if (nc==-1) { str10+="."+f 222
} else { str10=str10.slice(0,nc+1)+f } console.log (str10) // qq.work.tmp /* Напишите функцию camelize(str), которая преобразует строки вида 'my-short-string' в 'myShortString'. Функция удаляет дефисы, а все слова после них начинаются с заглавной буквы. */ function camelize(str) { let strarr=str.split(''); let newarr=[]; for (i=0; i<strarr.length; i++) { if (strarr[i]!="-") newarr.push (strarr[i]) else { i++ newarr.push (strarr[i].toUpperCase()) } } return newarr.join(''); } camelize('background-color') // 'backgroundColor'; camelize('list-style-image') // 'listStyleImage'; camelize('-webkit-transition') // 'WebkitTransition'; Задание1 Дана строка цифр. Составьте скрипт, подсчитывающий сумму цифр строки. Задание2 Дана строка чисел (числа отделены пробелом). Составьте скрипт, подсчитывающий сумму чисел строки. 223
Задание3 Дан номер мобильного телефона +79053672091. Составьте скрипт, расставляющий пробелы в номере для лучшего просмотра: +7 905 367 20 91 П р и м е р. Число слов. Разработайте сценарий, который подсчитает число одинаковых слов, встречающихся в текстовом поле веб-страницы. <HTML> <HEAD> <SCRIPT> function подсчитать_слова () { var строка = document.forms[0].txt.value var m = new Array (); m = строка.split (' ') var сколько_слов = 0, номер_слова = 0 while (!m.length == 0) { сколько_слов = 1; текущее_слово = m [0]; m.splice (0,1) for (i = 0; i < m.length; i++) { if (текущее_слово == m [i]) { сколько_слов++ m.splice (i,1) i-} } document.forms[0].список_оригинальных_слов. 224
options [номер_слова]=new Option (текущее_слово+" - " + сколько_слов) номер_слова++ } } function чистить () { n=document.forms[0].список_оригинальных_слов.length for (i=0; i<n; i++) document.forms[0].список_оригинальных_слов.options[0]=null document.forms[0].reset () } </SCRIPT> </HEAD> <BODY STYLE="font-size:20pt"> <H1 style=”text-align:center”>Проект. Число слов</H1> <FORM> <DIV STYLE=”text-align:center”> <P STYLE=”text-align:top”> Введите текст <TEXTAREA NAME="txt" ROWS="7" COLS=35 style="display:inline; vertical-align:top; font-size:20pt; font-style:italic;"> Здесь должен располагаться Ваш текст Здесь должен располагаться Ваш текст Здесь должен располагаться Ваш текст </TEXTAREA> </P> <INPUT TYPE="button" VALUE="Подсчитать слова" STYLE="fontsize:21pt" ONCLICK="подсчитать_слова ()"> <INPUT TYPE="button" VALUE="Очистить" STYLE="font-size:21pt" ONCLICK = "чистить ()"> <P> <SELECT NAME='список_оригинальных_слов' size=5 style="fontsize:21pt"> <OPTION> результат <OPTION> будет <OPTION> здесь </SELECT> </P> </DIV> </FORM> 225
</BODY> </HTML> Практическая работа на строки Задание 1. Усовершенствуйте скрипт из примера 2 таким образом, чтобы он учитывал знаки препинания, то есть чтобы знаки препинания не влияли на подсчет одинаковых слов. Задание 2. Разработайте сценарий, который сможет перевести текстовую информацию, размещенную на веб-странице с русского языка в кириллице на русский, но в латинском алфавите и предусмотрите обратный перевод. Задание 3. Разработайте сценарий, который сможет зашифровывать многострочный текст, размещенный на веб-странице методом сдвига по алфавиту. Предусмотрите возможность расшифровки сообщения. Задание 4. Разработайте сценарий, который сможет словами написать заданное число. Например 5 535 → Пять тысяч пятьсот тридцать пять. Задание 5. Разработайте сценарий, который сможет по нажатию на соответствующую кнопку добавлять часто употребляемые слова, например: добрый день, спасибо, пожалуйста, к сожалению, и так далее. 226
Задание 6. Разработайте сценарий, который сможет по введенному при наборе текста шаблону (например, дбр) автоматически заменять его на соответствующее слово (например, добрый). Задание 7. Разработайте сценарий, который сможет осуществлять поиск в исходной строке по образцу и замену найденного фрагмента на заданный. Предусмотрите подсчет числа замен. Задание 8. Разработайте сценарий, который сможет удалять идущие подряд несколько пробелов, оставляя только один. Предусмотрите счетчик удалений. Задание 9. Разработайте сценарий, который сможет из введенного поcетителем слова построить слово-перевертыш и определить совпадает ли словоперевертыш с исходным словом. Задание 10. Разработайте сценарий, который сможет удалять из текста заданные слова. Предусмотрите подсчет числа удалений. Задание 11. Разработайте сценарий, который переведет в верхний регистр первую букву каждого слова, следующего за точкой. Проект 12. Разработайте сценарий, который в заданное число добавит пробелы так, чтобы они отделяли по 3 разрада справав налево. Задание 13. Разработайте сценарий, который к заданному рациональному числу добавит недостающие нули справа так, чтобы число имело только два знака после десятичной точки (запятой). Задание 14. Реализуйте форму в соответствии с приведенными критериями. 1. Фамилия (текстовое поле от 3-х до 20 символов без цифр, первая буква заглавная). 2. Логин (текстовое поле от 3-х до 10 символов и состоит из латинских символов и цифр). 3. Пароль (содержит по крайней мере одну букву, по крайней мере одну прописную букву, по крайней мере одну цифру, не менее 8 символов). 227
4. 5. 6. Подтвердите пароль (должно быть равно полю с паролем). Дата рождения (в формате день.месяц.год или день/месяц/ год). Телефон (в виде (555) 555-5555 или (555) 55-55-55 с пробелами или без). Задание 15. 8 Дано положительное целое число n. Напишите функцию, возвращающую строку-считалку "1 sheep...2 sheep...3 sheep...", в которой ключевая фраза повторяется n раз. function countSheep (n) { } countSheep(0) // "" countSheep(1) // "1 sheep..." countSheep(2) // "1 sheep...2 sheep..." Задание 16. 8 Создайте функцию с именем shortcut для удаления строчных гласных (a, e, i, o, u ) в заданной строке. function shortcut (string) { 228
} shortcut ("hello") // "hll" shortcut ("codewars") // "cdwrs" shortcut ("goodbye") // "gdby" shortcut ("HELLO") // "HELLO" Задание 17. 7 Помните мем губки Боба, который предназначен для того, чтобы высмеивать людей, повторяя то, что они говорят, в насмешливой форме? Создайте функцию, которая преобразует входные данные в этот формат. Выходные данные будут той же строкой, но строчные и прописные буквы должны чередоваться друг с другом. function spongeMeme (str) { } spongeMeme("stop Making spongebob Memes!") // 'StOp mAkInG SpOnGeBoB MeMeS!' spongeMeme("colored teens cant Be successful in tech") // 'CoLoReD TeE Задание 18. 7 Напишите функцию, которая вернет длину самого короткого слова в исходной строке слов. Исходная строка никогда не будет пустой, и нет необходимости учитывать разные типы данных. function findShort(s){ } findShort("bitcoin take over the world maybe who knows perhaps") // 3 findShort("turns out random test cases are easier than writing out basic ones") // 3 findShort("Let's travel abroad shall we") // 2 229
Задание 19. 7 Анаграмма — это результат перестановки букв слова для получения нового слова. Анаграммы не чувствительны к регистру. Напишите функцию, которая вернет значение true, если два приведенных аргумента являются анаграммами друг друга в противном случае вернет значение false. var isAnagram = function(test, original) { }; isAnagram("foefet", "toffee") // true isAnagram("Buckethead", "DeathCubeK") // true isAnagram("Twoo", "WooT") // true isAnagram("dumble", "bumble") // false isAnagram("ound", "round") // false isAnagram("apple", "pale") // false Задание 20. В переменных name, surname написаны имя и фамилия человека. При этом в строках беспорядок с большими и маленькими буквами, и нужно привести строки в порядок. Для этого первые буквы имени и фамилии приведите к верхнему регистру, а оставшиеся буквы — к нижнему. Запишите результат в новые переменные и выведите их значения с помощью console.log. С помощью тернарных операторов и console.log выведите сообщение «Имя было преобразовано» или «Имя осталось без изменений» для имени и фамилии в зависимости от того, были ли исходные строки равны преобразованным. Задание 21. 7 Тролли атакуют ваш раздел комментариев. Распространенным способом справиться с этой ситуацией является удаление всех гласных из комментариев троллей, нейтрализуя угрозу. Задача состоит в том, чтобы написать функцию, которая принимает строку и возвращает новую строку со всеми удаленными гласными. 230
function disemvowel(str) { } disemvowel("This website is for losers LOL!") // "Ths wbst s fr lsrs LL!" disemvowel("No offense but,\nYour writing is among the worst I've ever read") // "N ffns bt,\nYr wrtng s mng th wrst 'v vr rd" disemvowel("What are you, a communist?") // "Wht r y, cmmnst?" Задание 22. 7 Группы персонажей решили устроить битву. Помогите им выяснить, какая группа более могущественна. Создайте функцию, которая будет принимать 2 строки и возвращать ту, которая сильнее. Строки будут состоять только из прописных букв. У каждого символа есть своя сила: A = 1, B = 2, ... Y = 25, Z = 26. Выигрывает группа, чья общая мощность сиволов строки (A + B + C + ...) больше. Если силы равны, то это ничья. function battle(x, y) { // Lets the battle begin! } battle("AAA", "Z") // "Z" battle("ONE", "TWO") // "TWO" battle("ONE", "NEO") // "Tie!" battle("FOUR", "FIVE") // "FOUR" Задание 23. 7 Обычно когда вы что-то покупаете, вас спрашивают, верен ли номер вашей кредитной карты, номер телефона или ответ на ваш самый секретный вопрос. Однако, поскольку кто-то может заглянуть вам через плечо, вы не хотите, чтобы это отображалось на вашем экране. Вместо этого мы маскируем это. Задача — написать функцию maskify, которая 231
преобразует все символы исходной строки чисел, кроме последних четырех, в '#'. function maskify(cc) { } maskify('4556364607935616'), '############5616' maskify('1'), '1' maskify('11111'), '#1111' Задание 24. 8 Составьте функцию так, чтобы она изменила все слова в переданной строке на противоположные. function reverseWords(str) { } reverseWords("hello world!") // "world! hello" reverseWords("yoda doesn't speak like this") // doesn't yoda" reverseWords("foobar") // "foobar" "this like speak Задание 25. 8 Составьте функцию так, чтобы она изменила переданную в нее строку на противоположную. function solution(str) { } solution('world') // 'dlrow' solution('hello') // 'olleh' solution('') // '' 232
Задание 26. 8 Создайте функцию, которая удаляет первый и последний символы строки. Дается один параметр — исходная строка, содержащая не менее двух символов. function removeChar(str) { }; removeChar('eloquent') // 'loquen' removeChar('country') // 'ountr' removeChar('person') // 'erso' Задание 27. 8 Напишите функцию для разделения строки и преобразования ее в массив слов. function stringToArray(string) { } stringToArray("Robin Singh") // ["Robin", "Singh"] stringToArray("I love arrays they are my favorite") // ["I", "love", "arrays", "they", "are", "my", "favorite"] Задание 28. 7 Создайте функцию, которая фильтрует массив строк и возвращает массив, содержащий только имена Ваших друзей. Если в имени ровно 4 буквы, вы можете быть уверены, что это Ваш друг! В противном случае вы можете быть уверены, что это не так... function friend(friends){ 233
} friend(["Ryan", "Kieran", "Mark"]) // ["Ryan", "Mark"] friend(["Ryan", "Jimmy", "123", "4", "Cool Man"]) // ["Ryan"] friend(["Jimm", "Cari", "aret", "truehdnviegkwgvke", "sixtyiscooooool"]) // ["Jimm", "Cari", "aret"] friend(["Love", "Your", "Face", "1"]) // ["Love", "Your", "Face"] Задание 29. 8 Напишите функцию hello, которая возвращает "Hello, <имя>!" по заданному имени или "Hello, World!" если имя не указано (или передается как пустая строка). Имя должно начинаться с первой заглавной буквы (Xxxx). Для проверки имени используйте условный или тернарный оператор. function hello(name = '') { } hello('alice') // 'Hello, Alice!' hello() // 'Hello, World!' hello('') // 'Hello, World!' Задание 30. 8 Дана строка, содержащая последовательность последовательностей символов, разделенных запятыми. Напишите функцию, которая возвращает новую строку, содержащую те же последовательности символов, за исключением первой и последней, но разделенных пробелами. Если входная строка пуста или удаление первого и последнего элементов приведет к тому, что результирующая строка будет пустой, верните null. function array(arr) { } 234
array('1,2,3') // '2' array('1,2,3,4') // '2 3' array('1,2,3,4,5') // '2 3 4' array('') // null array('1') // null array('1,2') // null Задание 31. 8 Дано случайное неотрицательное число, функция должна вернуть цифры этого числа в массиве в обратном порядке. function digitize(n) { } digitize(35231) // [1,3,2,5,3] digitize(0) // [0] Задание 32. 8 Напишите функцию, которая принимает размер строки и возвращает строку из чередующихся "1" и "0". Строка всегда должна начинаться с 1. Размер строки всегда положительное целое. function stringy(size) { } stringy(6) // '101010' stringy(4) // '1010' stringy(12) // '101010101010' Примечание: padStart() 235
Задание 33. 6 Матери устроили танцевальную вечеринку для детей в школе. На этой вечеринке есть только матери и их дети. Все очень веселились на танцполе, когда внезапно погас весь свет. Ночь темная, никто не может видеть друг друга. Но вы случайно оказались поблизости, и вы можете видеть в темноте и иметь возможность телепортировать людей куда угодно, куда захотите. Заглавные буквы обозначают матерей, те же буквы, но в нижнем регистре обозначают их детей, например, "А" — это мать, ее дети — "ааааа". Дана строка, которая содержит только буквы, заглавные буквы уникальны. Составьте функцию, которая вернет всех людей в алфавитном порядке, где за матерями следуют их дети function findChildren(dancingBrigade) { } findChildren ("beeeEBb") // "BbbEeee" findChildren ("uwwWUueEe") // "EeeUuuWww" findChildren ("AaaaaZazzz") // "AaaaaaZzzz" Задание 34. 7 Создайте функцию, которая возвращает значение true, если первый переданный аргумент (строка) заканчивается вторым аргументом (также строкой). function solution(str, ending) { } solution('abcde', 'cde') // true solution('abcde', 'abc') // false Примечание: endsWith() 236
Задание 35. Создайте функцию getHiddenCard(), которая принимает на вход номер кредитки (состоящий из 16 цифр) в виде строки и возвращает его скрытую версию. Если исходная карта имеет номер 2034399002125581, то скрытая версия выглядит ****5581. Функция заменяет первые 12 символов на звездочки. Количество звездочек регулируется вторым необязательным параметром. Значение по умолчанию — 4. getHiddenCard("1234567812345678",2) // "**5678" getHiddenCard("1234567812345678", 3) // "***5678" getHiddenCard('1234567812345678') // "****5678" getHiddenCard('2034399002121100', 1) // "*1100" Для выполнения задания рекомендуется использовать метод строки repeat, который повторяет строку указанное количество раз "+".repeat(5); // "+++++" "o".repeat(5); // "ooooo" Задание 36. 7 Существует потрясающее видео, где парень взломал несколько лампочек, управляемых Wi-Fi, пролетев мимо них на дроне. Воссоздадим этот трюк... в некотором роде. Даны две строки: lamps и drone. Строка lamps представляют собой ряд выключенных ламп, каждая из которых обозначена символом "x". Когда лампы включены, они должны быть обозначены символом "o". Строка беспилотника drone представляет положение беспилотника T и траекторию его полета до этой точки. Беспилотник всегда летит слева направо и всегда начинает с начала ряда ламп. В любом месте, где пролетел беспилотник, включая его текущее положение, лампа включится. Напишите функцию, возвращающую результирующую строку ламп. function flyBy(lamps, drone) { } flyBy('xxxxxx', '====T') // 'ooooox' flyBy('xxxxxxxxx', '==T') // 'oooxxxxxx' flyBy('xxxxxxxxxxxxxxx', '=========T') // 'ooooooooooxxxxx' Примечание: методы repeat, padStart. 237
Задание 37. 7 Обучение программированию захватывает всю вашу жизнь. Вы понимаете, что для того, чтобы быстро сделать важные шаги, было бы полезно посетить учебный лагерь по программированию в Лондоне. Проблема в том, что это стоит целое состояние, а у Вас есть ипотека. Чтобы компенсировать риски, вы решаете, что вместо того, чтобы полностью уйти с работы, вы запросите академический отпуск, чтобы вы могли вернуться к работе после учебного лагеря и получать зарплату, пока будете искать свою следующую должность. Вам нужно обратиться к своему начальнику. Ее решение будет основываться на трех параметрах. 1. val — ваша ценность для организации; 2. happiness — уровень счастья на момент запроса; 3. Количество букв из "sabbatical", которые присутствуют в строке s. Обратите внимание, что если s содержит три экземпляра буквы "l", это дает три балла, даже если в слове sabbatical есть только одна буква "l". Если сумма трех параметров больше 22, функция вернет "Sabbatical! Boom!'", в противном случае вернет "Back to your desk, boy.'. function sabb(s, val, happiness) { } sabb('Can I have a sabbatical?', 5, 5) // 'Sabbatical! Boom!' sabb('Why are you shouting?', 7, 2) // 'Back to your desk, boy.' sabb('What do you mean I cant learn to code??', 8, 9) // 'Sabbatical! Boom!' 238
Задание 38. 8 Числа, заканчивающиеся нулями, скучны. Они могут быть забавными в обыденном мире, но не здесь. Необходимо избавиться от них, но только от тех, которыми заканчивается данное число. function noBoringZeros(n) { } noBoringZeros(1450) // 145 noBoringZeros(960000) // 96 noBoringZeros(1050) // 105 noBoringZeros(0) // 0 Примечание: метод endsWith Задание 39. Напишите функцию filter-black-list(), которая возвращает массив emailадресов, не попавших в черный список. В качестве аргументов функция принимает массив строк с исходными email адресами и массив строк с email адресами из черного списка. function filter-black-list (emails, blacks) { } Задание 40. 7 Учитывая строку и массив индексов, переставьте символы строки так, чтобы каждый символ оказался на позиции, указанной соответствующим индексом в массиве. function scramble(str, arr) { } scramble ('abcd', [0,3,1,2]) // 'acdb' scramble ('sc301s', [4,0,3,1,5,2]) // "c0s3s1" 239
scramble ('bskl5', [2,1,4,3,0] // "5sblk" Задача на пустые элементы массива! Задание 41. 7 Дополните решение так, чтобы оно возвращало отформатированную строку. Возвращаемое значение должно быть равно «Значение — ЗНАЧЕНИЕ», где значение — это дополненное 5-значное число. function solution(value){ } solution(5) // "Value is 00005" solution(1204) // "Value is 01204" solution(109) // "Value is 00109" solution(0) // "Value is 00000" Примечание: метод padStart Задание 42. 7 Создайте функцию, которая принимает одну произвольную строку в качестве аргумента и возвращает строку длиной 26. Цель состоит в том, чтобы установить каждый из 26 символов выходной строки в одно из следующих значений: '1' или '0' на основе того, присутствует ли во входных данных N-я буква алфавита (независимо от ее регистра). Так что если 'a' или 'A' появляется в любом месте входной строки (любое количество раз), установите первый символ выходной строки в '1', в противном случае '0'. если 'b' или 'B' появляется в строке, установите второй символ на '1' и так далее для остальной части алфавита. function change(string) { } change("a **& bZ") // "11000000000000000000000001" 240
Задание 43. 8 Дана строка произвольной длины, содержащая любые символы ASCII. Напишите функцию, которая определяет, содержит ли строка слово «English» целиком. Порядок символов важен — строка «abcEnglishdef» является правильной, а «abcnEglishsef» — неправильной. Заглавные или строчные буквы не имеют значения — «eNglisH» тоже правильно. Возвращаемое значение должно быть в виде логического значения: true, если строка содержит «English», false — если не содержит. function spEng(sentence){ } spEng("english") // true spEng("egnlish") // false Примечание: метод includes Дополнительные задачи в онлайн тренажере codeWars 1. 2. 3. 4. 5. 6. 7. Number of Decimal Digits 7 Remove duplicate words 7 Alternate capitalization 7 Cat and Mouse - Easy Version 7 String Merge! 7 By 3, or not by 3? That is the question . . . Remove String Spaces 8 241
Практическая работа на вложенный цикл Задание 1. 7 Цветной треугольник создается из ряда цветов, каждый из которых может быть красным, зеленым или синим. Последовательные строки, каждая из которых содержит на один цвет меньше, чем предыдущая, генерируются с учетом двух соприкасающихся цветов в предыдущей строке. Если эти цвета идентичны, то в новой строке используется тот же цвет. Если они отличаются, то в новой строке используется отсутствующий цвет. Это продолжается до тех пор, пока не будет сгенерирована последняя строка, содержащая только один цвет. G G G B G R R G B B R G R R G B R G B B R B R G B R B G G B R G G G R G B G B B R R B G R R B G Дана первая строка треугольника в виде строки, и задача — написать функцию, возвращающую окончательный цвет, который будет отображаться в нижней строке в виде строки. Строка ввода будет содержать только заглавные буквы R, G, B, и в ней будет по крайней мере одна буква. Если задан только один цвет в качестве входных данных, то функция должна вернуть этот цвет. function triangle(row) { } triangle('GB') // 'R' triangle('RRR') //'R' triangle('RBRGBRBGGRRRBGBBBGG') // 'G' 242
Задание 2. 7 Вы получаете название города в виде строки, и вам нужно вернуть строку, которая показывает, сколько раз каждая буква встречается в строке, используя звездочки (*). Например: "Chicago" // "c:**,h:*,i:*,a:*,g:*,o:*" Как вы можете видеть, буква “c” отображается только один раз, но с двумя звездочками. Возвращаемая строка должна содержать только буквы (без дефисов, пробелов, апострофов и т. д.). В выводе не должно быть пробелов, а все буквы разделяются запятой (,), как показано в примере выше. Обратите внимание, что возвращаемая строка должна содержать список букв в порядке их первого появления в исходной строке. function getStrings(city) { } getStrings("Chicago") // "c:**,h:*,i:*,a:*,g:*,o:*" getStrings("Bangkok") // "b:*,a:*,n:*,g:*,k:**,o:*" getStrings("Las Vegas") // "l:*,a:**,s:**,v:*,e:*,g:*" Задание 3. 7 Дана строка, состоящая из цифр 0–9. Напишите функцию, которая возвращает строку, в которой каждая цифра повторяется количество раз, равное ее значению. function explode(s) { } explode ("312") // "333122" explode ("102269") // "12222666666999999999" explode ("0") // "" 243
РЕГУЛЯРНЫЕ ВЫРАЖЕНИЯ Регулярное выражение — это еще один тип данных, являющийся маской для строковых данных. Оно задает структуру данных. Регулярное выражение задается между двумя косыми чертами / / и применяется к строке. Например, для проверки ввода адреса электронной почты регулярное выражение в простейшем случае может быть таким /@/. Регулярные выражения представлены в виде объектов RegExp (от англ. regular expression — регулярное выражение) и могут быть созданы динамически с помощью конструктора RegExp(). RegExp( [, ]), где  — строка или строковая переменная, являющаяся телом регулярного выражения;  — строка или строковая переменная, являющаяся флагом регулярного выражения. var  = new RegExp( [, ]). Например, конструктор RegExp (“JavaScript”) создает регулярное выражение /JavaScript/. Конструктор RegExp (“JavaScript”,”g”) создает регулярное выражение /JavaScript/g. Флаг регулярного выражения Значение i поиск, нечувствительный к регистру g глобальный поиск, то есть поиск всех соответствий m многострочный поиск Применить регулярное выражение к строке можно с помощью свойства test или match. 244
.test() .match(), где  — объект, дающий регулярное выражение,  — объект, возвращающий проверяемую строку. Свойство test возвращает логическое значение true или false в зависимости от того, содержит ли проверяемая строка  подстроку, соответствующую образцу . Свойство match дает саму подстроку или массив всех подстрок. Например, alert (/@/.test("an171@mail.ru")) str="d123hgfdhjk566hgh" console.log ( str.match(/[0-9]+/g)!=null ? +str.match(/[0-9]+/g).join(""): "no digits" ) // 123566 Метод replace заменяет дающую регулярным выражением подстроку заданным образцом. .replace(,), где  — это исходная текстовая строка,  — регулярное выражение,  — подстрока, которой заменяются части исходной строки в соответствии с регулярным выражением. 245
В качестве  может стоять функция, которая будет вызываться столько раз, сколько раз будут находиться совпадения. Результат вызова функции (ее возвращаемое значение) будет использоваться в качестве строки замены. Входной параметр функции — найденная подстрока. Данная конструкция может заменить оператор цикла для обработки строки. let text = “Mr Blue has a blue house and a blue car” console.log (text.replace(/blue|house|car/gi, function (x) { return x.toUpperCase() })) // Mr BLUE has a BLUE HOUSE and a BLUE CAR var s = "JavaScript исполняется браузером, поэтому JavaScript считается клиентской технологией"; var re = /JavaScript/g; console.log (s.replace(re, "JScript")); /* JScript исполняется браузером, поэтому JScript считается клиентской технологией */ В приведенном примере все вхождения слова JavaScript будут заменены на JScript. В регулярном выражении можно использовать не только обычные символы, но и символьные классы. Символьные классы в регулярных выражениях — это конструкции, которые задают набор символов, из которых должен быть выбран один для совпадения с позицией в строке. Они обозначаются квадратными скобками [] и позволяют компактно указать перечень символов или диапазонов символов, которые подходят для сопоставления. • • • [abc] соответствует одному символу, который может быть либо a, либо b, либо c; [a–z] соответствует любой строчной букве английского алфавита от a до z; [^0–9] соответствует любому символу, кроме цифр от 0 до 9, благодаря отрицанию ^ внутри квадратных скобок. Символьные классы позволяют гибко задавать шаблоны для поиска символов из определенных множеств, что часто используется для валидации, парсинга текста и поиска по шаблонам. Также для обозначения символьных классов существуют сокращенные метасимволы 246
• • • \d вместо [0–9] (цифра); \w вместо [A-Za-z0-9_] (буква, цифра или подчёркивание); \s (пробельный символ). Если часть регулярного выражения заключена в круглые скобки, то соответствующая ей подстрока будет запомнена для последующего использования. Для доступа к запомненным подстрокам используются свойства $1, … , $9 объекта RegExp. Например, var re = /([а-я]+)\s([а-я]+)/i; var s = "Ален Делон"; alert (s.replace(re, "$2 $1")); В приведенном примере порядок слов в исходной строке s изменен на обратный (Делон Ален). Комбинация [а-я] соответствует любой букве русского алфавита, символ + соответствует повторению предыдущего символа один или более раз. Комбинация \s соответствует символу пробела. Спецсимволы для построения регулярных выражений Символьный класс / обратный символьный класс Описание \d соответствует цифре. Эквивалентно [0–9]. (d от digital) \D соответствует нецифровому символу. Эквивалентно [^0-9] \w соответствует цифре, букве латинского алфавита или подчеркиванию (w от word). Эквивалентно /[A-Za-z0-9_]/ \W соответствует символам, отличным от цифр, букв латинского алфавита и подчеркивания соответствует любому одному символу, отличному от разделителя строки . function doubleChar(str) { return str.replace(/(.)/g, "$1$1") } var re = /.{2,}@.{2,}[.].{2,}/ var строка = "an171@rambler.ru" var проверка_строки = re.test(строка) // true 247
Продолжение табл. Символьный класс / обратный символьный класс Описание \s соответствует неотображаемым символам (которые разделяют данные на слова (пробел), абзацы, строки и т. д.) Эквивалентно /[ \f\n\r\t\v]/ \S соответствует отображаемым символам. Эквивалентно /[^ \f\n\r\t\v]/ [xyz] соответствует символам из заключенных в квадратные скобки [^xyz] cоответствует любому символу, кроме заключенных в квадратные скобки \b cоответствует началу или концу слова (искл. для кирилицы) \B cоответствует любому символу, кроме начала или конца слова (b от begin) ? cоответствует одному символу или указывает на отсутствие символа ([\( -]? соответствует наличию или отсутствию одного из символов, заключенных в квадратные скобки) * cоответствует нескольким символам или указывает на отсутствие символа + соответствует повторению предыдущего символа один или более раз {n} соответствует n вхождениям предыдущего символа {n,} соответствует n или более вхождениям предыдущего символа /x{1,}/ эквивалентно /x+/ /x{0,}/ эквивалентно /x*/ {n,m} соответствует не менее чем n и не более чем m вхождениям предыдущего символа /x{0,1}/ эквивалентно /x?/ ^ соответствует началу строки, а если внутри квадратных скобок, то логическое отрицание или исключающий диапазон (исключающие диапазоны начинаются с символа каретки и соответствуют любому символу кроме заданных в диапазоне) 248
Продолжение табл. Символьный класс / обратный символьный класс Описание x="HTML и JavaScript"; /^HTML/.test(x) // true x="JavaScript и HTML"; /^HTML/.test(x) // false txt="ivanov.sura.ru" txt.match(/([^.]+)/g) // ["ivanov", "sura", "ru"] txt="номер телефона 1234567" txt.match(/[^\D]+/) // ["1234567"] соответствует концу строки string.replace(/[!]$/,'') // удалить знак ! в конце строки $ x="HTML и JavaScript"; /HTML$/.test(x) // false x="JavaScript и HTML"; /HTML$/.test(x) // true [a-z] соответствует любому символу в указанном диапазоне (?=.*[a-z]) проверяемая строка содержит хотя бы одну латинскую букву в нижнем регистре, шаблон должен быть в самом начале регулярного выражения /^(\d{4}|\d{6})$/ 4 цифры или 6 цифр в исходной строке (?<=\.) просмотр назад или ретроспективный поиск после точки (?=XVI) просмотр вперед /Ludovic(?=XVI)/ Спецсимволы строки замены для вставки фрагментов совпадений Спецсимволы Описание $& вставляет все найденные совпадения $` вставляет часть строки до совпадения $’ вставляет часть строки после совпадения "Люблю HTML".replace(/HTML/,"$& и JavaScript") // Люблю HTML и JavaScript "Люблю HTML".replace(/HTML/,"$` и очень JavaScript") // Люблю Люблю и очень JavaScript "Люблю HTML и CSS".replace(/HTML/,"$' и очень JavaScript") // Люблю и CSS и очень JavaScript и CSS 249
В регулярных выражениях используется экранирование символов — это способ, с помощью которого специальные символы (метасимволы), имеющие особое значение в синтаксисе регулярных выражений, превращаются в обычные символы. Для экранирования используется обратный слеш \. Например, экранируем круглые скобки: txt="function zadacha()" console.log(txt.match(/\s.+\(\)/)) // [" zadacha()"] В квадратных скобках большинство спецсимволов не требуется экранировать, поскольку они теряют свой функционал. К ним относятся большинство специальных символов, включая точку ., плюс +, знак вопроса ?, круглые скобки (), фигурные скобки {}, вертикальную черту | и другие. Какие символы нужно экранировать в квадратных скобках: • • • • Закрывающую квадратную скобку ], если она должна восприниматься как символ, а не как конец класса символов (например, чтобы искать символ ], нужно писать $$). Обратный слеш \, потому что он сам служит для экранирования. Символ дефиса -, если он не используется для задания диапазона. Например, [-a] или [a-] — дефис в начале или в конце скобок считается символом и не требует экранирования, а в середине, если нужно воспринимать как символ, надо экранировать [\-]. Символ каретки ^, если он не стоит в самом начале списка символов. В начале [^...] каретка означает отрицание, а в любом другом месте — символ, который нужно экранировать. Квантификатор в регулярных выражениях — это специальный символ или конструкция, которая задает количество повторений предыдущего символа, группы символов или символьного класса. Он обозначает сколько раз должно встречаться указанное выражение для совпадения с текстом. Основные квантификаторы: • • ? — предыдущий элемент встречается 0 или 1 раз (опционально), — 0 и более раз, 250
• • • • + — 1 и более раз, {m} — ровно m раз, {m,n} — от m до n раз, {m,} — не менее m раз. Например, регулярное выражение a? найдет либо отсутствие буквы "a", либо одно ее вхождение, a* — любое количество букв "a" (включая 0), a+ — одну или более "a", a{2, 4} — от двух до четырех подряд идущих букв "a". Также существуют жадные и ленивые квантификаторы, где жадные (по умолчанию) пытаются захватить как можно больше символов, а ленивые (обозначаются добавлением ?) — как можно меньше. Скобочные группы — это части регулярного выражения, заключенные в круглые скобки (). Они служат для группировки символов или подвыражений, чтобы к ним можно было применить квантификатор, получить отдельный результат совпадения и использовать повторно. Основные свойства скобочных групп • • • • • • Группировка позволяет применять квантификаторы ко всей группе целиком. Например, (ma)+ соответствует ma, mama, mamama и так далее. Запоминание содержимого каждой скобочной группы. Его можно получить как отдельный результат поиска. Нумерация. Группы нумеруются слева направо по порядку открывающих скобок, начиная с 1. Обратные ссылки. Внутри регулярного выражения и в строке замены можно ссылаться на содержимое группы по её номеру (например, $1 или \1). Именованные группы. Можно дать группе имя, используя синтаксис (?<имя>...), чтобы потом обращаться к ней по имени (например, $<имя>). Не запоминающие группы. Если не нужно запоминать совпадение, можно использовать синтаксис (?:...). Такая группа служит только для группировки, но не сохраняет содержимое. const regex = /(go)+/ 'gogogo'.match(regex) // ['gogogo', 'go'] Метод exec сопоставляет строку с образцом, заданным регулярным выражением. Если не нашлись совпадения, то возвращается значение 251
null. В противном случае результатом является массив подстрок, соответствующих заданному шаблону. Первый элемент массива будет равен исходной строке удовлетворяющей образцу. .exec() Например, var re=/(\d+\s)([а-я]+\s)(\d+\s)/ var arr=re.exec("Выборы президента России состоялись 20 марта 2018 года") document.write("Дата выборов: ", arr[0], "<br>") document.write("День выборов: ", arr[1], "<br>") document.write("Месяц выборов: ", arr[2], "<br>") document.write("Год выборов: ", arr[3], "<br>") Результат работы скрипта: Дата выборов: 20 марта 2018 День выборов: 20 Месяц выборов: марта Год выборов: 2018 Регулярное выражение можно использовать в методе search объекта String. .search([]), где  — строка,  — регулярное выражение. В случае успешного нахождения образца  в строке  метод search() возвращает индекс первого совпадения с регулярным выражением внутри строки. В противном случае метод возвращает –1. var str="Hello World!" str.search(/world/i) // 6 str.search(/word/i) // -1 Регулярное выражение можно использовать в методе split, который конвертирует строку в массив. .split(), 252
где  — строка,  — регулярное выражение. Регулярное выражение разделителя. в этом методе играет роль символа- "5*x-7/y=9".split(/[-=]/) // [ "5*x", "7/y", "9" ] Пример1 Построение регулярного выражения — шаблона, проверяющего введенный текст на соответствие фамилии и инициалам. var re = /^[А-Я][а-я]+[ ][А-Я]\D[А-Я]\D$/ var строка = "Иванов А.И." var проверка_строки = re.test(строка) alert (проверка_строки) Пример2 Замена последовательности идущих подряд пробелов одним пробелом в строке. текст=” Здесь должен располагаться Ваш текст” текст=текст.replace(/ + /g," ") Пример3 Создадим регулярное выражение для проверки ввода телефонного номера во всевозможных вариантах 79261234567 7(926)1234567 +7 926 123 45 67 +7 926 123 4567 +7-926-123-45-67 +7-(926)-123-45-67 +7(926)-123-45-67 89261234567 8(926)123-45-67 8-926-123-45-67 let tel = "79261234567"; let regexp = /^\+?[78][\( -]?[\( -]?\d{3}[\) -]?[\) -]?\d{3}[ -]?\d{2}[ ]?\d{2}$/; document.write(tel.match(regexp)); 253
П р и м е р 4. просмотр назад или ретроспективный поиск str="vbnvbnv. dfsvsdvsf.vwefw wfew. wefew" rez=str.replace(/(?<=\.) [a-z]|(?<=\.)[a-z]/g, function (x, i, s) { // console.log(x, i, s[i+1]); t = x.length==2 ? x.slice(0,1)+x.slice(-1).toUpperCase() : x.toUpperCase() return t }); console.log(rez) // "vbnvbnv. Dfsvsdvsf.Vwefw wfew. Wefew" Интерактивный тренажер. https://regexone.com/ Практическая работа на RegExp Задание 1. 8 Управляющий решил сэкономить деньги, купив недорогое программное обеспечение для оптического распознавания символов для сканирования текста старых романов. Сначала кажется, что сканер хорошо распознает слова, но при внимательном рассмотрении выясняется, что он вводит много чисел в случайных местах текста. Напишите функцию, которая примет строку и очистит все числовые символы в ней. function stringClean(s) { } stringClean("") // "" stringClean("123456789") // "" stringClean("(E3at m2e2!!)") // "(Eat me!!)" stringClean("Dsa32 cdsc34232 csa!!! 1I 4Am cool!") // "Dsa cdsc csa!!! I Am cool!" 254
Задание 2. 7 Дана строка, задача состоит в том, чтобы вернуть массив целых чисел, содержащий число прописных букв, строчных букв, цифр и специальных символов. function solve(s) { } solve("Codewars@codewars123.com") // [1,18,3,2] solve("bgA5<1d-tOwUZTS8yQ") // [7,6,3,2] solve("P*K4%>mQUDaG$h=cx2?.Czt7!Zn16p@5H") // [9,9,6,9] Задание 3. Дана строка слов. Напишите функцию, возвращающую такую же строку, но преобразовав каждое слово с большой буквы. Задание 4. 6 Напишите функцию так, чтобы она преобразовала слова, разделенные тире или подчеркиванием, в верблюжий регистр. Первое слово в выходных данных должно быть заглавным, только если исходное слово было заглавным (известно как Верхний регистр верблюда, также часто называемый регистром Паскаля). function toCamelCase(str){ } toCamelCase('') // '' toCamelCase("the_stealth_warrior") // "theStealthWarrior", toCamelCase("The-Stealth-Warrior") // "TheStealthWarrior" toCamelCase("A-B-C") // "ABC" 255
Задание 5. 8 Дезоксирибонуклеиновая кислота, ДНК, является основной молекулой для хранения информации в биологических системах. Она состоит из четырех оснований нуклеиновых кислот: гуанина ("G"), цитозина ("C"), аденина ("A") и тимина ("T"). Рибонуклеиновая кислота, РНК, является основной молекулоймессенджером в клетках. РНК незначительно отличается от ДНК своей химической структурой и не содержит тимина. В РНК тимин заменен другой нуклеиновой кислотой урацилом ("U"). Создайте функцию, которая преобразует заданную строку ДНК в РНК. function DNAtoRNA(dna) { } DNAtoRNA("TTTT") // "UUUU" DNAtoRNA("GCAT") // "GCAU" DNAtoRNA("GACCGCCGCC") // "GACCGCCGCC" Задание 6. 8 Напишите функцию, которая удалит восклицательный знак из конца входной строки, если он там находится и вернет преобразованную строку. Если в конце сроки нет восклицательного знака, то вернет исходную строку. function remove (string) { } remove ("Hi!") // "Hi" remove ("Hi!!!") // "Hi!!" remove ("Hi") // "Hi" 256
Задание 7. 8 Напишите функцию, которая по заданному имени и фамилии возвращает строку, в которой имя меняется местами с фамилией. function nameShuffler(str) { } nameShuffler('john McClane') // 'McClane john' Задание 8. 8 Напишите простое регулярное выражение для проверки имени пользователя. Разрешенными символами являются: строчные буквы, цифры, подчеркивание. Длина должна составлять от 4 до 16 символов включительно. function validateUsr(username) { } validateUsr('____'), true validateUsr('012'), false validateUsr('asd43 34'), false Задание 9. 7 Создайте функцию, которая будет возвращать количество гласных в заданной строке. Будем считать гласными буквы a, e, i, o, u. Входная строка будет состоять только из строчных букв и (или) пробелов. function getCount(str) { } getCount("abracadabra") // 5 257
Задание 10. 7 Дана строка, состоящая из нулей и единиц. Необходимо выбрать любые две смежные позиции в строке: если одна из них равна 0, а другая равна 1, то удаляем эти две цифры из строки. Составьте функцию, которая возвращает длину результирующей (наименьшей) строки, которую можно получить после многократного применения этой операции. После каждой операции оставшиеся цифры разделяются пробелами и, таким образом, больше не являются смежными. "01010" → " 010" → " 0" "110100" → "1 100" → "1 0" function zeroAndOne(s) { } zeroAndOne zeroAndOne zeroAndOne zeroAndOne zeroAndOne ("01010") // 1 ("11101111") // 6 ("01") // 0 ("110100") // 2 ("110110") // 2 Задание 11. 7 Дан начальный и конечный номер диапазона, функция должна вернуть количество всех чисел, кроме чисел с 5 в нем. Начальный и конечный номера указаны включительно! Результат может содержать пятерки. Начальный номер всегда меньше конечного. Оба числа могут быть отрицательными. function dontGiveMeFive(start, end) { } dontGiveMeFive(1,9) // 8 dontGiveMeFive(4,17) // 12 258
Задание 12. 7 Дана случайная строка, состоящая из цифр, букв и символов. Составьте функцию, которая вернет сумму чисел в строке. Последовательность цифр следует рассматривать как одно число. Например, “2015 год” следует рассматривать как число 2015. Все числа должны рассматриваться как целые положительные числа. Если в строке нет чисел, должен вернуться 0. function sumFromString(str) { } sumFromString ("In 2015, I want to know how much does iPhone 6+ cost?") // 2021 sumFromString("1+1=2") // 4 sumFromString("e=mc^2") // 2 Задание 13. 7 Банкоматы допускают 4-х или 6-ти значные PIN-коды. PIN-коды не могут содержать ничего, кроме 4 цифр или 6 цифр. Функции передана строка. Она должна вернуть true в случе PIN-кода, в противном случае false. function validatePIN (pin) { } validatePIN("1") // false validatePIN("12345") // false validatePIN("1234") // true validatePIN("a234") // false validatePIN("-1.234") // false 259
Задание 14. 7 О, нет! По сообщениям прессы призраки наводнили город. Ваша работа — избавиться от них и спасти положение! Строки представляют здания, пробелы внутри этих строк представляют призраков. Так чего же Вы ждете? Если в строке есть призраки, верните здание (строку) без каких-либо призраков (пробелов)! Если призраков в строке нет, верните фразу "You just wanted my autograph didn't you?" function ghostBusters(building) { } ghostBusters("Factor y") // "Factory" ghostBusters("O f fi ce") // "Office" ghostBusters("BusStation") // "You just wanted my autograph didn't you?" Задание 15. 8 Предоставленный код должен заменить все точки “.” в заданной строке str на тире “-“. Но это не работает должным образом. Задача — исправить ошибку, чтобы мы все могли пораньше разойтись по домам. var replaceDots = function(str) { return str.replace(/./, '-'); } replaceDots("one.two.three") // "one-two-three" Задание 16. 8 Известно, что число 42 — это «ответ на жизнь, вселенную и все остальное», согласно книге Дугласа Адамса «Путеводитель автостопом по Галактике». Для Фрейда ответ был совершенно иным... 260
В обществе, в котором он жил, людям приходилось подавлять свои сексуальные потребности и желания. Таково было общество в то время. Фрейд изучал болезни, вызванные этим фактом, и он докопался до корня, что привело к появлению некоторых самых важных психоаналитических теорий на сегодняшний день. Фрейд является отцом психоанализа. Когда человек слышит о Фрейде, он слышит «секс», потому что для Фрейда все было связано с сексом и объяснялось им. Создайте функцию, которая примет строку в качестве своего аргумента и вернет строку, в которой каждое слово заменено объяснением ко всему, согласно Фрейду. Обратите внимание, что пустая строка или отсутствие аргументов должны возвращать пустую строку. function toFreud(string) { } toFreud("") // "" toFreud("test") // "sex" toFreud("This is a test") // "sex sex sex sex" Задание 17. 8 Дана строка цифр. Напишите функцию, возвращающую строку с заменой любой цифры меньше 5 на "0", а любой цифры 5 и больше на "1". function fakeBin(x) { } fakeBin('45385593107843568') // '01011110001100111' fakeBin('509321967506747') // '101000111101101' fakeBin('366058562030849490134388085') // '011011110000101010000011011' 261
Задание 18. 7 Дана строка, которая может содержать смешанные прописные и строчные буквы. Задача состоит в том, чтобы преобразовать эту строку либо только в нижний регистр, либо только в верхний регистр так, чтобы внести как можно меньше изменений в строку. Если строка содержит равное количество прописных и строчных букв, преобразуйте строку в нижний регистр. function solve(s) { } solve("code") // "code" solve("CODe") // "CODE" solve("COde") // "code" Задание 19. 7 Пляжи полны песка, воды, рыбы и солнца. Если дана строка, подсчитайте, сколько раз в ней встречаются слова "Sand", "Water", "Fish" и "Sun", появляются без перекрытия (независимо от регистра). function sumOfABeach(beach) { } sumOfABeach ("SanD") // 1 sumOfABeach ("sunshine") // 1 sumOfABeach ("sunsunsunsun") // 4 sumOfABeach ("123FISH321") // 1 262
Задание 20. 7 Задача — написать простую функцию проверки пароля, подобную той, что используется на многих веб-сайтах. Правила для действительного пароля следующие. • • • • Должна быть хотя бы одна заглавная буква. Должна быть хотя бы одна строчная буква. Должно быть хотя бы 1 число. Пароль должен содержать не менее 8 символов. Функция принимает строковый аргумент и возвращает, является ли он допустимым паролем в виде логического значения. function password(str) { } password("Abcd1234") // true password("Abcd123") // false password("abcd1234") // false password("AbcdefGhijKlmnopQRsTuvwxyZ1234567890") // true Задание 21. 7 В этой задаче задана строка, состоящая из строчных букв и цифр. Необходимо сравнить группы чисел и найти наибольшее число. Числа не должны содержать начальных нулей. Например, solve("gh12cdy695m1") = 695, потому что это самая большая из всех числовых группировок. function solve(s) { } solve('gh12cdy695m1') // 695 solve('2ti9iei7qhr5') // 9 solve('vih61w8oohj5') // 61 263
Практическая работа на replace с колбэк функцией Задание 1. 8 Удалите n восклицательных знаков в предложении слева направо. n — положительное целое число. function remove(s,n) { } remove("Hi!",1) // "Hi" remove("Hi!",100) // "Hi" remove("Hi!!!",1) // "Hi!!" Задание 2. 7 Дана строка, состоящая из букв a, b и/или c. Составьте функцию, которая поменяет буквы a на b и наоборот. Оставьте любое значение c нетронутым. 'acb' --> 'bca' 'aabacbaa' --> 'bbabcabb' function switcheroo(x) { } switcheroo('abc') // 'bac' switcheroo('aaabcccbaaa') // 'bbbacccabbb' switcheroo('ccccc') // 'ccccc' Задание 3. 7 264
Вы прибыли на охоту на уток. Вам будет выдано определенное количество боеприпасов и оценка прицела от 1 до 0, так как прицел не всегда идеальный. Напишите функцию, которая будет подсчитывать, сколько успешных выстрелов можно сделать, учитывая доступные боеприпасы и прицельный балл, и возвращать строку, представляющую пул уток. Те утки в пуле, которые были застрелены, отмечены "X", а те, которые выжили, остались неизменными. Вы всегда будете стрелять слева направо. function duckShoot(ammo, aim, ducks) { } duckShoot(4, 0.64, '|~~2~~~22~2~~22~2~~~~2~~~|') // '|~~X~~~X2~2~~22~2~~~~2~~~|' duckShoot(9, 0.22, '|~~~~~~~2~2~~~|') // '|~~~~~~~X~2~~~|' duckShoot(6, 0.41, '|~~~~~22~2~~~~~|') // '|~~~~~XX~2~~~~~|' Примечание. Используйте метод replace с функцией в качестве второго параметра. Задание 4. 8 Дана строка цифр. Напишите функцию, возвращающую строку с заменой любой цифры меньше 5 на "0", а любой цифры 5 и больше на "1". function fakeBin(x) { } fakeBin('45385593107843568') // '01011110001100111' fakeBin('509321967506747') // '101000111101101' fakeBin('366058562030849490134388085') // '011011110000101010000011011' 265
МНОЖЕСТВА JavaScript поддерживает такую структуру данных, как множество (set), которое представляет собой совокупность уникальных (неповторяющихся) значений. Множество — это коллекция уникальных значений В JavaScript для работы со множествами встроен объект Set, поэтому создать множество можно через конструктор этого объекта. let  = new Set([]), где  — имя переменной,  — имя массива let mySet = new Set() Удобно создать множество из имеющегося массива. const numarr = [1, 1, 2, 3, 4, 5, 2, 4] const numSet = new Set(numarr) console.log(numSet) // {1, 2, 3, 4, 5} В примере выше множество создается из массива. Так как множество может хранить только уникальные значения, то при его создании повторяющиеся элементы массива не включаются во множество. Новое множество можно создать из имеющегося множества, получив тем самым копию множества (дубликат). const set = new Set([4, 7, 5, 7]) // {4, 7, 5} const copySet = new Set(set) // {4, 7, 5} 266
Метод или свойство .size Параметры Действие  — имя множества возвращает число элементов множества numSet.size // 5 .add()  — имя множества,  — элемент добавляет элемент в конец множества const numbers = new Set() numbers.add(2) numbers.add(4) numbers.add(6) console.log(numbers) // {2, 4, 6} .delete()  — имя множества,  — элемент удаляет элемент из множества и возвращает булево значение true в случае, если элемент удален и false — если удаление не произошло let numbers = new Set(); numbers.add(1).add(3).add(5); // {1, 3, 5} numbers.delete(3); // true numbers.forEach (el => console.log(el) ); // {1, 5} .clear()  — имя множества удаляет все элементы из множества numbers.clear(); // { } .has()  — имя множества,  — элемент n = new Set ([1,2,3]) console.log(n.has(32)) // false 267 проверяет, есть ли элемент во множестве. Если элемент есть, то возвращает true, иначе false
Продолжение табл. Метод или свойство . forEach() Параметры  — имя множества,  — функция обратного вызова Действие перебирает элементы множества const numarr = [1, 1, 2, 3, 4, 5, 2, 4] const numSet = new Set(numarr) let newArr=[] numSet.forEach(el => newArr.push(el**2)) • console.log(newArr) // [1, 4, 9, 16, 25] .values()  — имя множества возвращает объект итератор (Set Iterator) со всеми значениями множества const letters = new Set(["j","a","v","a","s","c","i","p","t"]); let text = ""; for (const x of letters.values()) { text += x } console.log (text) // "javscipt" .keys()  — имя множества .entries()  — имя множества возвращает объект итератор (Set Iterator) со всеми значениями множества вместо ключей, так как у множества нет ключей возвращает пары [значение, значение] вместо пар [ключ, значение] const letters = new Set(["j","a","v","a","s","c","i","p","t"]); let text = ""; for (const x of letters.entries()) { text += x } • console.log (text) // "j,ja,av,vs,sc,ci,ip,pt,t" 268
Удаление из массива повторяющихся элементов const lang = ["Pascal", "Python", "Pascal", "JS", "PHP", "Perl", "JS"] const langSet = new Set(lang) const unicLang = Array.from(langSet) console.log(unicLang) // ["Pascal", "Python", "JS", "PHP", "Perl"] Практическая работа на множества Задание 1. 7 Дан массив цифр. Напишите функцию, возвращающую наименьшее число, которое можно образовать из этих цифр, используя цифры только один раз (игнорируйте дубликаты). function minValue(values) { } minValue([1, 3, 1]) // 13 minValue([4, 7, 5, 7]) // 457 minValue([4, 8, 1, 4]) // 148 Задание 2. 7 Множество позволяет хранить уникальные значения любого типа. Оно сопровождается некоторыми полезными методами, такими как .add, .clear, .has и так далее. Но некоторые операции отсутствуют, например, дополнение. Два множества могут быть «вычтены». Относительное дополнение B в A, обозначаемое A \ B (или A − B), представляет собой набор всех элементов, которые являются членами A, но не являются членами B. 269
{1, 2} \ {1, 2} =  {1, 2, 3, 4} \ {1, 3} = {2, 4} Создайте функцию diff, получающую 2 множества в качестве аргументов и возвращающую новое множество в результате относительного дополнения второго множества к первому. function diff(s1, s2) { } A = new Set([1,2]) B = new Set([2,3]) diff(A,B) // {1} diff(B,A) // {3} Задание 3. 7 Множество позволяет хранить уникальные значения любого типа. Оно сопровождается некоторыми полезными методами, такими как .add, .clear, .has и так далее. Но некоторые операции отсутствуют, например. объединение. Два множества могут быть сложены вместе. Объединение A и B, обозначаемое A ∪ B — это множество всех объектов, которые являются членами либо A, либо B. Создайте функцию union, получающую 2 множества в качестве аргументов и возвращающую новое множество в результате их объединения. {1, 2} ∪ {1, 2} = {1, 2} {1, 2} ∪ {2, 3} = {1, 2, 3}. {1, 2, 3} ∪ {3, 4, 5} = {1, 2, 3, 4, 5} 270
function union(s1, s2) { } A = new Set([1,2]) B = new Set([2,3]) C = union(A,B) // {1,2,3} Задание 4. 7 Множество позволяет хранить уникальные значения любого типа. Оно сопровождается некоторыми полезными методами, такими как .add, .clear, .has и так далее. Но некоторые операции отсутствуют, например, равенство. Два множества (A, B) считаются «равными», если все элементы A являются элементами B и все элементы B являются элементами A независимо от «порядка» элементов. {1, 2} == {2, 1} {1, 2} != {1, 2, 3} Создайте 2 функции, AreEqual и NotEqual, которые получают 2 множества в качестве аргументов и возвращают значение true или false в за- 271
висимости от того, являются ли эти 2 множества равными или не равными. function areEqual(s1, s2) { } function notEqual(s1, s2) { } A = new Set([1,2]) A2 = new Set([2,1]) B = new Set([2,3]) areEqual(A,B) // false areEqual(A,A2) // true notEqual(A,B) // true Задание 5. 7 Множество позволяет хранить уникальные значения любого типа. Оно сопровождается некоторыми полезными методами, такими как .add, .clear, .has и так далее. Но некоторые операции отсутствуют, например, симметричная разница. Симметричная разность является продолжением дополнения. Обозначается как Δb, это множество всех элементов A, которые не являются элементами B, и всех элементов B, которые не являются элементами A. {7,8,9,10} Δ {9,10,11,12} = {7,8,11,12}. Создайте функцию symDiff, получающую 2 множества в качестве аргументов и возвращающую новое множество в результате их симметричной разницы. 272
function symDiff(s1, s2) { } A = new Set([1,2,3]) B = new Set([2,3,4]) symDiff(A,B) // {1,4} Задание 6. 7 Множество позволяет хранить уникальные значения любого типа. Оно сопровождается некоторыми полезными методами, такими как .add, .clear, .has и так далее. Но некоторые операции отсутствуют, например, пересечение. Новое множество может быть построено путем определения того, какие элементы двух множеств совпадают. Пересечение A и B, обозначаемое A ∩ B — это множество всех объектов, которые являются членами как A, так и B. Если A ∩ B = ∅, то A и B называются непересекающимися. {1, 2} ∩ {1, 2} = {1, 2} {1, 2} ∩ {2, 3} = {2} Создайте функцию inter, получающую 2 множества в качестве аргументов и возвращающую новое множество в результате их пересечения. function inter(s1, s2) { } A = new Set([1,2]) B = new Set([2,3]) C = inter(A,B) // {2} 273
Задание 7. 7 Дан массив из n целых чисел, найти максимальную триплетную сумму в массиве без дупликаций. [3,2,6,8,2,3] => [3,2,6,8] => [3,6,8] => 17 [-7,12,-7,29,-5,0,-7,0,0,29] => [-7,12,29,-5,0] => [0,12,29] => 41 function maxTriSum(numbers) { } maxTriSum([2,9,13,10,5,2,9,5]) // 32 maxTriSum( [-3,-27,-4,-2,-27,-2]) // -9 maxTriSum([-2,-4,0,-9,2]) // 0 Задание 8. 6 Создайте функцию unique_in_order, которая принимает в качестве аргумента отсортированную последовательность элементов и возвращает массив элементов последовательности без элементов с одинаковым значением, стоящих рядом друг с другом, с сохранением исходного порядка элементов. uniqueInOrder('AAAABBBCCDAABBB') // ['A', 'B', 'C', 'D', 'A', 'B'] uniqueInOrder('ABBCcAD') // ['A', 'B', 'C', 'c', 'A', 'D'] uniqueInOrder([1,2,2,3,3]) // [1,2,3] var uniqueInOrder=function(iterable) { } uniqueInOrder('AAAABBBCCDAABBB') // ['A','B','C','D','A','B'] 274
Задание 9. 8 Даны два отсортированных массива, оба из которых содержат только целые числа. Задача – найти способ объединить их в один отсортированный в порядке возрастания массив. Напишите функцию mergeArrays(arr1, arr2), где arr1 и arr2 – исходные отсортированные массивы. Если arr1 и arr2 пусты, то просто верните пустой массив. Массивы arr1 и arr2 могут быть отсортированы в разном порядке. Также arr1 и arr2 могут иметь одинаковые целые числа. В этом случае удалите дубликаты в возвращаемом результате. function mergeArrays(arr1, arr2) { } mergeArrays([1,2,3,4], [5,6,7,8]) // [1,2,3,4,5,6,7,8] mergeArrays([1,3,5,7,9], [10,8,6,4,2]) // [1,2,3,4,5,6,7,8,9,10] mergeArrays([1,3,5,7,9,11,12], [1,2,3,4,5,10,12]) // [1,2,3,4,5,7,9,10,11,12] Задание 10. 7 Напишите код функции, которая возвращает первый неповторяющийся символ в данной строке. Если все символы уникальны, верните первый символ строки. Если уникального символа нет, верните значение null. function firstNonRepeated(s) { } firstNonRepeated("test") // 'e' firstNonRepeated("teeter") // 'r' firstNonRepeated("1122321235121222") // '5' 275
ОБЪЕКТЫ РАЗРАБОТЧИКА Объект разработчика в JavaScript это еще один тип данных, который хранит совокупность свойств и методов какой-то сущности. Совокупность свойств и методов заключаются в фигурные скобки. Свойство объекта — это пара «ключ: значение», где ключ — строка (также называемая «именем свойства») или специальный тип данных символ, а значение может быть любым поддерживаемым js значением. var  = new Object(); var  = {}, где  — имя переменной,  — описание свойств и методов объекта. const car1 = { brand: “VW”, color: “red”, model: “golf”, horsepower: 100 } Для объектов доступны следующие операторы и методы объекта Object Метод Параметры Действие Object.assign(, β, …)  — целевой объект β — исходные объекты возвращает целевой объект после копирования значений всех свойств из всех исходных объектов .hasOwnProperty(β)  — имя объекта β — ключ возвращает логическое значение, указывающее, содержит ли объект указанный ключ 276
Продолжение табл. Метод Параметры Действие Object.is(, β) , β — значения возвращает логическое значение, указывающее, являются ли два аргумента одним и тем же значением Object.keys()  — имя объекта разработчика возвращает массив ключей Object.values()  — имя объекта разработчика возвращает массив значений Object.entries()  — имя объекта разработчика возвращает массив массив пар [ключ, значение]  — имя массива возвращает объект с ключами и их значениями согласно данным массива. Каждый элемент массива должен быть массивом из двух элементов, которые и преобразуются в пару ключ-значение Object.fromEntries() const names = [ ['name', 'Федор'], ['age', 16], ['city', 'Москва'], ] Object.fromEntries(names) // { name: 'Федор', age: 16, city: 'Москва' } names.map(el => Object.fromEntries([el])) // [ {name: 'Федор'}, {age: 16}, {city: 'Москва'} ] 277
Продолжение табл. Метод delete o. .call(β) Параметры Действие  — ключ o — имя объекта удаляет свойство из объекта  — функция-метод, β — объект вызывает метод (любую функцию) с разными объектами (все функции JS являются методами) если функция не является методом объекта JavaScript, она является функцией глобального объекта window function greet() { console.log(`Hello, ${this.name}!`); } const person = { name: 'John' }; greet.call(person); // Hello, John! .bind(β)  — функция-метод, β — объект возвращает новую функцию function greet() { console.log(`Hello, ${this.name}!`); } const greetJohn = greet.bind({ name: 'John' }); greetJohn(); // Hello, John! вызывает метод с разными объектами .apply(β)  — функция-метод, β — объект метод call() принимает аргументы отдельно метод apply() принимает аргументы в виде массива const person = { fullName: function(city, country) { return this.firstName + " " + this.lastName + "," + city + "," + country; } } person.fullName.apply(person1, ["Oslo", "Norway"]); person.fullName.call(person1, "Oslo", "Norway"); 278
Для проверки существования свойства (ключа) в объекте существует оператор in, возвращающий булево значение.  in , где  — свойство,  — объект. Существует вариант цикла for для перебора всех свойств объекта. for (var  in ) {  }, где  — имя переменной, пробегающей все свойства объекта;  — имя объекта;  — тело цикла, содержащее команды JavaScript. Пример for (var ключ in obj) { console.log (ключ, obj[ключ]) } П р и м е р 1. Объект student let student = { name: "Иван", surname: "Иванов", birth: "12-12-1965", year_of_admission: 2019, specialization: "математика", level: "бакалавр", dormitory: false, session: [4,5,4,4,5], card: function() { return (this.name + ' ' + this.surname[0] + '. ' + this.birth + ' года рождения.') // метод } } console.log(student.card()) // Иванов И. 12-12-1965 года рождения. arr=Object.entries(student) // [ 279
["name", "Иван"], ["surname", "Иванов"], ["birth", "12-12-1965"], ["year_of_admission", 2019], ["specialization", "математика"], ["level", "бакалавр"], ["dormitory", false], ["session", [4, 5, 4, 4, 5]], ["card", function() { return (this.name + ' ' + this.surname[0] + '. ' + this.birth + ' года рождения.') // метод }] ] fun=arr.slice(-1)[0][1] // function() { return (this.name + ' ' + this.surname[0] + '. ' + this.birth + ' года рождения.') // метод } console.log(fun.call(student)) // "Иван И. 12-12-1965 года рождения." П р и м е р 2. Калькулятор let calc = { a: 0, b: 0, inputValue: function (a, b) { this.a = a this.b = b }, add: function () { return (this.a + this.b) } } calc.add() // 0 calc.inputValue(5, 2) calc.add() // 7 П р и м е р 3. Массив объектов const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, 280
{ name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ] const fullAge = persons.filter(person => person.age >= 18); console.log(fullAge) // [ { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Tony', age: 24} ] П р и м е р 4. Зарплата Дан объект, в котором хранятся зарплаты сотрудников компании let John: Ann: Pete: month: currency: isPayed: } salaries = { 1000, 1600, 1300, 'December', 'USD', false Напишем функцию для суммирования всех зарплат. sumSalary(salaries); // 3900 Кроме зарплат, в объекте salaries хранится дополнительная информация: тип валюты (currency), выплачена зарплата или нет (isPayed). Значения в этих свойствах могут быть любого типа, кроме числового. Если в свойстве находится зарплата, то тип значения — число. Перед сложением зарплат следует исключить специальные числовые значения: NaN, Infinity, -Infinity. Если в объекте нет свойств, хранящих зарплаты, функция должна вернуть 0. function sumSalary(salaries) { let sum=0 for (x in salaries) { if (typeof (salaries[x])=='number' && (salaries[x])!=Infinity && (salaries[x])!=-Infinity && !isNaN(salaries[x])) 281
sum+=salaries[x] } return sum } console.log (sumSalary(salaries)); П р и м е р 5. Добавить новую пару ключ: значение в объект. Higher-Order Functions Series - Greet developers 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в совещании по программированию. Задача — вернуть массив, в котором каждый объект будет иметь новое свойство "greeting" со следующим строковым значением: “Hi <first Name>, what do you like the most about <language>?” var list1 = [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python' }, { firstName: 'Madison', 282
lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby' } ] Функция должна вернуть следующий массив объектов: [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java', greeting: 'Hi Sofia, what do you like the most about Java?' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python', greeting: 'Hi Lukas, what do you like the most about Python?' }, { firstName: 'Madison', lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby', greeting: 'Hi Madison, what do you like the most about Ruby?' } ] 283
function greetDevelopers(list) { for (x of list) { x["greeting"] = `Hi ${x.firstName}, what do you like the most about ${x.language}?` } return list } П р и м е р 6. Объект пустой? Создадим функцию isEmpty(obj), которая возвращает true, если в объекте нет свойств и false — если хоть одно свойство имеется. function isEmpty(obj) { for (x in obj) { return false } return true } let schedule = {}; alert( isEmpty(schedule) ); // true schedule["8:30"] = "подъём"; alert( isEmpty(schedule) ); // false П р и м е р 7. Фильтрация объектов Напишем функцию filter, фильтрующую массив объектов по значению свойства. Массив, название свойства и нужное значение передаются в качестве аргументов. let objects = [ { name: 'Василий', surname: 'Васильев' }, { name: 'Иван', surname: 'Иванов' }, { name: 'Пётр', surname: 'Петров' } ] let result = filter(objects, 'name', 'Иван') console.log(result) 284
/* [ { name: 'Иван', surname: 'Иванов' } ] */ let objects2 = [ { name: 'Василий', surname: 'Васильев' }, { name: 'Иван', surname: 'Иванов' }, { name: 'Пётр', surname: 'Петров' }, { name: 'Иван', surname: 'Сидоров' }, ] result = filter(objects, 'name', 'Иван') console.log(result) /* [ { name: 'Иван', surname: 'Иванов' }, { name: 'Иван', surname: 'Сидоров' } ] */ function filter(x,y,z) { let newFiltr=[]; for (o of x) { if (o[y]==z) newFiltr.push(o) } return newFiltr; } Тип данных Символ В качестве ключей для свойств объекта могут использоваться не только строки, но и символы. Символ представляет собой уникальный идентификатор. new Symbol(), 285
где  — описание идентификатора (имя), которое хранит свойство description let newKey = Symbol("key") console.log(newKey.description) // "key" Символ при в описании объекта необходимо заключить в квадратные скобки. let id = Symbol("id") let student = { [id]: “студент”, name: "Вася" } Cимволы не перебираются циклом for..in. Символы уникальны, даже если их имена совпадают. let key1 = Symbol("key") let key2 = Symbol("key") console.log(key1 == key2) // false В javascript существует глобальный реестр символов. В нем символы с одинаковыми именами являются равными. Для создания глобального символа реестра или его чтения используется конструкция Symbol.for(), где  — описание идентификатора (имя) let key1 = Symbol.for("key") let key2 = Symbol.for("key") console.log(key1 == key2) // true У объекта Symbol есть еще метод keyFor, который возвращает имя символа по его идентификатору Symbol.keyFor(), где  — символ. let key1 = Symbol.for("key") console.log(Symbol.keyFor(key1)) // key 286
Практическая работа на объекты Задание 1. 8 Директор по маркетингу некоторого стартапа сообщил маркетологам, что у его сайта большая аудитория в Скандинавии и соседних странах. Маркетинг считает, что нужно приветствовать посетителей сайта на их родном языке. Для этого можно использовать API, который определяет местоположение пользователя. Способ хранения языков — объект JS. english: 'Welcome', czech: 'Vitejte', danish: 'Velkomst', dutch: 'Welkom', estonian: 'Tere tulemast', finnish: 'Tervetuloa', flemish: 'Welgekomen', french: 'Bienvenue', german: 'Willkommen', irish: 'Failte', italian: 'Benvenuto', latvian: 'Gaidits', lithuanian: 'Laukiamas', polish: 'Witamy', spanish: 'Bienvenido', swedish: 'Valkommen', welsh: 'Croeso' Напишите функцию, которая принимает параметр language (строка) и возвращает приветствие — если оно есть в базе данных. Если заданного языка нет в базе данных или в случае неверного ввода приветствие должно быть английским. function greet(language) { } 287
greet('english') // 'Welcome' greet('dutch') // 'Welkom' greet('IP_ADDRESS_INVALID') // 'Welcome' Задание 2. Составьте функцию, подсчитывающую все одинаковые символы в строке и заносящую результат в объект. Если есть строка “aba”, то результатом должно быть {'a': 2, 'b': 1}. Если исходная строка пустая, то результатом должен быть пустой литерал объекта{}. Задание 3. 7 Имеется 8 шаров, пронумерованных от 0 до 7. Семь из них имеют одинаковый вес. Один тяжелее других. Задача — найти и вернуть его номер. Функция findBall получает единственный аргумент — объект scales (весы). Объект scales содержит массив из 8 элементов, каждый из которых имеет одинаковое значение, за исключением одного, который больше. Объект имеет метод getWeight (слева, справа), который принимает два массива индексов шаров и возвращает –1, 0 или 1 в зависимости от того, которая сторона тяжелее: –1, если левая сторона тяжелее 1 если правая сторона тяжелее 0, если вес обеих сторон одинаков scales.getWeight([3], [7]) возвращает: –1, если шар 3 тяжелее шара 7, 1, если шар 7 тяжелее, 0, если эти шары имеют одинаковый вес. scales.getWeight([3, 4], [5, 2]) возвращает –1, если вес шаров 3 и 4 тяжелее веса шаров 5 и 2 Весы очень старые. Их можно использовать только 3 раза, прежде чем шкала сломается. function findBall(scales) { } 288
Задание 4. 7 Дан массив чисел. Составьте функцию, которая для каждого числа в массиве создает объект. Ключом объекта является число, конвертируемое в строку. Значением является соответствующий код символа в виде строки. Функция должна возвращать массив результирующих объектов. function numObj(s) { } numObj([118,117,120]) // [{'118':'v'}, {'117':'u'}, {'120':'x'}] numObj([101,121,110,113,113,103]) // [{'101':'e'}, {'121':'y'}, {'110':'n'}, {'113':'q'}, {'113':'q'}, {'103':'g'}] Задание 5. 7 Джейден Смит, сын Уилла Смита, является звездой фильмов "The Karate Kid” (2010) и "After Earth" (2013). Джейден известен своей философией, которую он излагает через Х*. Когда он пишет в Х*, он всегда использует заглавные буквы в каждом слове. Напишите функцию, которая будет преобразовать строки так, как они были бы написаны Джейденом Смитом. Строки представляют собой настоящие цитаты из Джейдена Смита, но они написаны не с заглавной буквы так, как он их изначально набрал. String.prototype.toJadenCase = function () { } var str = "How can mirrors be real if our eyes aren't real"; str.toJadenCase() // "How Can Mirrors Be Real If Our Eyes Aren't Real" * Принадлежит Meta, деятельность которого признана экстремисткой и запрещена на территории РФ. 289
Задание 6. 6 Стиву и Джошу скучно, и они хотят во что-нибудь поиграть. Они не хотят слишком много думать, поэтому придумали простую игру. Раздается одинаковое количество карт. Оба игрока переворачивают карту сверху своей колоды. Тот, у кого карта более высокого достоинства, выигрывает раунд и получает одно очко (если карты одинакового достоинства, ни одна из них не получает очка). После этого две карты сбрасываются, и переворачиваются другие карты с верхней части колоды. Делается это до тех пор, пока не останется ни одной карты. Напишите функцию с именем winner и выясните, кто из них победит. deckSteve и deckJosh — массивы, представляющие колоды карт Стива и Джоша. Они заполнены карточками, представленными одним символом. Ранг карты выглядит следующим образом (от самого низкого к самому высокому): '2','3','4','5','6','7','8','9',' T', 'J', 'Q', 'K', 'A' Каждая карта может появиться в колоде более одного раза. Функция должна выяснить и вернуть, кто победит и с каким счетом: "Steve wins x to y", если Стив выигрывает, где x — счет Стива, y — счет Джоша.; "Josh wins x to y", если Джош выигрывает, где x — счет Джоша, y — счет Стива; "Tie", если в конце игры счет ничейный. function winner(deckSteve, deckJosh) { } winner(['A', '7', '8'], ['K', '5', '9']) // 'Steve wins 2 to 1' winner(['T', '9'], ['T', '8']) // 'Steve wins 1 to 0' winner(['T'], ['T']) // 'Tie' Примечание: используйте объект для представления ранга карт 290
Задание 7. 7 Напишите функцию для замены букв a-e-i-o-u-y на следующие A = Ä, E = Ë, I = Ï, O = Ö, U = Ü, Y = Ÿ, a = ä, e = ë, i = ï, o = ö, u = ü, y = ÿ function heavyMetalUmlauts(boringText) { } heavyMetalUmlauts("Announcing the "Ännöüncïng thë Mäcböök Äïr Güïtär" Macbook Air Guitar") // heavyMetalUmlauts("Facebook introduces new heavy metal reaction buttons") // "Fäcëböök ïntrödücës nëw hëävÿ mëtäl rëäctïön büttöns" heavyMetalUmlauts("Strong sales of Google's VR Metalheadsets send tech stock prices soaring") // "Ströng sälës öf Gööglë's VR Mëtälhëädsëts sënd tëch stöck prïcës söärïng" Примечание: используйте объект для представления соответствия букв и метод replace с регулярным выражением и стрелочной функцией. Задание 8. 8 Точечные объекты имеют атрибуты x и y. Напишите функцию, вычисляющую расстояние между точками a и b, находящимися на координатной плоскости. function distanceBetweenPoints(a, b) { } distanceBetweenPoints({x:3, y:3}, {x:3, y:3}) // 0 distanceBetweenPoints({x:1, y:6}, {x:4, y:2}) // 5 291
distanceBetweenPoints({x:-10.2, y:12.5}, {x:0.3, y:14.7}).toFixed(6) // 10.728001 Задание 9. 8 Программное обеспечение для распознавания символов широко используется для оцифровки печатных текстов. Таким образом, тексты можно редактировать, искать и сохранять на компьютере. Когда документы (особенно довольно старые, написанные на пишущей машинке) оцифровываются, программы распознавания символов часто допускают ошибки. Задача — исправить следующие ошибки в оцифрованном тексте: 5 на S, 0 на O, 1 на I. function correct(string) { } correct("L0ND0N") // "LONDON" correct("DUBL1N") // "DUBLIN" correct("51NGAP0RE") // "SINGAPORE" Задание 10. 7 Цвет играет важную роль в нашей жизни. Большинству из нас этот цвет нравится больше, чем другой. Специалисты по пользовательскому опыту считают, что определенные цвета имеют для нас определенное психологическое значение. Дан массив, в котором находятся массивы, состоящие из двух элементов: названия цвета и его ассоциации. Напишите функцию, которая будет возвращать цвет как ключ объекта, а ассоциацию как его значение. function colourAssociation(array) { } 292
colourAssociation([["white", "goodness"], [{white:"goodness"}, {blue:"tranquility"}] ["blue", "tranquility"]]) // colourAssociation([["red", "energy"], ["yellow", "creativity"], ["brown" , "friendly"], ["green", "growth"]]) // [{red: "energy"}, {yellow: "creativity"}, {brown: "friendly"}, {green: "growth"}] Задание 11. 7 Сложно отслеживать, кто и что должен, когда тратишь деньги в группе. Напишите функцию для балансировки бухгалтерских книг. Функция должна принимать один параметр: объект с двумя или более парами имя-значение, которые представляют членов группы и сумму, потраченную каждым из них. Функция должна возвращать объект с теми же именами, показывая, сколько денег участники должны заплатить или получить. Значения должны быть положительными числами, если человек должен получать деньги от группы, и отрицательными числами, если он должен деньги группе. Если значение является дробным, округлите его до двух знаков после запятой. Пример. 3 друга идут куда-нибудь вместе: A тратит 20 фунтов стерлингов, B тратит 15 фунтов стерлингов, а C тратит 10 фунтов стерлингов. Функция должна вернуть объект, показывающий, что A должен получить £ 5, B должен получить £ 0, а C должен заплатить £ 5. function splitTheBill(x) { } splitTheBill({A: 20, B: 15, C: 10}) // {A: 5, B: 0, C: -5} splitTheBill({A: 40, B: 25, X: 10}) // {A: 15, B: 0, X: -15} 293
Задание 12. 8 Напишете код для управления светофорами вашего города. Вам нужна функция для обработки каждого изменения сигнала сфетофора с зеленого на желтый, затем на красный, а затем снова на зеленый. Функция принимает строку в качестве аргумента, представляющего текущее состояние источника света, и возвращает строку, представляющую состояние, в которое должен перейти источник света. Например, когда входной сигнал зеленый, выходной сигнал должен быть желтым. function updateLight(current) { } updateLight("green") // "yellow" updateLight("yellow") // "red" updateLight("red") // "green" Задание 13. 7 На собрании команды ужасный человек заявляет группе, что Вы не работаете. Вы в беде. Вы должны быстро оценить обстановку в комнате, чтобы решить, следует ли вам собирать свои вещи и уходить.Учитывая объект (meet), содержащий имена членов команды в качестве ключей и их рейтинг счастья от 0 до 10 в качестве значения, необходимо написать код функции, которая оценит общий рейтинг счастья группы. Если он <= 5, то функция вернет 'Get Out Now!'. В противном случае 'Nice Work Champ!'. Рейтинг счастья равен общему баллу, разделенному на количество людей в комнате. Обратите внимание, что Ваш босс находится в комнате (boss). Его оценка стоит вдвое больше номинальной стоимости. function outed(meet, boss) { } 294
outed({'tim':0, 'jim':2, 'randy':0, 'sandy':7, 'andy':0, 'katie':5, 'laura':1, 'saajid':2, 'alex':3, 'john':2, 'mr':0}, 'laura') // 'Get Out Now!' outed({'tim':1, 'jim':3, 'randy':9, 'sandy':6, 'andy':7, 'katie':6, 'laura':9, 'saajid':9, 'alex':9, 'john':9, 'mr':8}, 'katie') // 'Nice Work Champ!' outed({'tim':2, 'jim':4, 'randy':0, 'sandy':5, 'andy':8, 'katie':6, 'laura':2, 'saajid':2, 'alex':3, 'john':2, 'mr':8}, 'john') // 'Get Out Now!' Задание 14. 7 Время от времени люди в офисе меняют команды или отделы. В зависимости от того, чем люди занимаются, со временем они могут стать более или менее скучными. Время оценить нынешнюю команду. Дан объект (staff), содержащий имена сотрудников в качестве ключей и отдел, в котором они работают, в качестве значений. Каждый отдел имеет разный балл оценки скуки accounts = 1 finance = 2 canteen = 10 regulation = 3 trading = 6 change = 6 IS = 8 retail = 5 cleaning = 4 pissing about = 25 Напишите код функции, которая в зависимости от совокупного балла команды, вернет соответствующее настроение <=80: 'kill me now' < 100 и > 80: 'i can handle this' 100 or over: 'party time!!' function boredom(staff) { } 295
boredom({tim: 'change', jim: 'accounts', randy: 'canteen', sandy: 'change', andy: 'change', katie: 'IS', laura: 'change', saajid: 'IS', alex: 'trading', john: 'accounts', mr: 'finance' }) // 'kill me now' boredom({ tim: 'IS', jim: 'finance', randy: 'pissing about', sandy: 'cleaning', andy: 'cleaning', katie: 'cleaning', laura: 'pissing about', saajid: 'regulation', alex: 'regulation', john: 'accounts', mr: 'canteen' }) // 'i can handle this' boredom({ tim: 'accounts', jim: 'accounts', randy: 'pissing about', sandy: 'finance', andy: 'change', katie: 'IS', laura: 'IS', saajid: 'canteen', alex: 'pissing about', john: 'retail', mr: 'pissing about' }) // 'party time!!' Задание 15. 7 Идет война алфавитов! Есть две группы враждебных символов. Напряжение между левыми и правыми буквами было слишком велико, и началась война. Напишите функцию, которая принимает строку боя, состоящую только из маленьких букв, и возвращает, кто выиграл бой. Когда побеждает левая сторона “Left side wins!”, когда побеждает правая сторона, возвращается “Right side wins!”, в противном случае возвращается “Let's fight again!”. Левые буквы и их сила Правые буквы и их сила w—4 m—4 p—3 q—3 b—2 d—2 s—1 z—1 Остальные буквы не имеют силы и являются только жертвами. function alphabetWar(fight) { } alphabetWar("z") // "Right side wins!" 296
alphabetWar("zdqmwpbs") // "Let's fight again!" alphabetWar("zzzzs") // "Right side wins!" Задание 16. Напишите код функции, которая принимает строку с числами и возвращает объект, содержащий минимальное и максимальное значения чисел из этой строки. Элементы в строке могут быть разделены только одним пробелом. При этом кроме чисел там могут быть слова и нечисловые символы (+, –, = и др). function person(str) { } const inputData = '1 и -5.8 или 10 хотя 34 + -5.3 и 73'; getMinMax(inputData)) // { min: -5.8, max: 73 } Задание 17. 7 Приближается новый сезон футбольной лиги, и Футбольной ассоциации нужна помощь в обновлении турнирной таблицы. Обычно первоначальный рейтинг лиги составляется в алфавитном порядке (от А до Я), но в этом году ФА решила его обновить. Было решено, что команда, финишировавшая первой в прошлом сезоне, начнет следующий сезон с первого места, независимо от того, с какой буквы начинается их клуб. Например если 'Manchester City' в прошлом году был на первом месте, то он начнет новый сезон с первой позиции. Все остальные команды должны располагаться в алфавитном порядке. Команды даны как объект ({}). Ключом является их позиция в прошлом сезоне, а значением название клуба. Выходными данными должен быть объект ({}) с ключом в качестве позиции клуба в новом сезоне, а значением должно быть название клуба. Например. В прошлом сезоне турнирная таблица была 1:'Leeds United' 2:'Liverpool' 3:'Manchester City' 297
4:'Coventry' 5:'Arsenal' Турнирная таблица нового сезона должна быть 1:'Leeds United' (first last season) 2:'Arsenal' (alphabetical) 3:'Coventry' (alphabetical) 4:'Liverpool' (alphabetical) 5:'Manchester City' (alphabetical) function premierLeagueStandings(teamStandings) { } premierLeagueStandings({1:'Arsenal'}) // {1:'Arsenal'} premierLeagueStandings({2:'Arsenal', 3:'Accrington Stanley', 1:'Leeds United'}) // {3:'Arsenal', 2:'Accrington Stanley', 1:'Leeds United'} premierLeagueStandings({1:'Leeds United', 2:'Liverpool', 3:'Manchester City', 4:'Coventry', 5:'Arsenal'}) // {1:'Leeds United', 2:'Arsenal', 3:'Coventry', 4:'Liverpool', 5:'Manchester City'} Задание 18. 7 До того, как я научился программировать, я много играл в FIFA. Это одна из многих вещей, на которые я потратил добрую часть жизни! И все же когда я увидел рекламу по телевизору, анонсирующую выход новой версии, я подумал, что она заслуживает ката в память о стольких счастливых часах. Вы сделали ставки на серию футбольных матчей. Ваш билет будет выглядеть примерно так: Home: £74 Away: £36 Draw: £5 Каждая линия — это отдельная ставка, представляющая собой пару «ключ: значение» в объекте билета. В каждом случае вы всегда будете ставить на победу хозяев, победу гостей и ничью. Вот такой ты странный. Каждая ставка делается на отдельную игру. 298
Вам также будет предоставлен массив (результатов). Например: [3-0, 1-1, 0-2] Количество результатов всегда будет равно количеству ставок в билете. В таблице результатов большее число слева от пары — победа хозяев, большее число справа — победа гостей, равное — ничья. Например: 3-0 = Home win 0-3 = Away win 3-3 = Draw Проверьте, совпадает ли результат в каждой строке вашего билета. Если да, вы выигрываете сумму, указанную в билете для этого совпадения. Например: Away: £20 Home: £10 Draw: £5 [1-0, 2-1, 0-1] Результат выигрыша равен 10 фунтов стерлингов (первая ставка проиграла, вторая ставка выиграла, третья ставка проиграла). Верните ваш общий выигрыш в виде строки со знаком £, например: «£100» function fifa(ticket, results) { } fifa({'Home':'£75', 'Away':'£5000', 'Draw':'£1324'}, ['1-0', '2-3', '01']) // '£5075' 299
Практическая работа на массивы объектов Задание 1. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции coding meetup. Задача функции, код которой нужно написать, вернуть количество разработчиков JavaScript, приезжающих из Европы. function countDevelopers(list) { } const list1 = [ { firstName: 'Noah', lastName: 'M.', country: 'Switzerland', continent: 'Europe', age: 19, language: 'JavaScript' }, { firstName: 'Maia', lastName: 'S.', country: 'Tahiti', continent: 'Oceania', age: 28, language: 'JavaScript' }, { firstName: 'Shufen', lastName: 'L.', country: 'Taiwan', continent: 'Asia', age: 35, language: 'HTML' }, { firstName: 'Sumayah', lastName: 'M.', country: 'Tajikistan', continent: 'Asia', age: 30, language: 'CSS' } ] countDevelopers(list1) // 1 const list2 = [ { firstName: 'Oliver', lastName: 'Q.', country: 'Australia', continent: 'Oceania', age: 19, language: 'HTML' }, { firstName: 'Lukas', lastName: 'R.', country: 'Austria', continent: 'Europe', age: 89, language: 'HTML' } ] countDevelopers(list2) // 0 300
Задание 2. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции coding meetup. Задача функции, код которой нужно написать, вернуть массив, в котором каждый объект будет иметь новое свойство greeting со следующим строковым значением: Hi < firstName here >, what do you like the most about < language here >? function greetDevelopers(list) { } const list1 = [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java', }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python', }, { firstName: 'Madison', lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby', }, ] greetDevelopers(list1) // [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java', greeting: 'Hi Sofia, what do you like the most about Java?', }, 301
{ firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python', greeting: 'Hi Lukas, what do you like the most about Python?', }, { firstName: 'Madison', lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby', greeting: 'Hi Madison, what do you like the most about Ruby?', }, ] Задание 3. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции coding meetup. Задача функции, код которой нужно написать, вернуть true, если хотя бы один Ruby-разработчик зарегистрировался или false, если разработчиков на Ruby не будет. function isRubyComing(list) { } var list1 = [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python' }, 302
{ firstName: 'Madison', lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby' } ] var list2 = [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python' } ] isRubyComing(list1) // true isRubyComing(list2) // false Задание 4. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Список упорядочен в соответствии с тем, кто зарегистрировался первым. Задача — вернуть первого зарегистрировавшегося разработчика на Python в формате: < Имя>, < страна>. Если ни один разработчик на Python не зарегистрировался, то вернуть строку 'There will be no Python developers' function getFirstPython(list) { } var list1 = [ { firstName: 'Mark', lastName: 'G.', country: 'Scotland', continent: 'Europe', age: 22, language: 'JavaScript' }, { firstName: 'Victoria', lastName: 'T.', country: 'Puerto Rico', continent: 'Americas', age: 30, language: 'Python' }, { firstName: 'Emma', lastName: 'B.', country: 'Norway', continent: 'Europe', age: 19, language: 'Clojure' } ]; var list2 = [ 303
{ firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 29, language: 'JavaScript' }, { firstName: 'Amar', lastName: 'V.', country: 'Bosnia and Herzegovina', continent: 'Europe', age: 32, language: 'Ruby' }, ]; getFirstPython(list1) // 'Victoria, Puerto Rico' getFirstPython(list2) // 'There will be no Python developers' Задание 5. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — вернуть объект, который включает количество языков программирования, представленных на встрече. Например, { C: 2, JavaScript: 1, Ruby: 1 } function countLanguages(list) { } var list1 = [ { firstName: 'Noah', lastName: 'M.', country: 'Switzerland', continent: 'Europe', age: 19, language: 'C' }, { firstName: 'Anna', lastName: 'R.', country: 'Liechtenstein', continent: 'Europe', age: 52, language: 'JavaScript' }, { firstName: 'Ramon', lastName: 'R.', country: 'Paraguay', continent: 'Americas', age: 29, language: 'Ruby' }, { firstName: 'George', lastName: 'B.', country: 'England', continent: 'Europe', age: 81, language: 'C' }, ]; countLanguages(list1) // { C: 2, JavaScript: 1, Ruby: 1 }; 304
Задание 6. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — вернуть true, если все разработчики в списке пишут код на одном языке или false в противном случае. function isSameLanguage(list) { } var list1 = [ { firstName: 'Daniel', lastName: 'J.', country: 'Aruba', continent: 'Americas', age: 42, language: 'JavaScript' }, { firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 22, language: 'JavaScript' }, { firstName: 'Hanna', lastName: 'L.', country: 'Hungary', continent: 'Europe', age: 65, language: 'JavaScript' }, ]; var list2 = [ { firstName: 'Mariami', lastName: 'G.', country: 'Georgia', continent: 'Europe', age: 29, language: 'Python' }, { firstName: 'Mia', lastName: 'H.', country: 'Germany', continent: 'Europe', age: 39, language: 'Ruby' }, { firstName: 'Maria', lastName: 'I.', country: 'Greece', continent: 'Europe', age: 32, language: 'C' }, ]; isSameLanguage(list1) // true isSameLanguage(list2) // false 305
Задание 7. 6 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — вернуть массив объектов, включающий разработчика, который является самым старшим. В случае если их окажется несколько человек, вернуть массив всех разработчиков того же возраста, перечисленных в том же порядке, в каком они появились в исходном массиве входных данных. function findSenior(list) { } let list1 = [ { firstName: 'Gabriel', lastName: 'X.', country: 'Monaco', continent: 'Europe', age: 49, language: 'PHP' }, { firstName: 'Odval', lastName: 'F.', country: 'Mongolia', continent: 'Asia', age: 38, language: 'Python' }, { firstName: 'Emilija', lastName: 'S.', country: 'Lithuania', continent: 'Europe', age: 19, language: 'Python' }, { firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 49, language: 'PHP' }, ] findSenior(list1) // [ { firstName: 'Gabriel', lastName: 'X.', country: 'Monaco', continent: 'Europe', age: 49, language: 'PHP' }, { firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 49, language: 'PHP' }, ] findSenior(list2) // [ { firstName: 'Gabriel', lastName: 'X.', country: 'Monaco', continent: 'Europe', age: 49, language: 'PHP' }, { firstName: 'Odval', lastName: 'F.', country: 'Mongolia', continent: 'Asia', age: 38, language: 'Python' }, 306
{ firstName: 'Emilija', lastName: 'S.', country: 'Lithuania', continent: 'Europe', age: 19, language: 'Python' }, ] Задание 8. 6 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — вернуть true, если все следующие континенты /географические зоны будут представлены хотя бы одним разработчиком: 'Africa', 'Americas', 'Asia', 'Europe', 'Oceania', в противном случае false. function allContinents(list) { } var list1 = [ { firstName: 'Fatima', lastName: 'A.', country: 'Algeria', continent: 'Africa', age: 25, language: 'JavaScript' }, { firstName: 'Agustín', lastName: 'M.', country: 'Chile', continent: 'Americas', age: 37, language: 'C' }, { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' }, { firstName: 'Laia', lastName: 'P.', country: 'Andorra', continent: 'Europe', age: 55, language: 'Ruby' }, { firstName: 'Oliver', lastName: 'Q.', country: 'Australia', continent: 'Oceania', age: 65, language: 'PHP' } ] var list2 = [ { firstName: 'Fatima', lastName: 'A.', country: 'Algeria', continent: 'Africa', age: 25, language: 'JavaScript' } ] allContinents(list1) // true allContinents(list2) // false 307
Задание 9. 6 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — вернуть true, если зарегистрировались разработчики из всех следующих возрастных групп: подростки, двадцатые, тридцатые, сороковые, пятидесятые, шестидесятые, семидесятые, восьмидесятые, девяностые, столетние (не менее 100 лет), в противном случае false. function isAgeDiverse(list) { } const list1 = [ { firstName: 'Harry', lastName: 'K.', country: 'Brazil', continent: 'Americas', age: 19, language: 'Python' }, { firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 29, language: 'JavaScript' }, { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 39, language: 'Ruby' }, { firstName: 'Noa', lastName: 'A.', country: 'Israel', continent: 'Asia', age: 40, language: 'Ruby' }, { firstName: 'Andrei', lastName: 'E.', country: 'Romania', continent: 'Europe', age: 59, language: 'C' }, { firstName: 'Maria', lastName: 'S.', country: 'Peru', continent: 'Americas', age: 60, language: 'C' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 75, language: 'Python' }, { firstName: 'Chloe', lastName: 'K.', country: 'Guernsey', continent: 'Europe', age: 88, language: 'Ruby' }, { firstName: 'Viktoria', lastName: 'W.', country: 'Bulgaria', continent: 'Europe', age: 98, language: 'PHP' }, { firstName: 'Piotr', lastName: 'B.', country: 'Poland', continent: 'Europe', age: 128, language: 'JavaScript' } ] const list2 = [ 308
{ firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 29, language: 'Ruby' }, { firstName: 'Amar', lastName: 'V.', country: 'Bosnia and Herzegovina', continent: 'Europe', age: 32, language: 'Ruby' }, ] const list3 = [ { firstName: 'Sofia', lastName: 'P.', country: 'Italy', continent: 'Europe', age: 41, language: 'Clojure' }, { firstName: 'Jayden', lastName: 'P.', country: 'Jamaica', continent: 'Americas', age: 42, language: 'JavaScript' }, { firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 43, language: 'Python' }, { firstName: 'Rimas', lastName: 'C.', country: 'Jordan', continent: 'Asia', age: 44, language: 'Java' } ] isAgeDiverse(list1) // true isAgeDiverse(list2) // false isAgeDiverse(list3) // false Задание 10. 6 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — напишите функцию, которая добавляет свойство username к каждому объекту во входном массиве. Значение свойства username составляется путем объединения имени в нижнем регистре, первой буквы фамилии в нижнем регистре и года рождения, который вычисляется путем вычитания возраста из текущего года. Пожалуйста, убедитесь, что функция выдает правильный год рождения, независимо от того, когда она будет выполнена, например, она также должна корректно работать для собрания, организованного через 10 лет. function addUsername(list) { } 309
var list1 = [ { firstName: 'Emily', lastName: 'N.', country: 'Ireland', continent: 'Europe', age: 30, language: 'Ruby' }, { firstName: 'Nor', lastName: 'E.', country: 'Malaysia', continent: 'Asia', age: 20, language: 'Clojure' } ] addUsername(list1) // [ { firstName: 'Emily', lastName: 'N.', country: 'Ireland', continent: 'Europe', age: 30, language: 'Ruby', username: 'emilyn1990' }, { firstName: 'Nor', lastName: 'E.', country: 'Malaysia', continent: 'Asia', age: 20, language: 'Clojure', username: 'nore2000' } ] Задание 11. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — напишите функцию, которая возвращает средний возраст разработчиков (округленный до ближайшего целого числа). function getAverageAge(list) { } var list1 = [ { firstName: 'Maria', lastName: 'Y.', country: 'Cyprus', continent: 'Europe', age: 30, language: 'Java' }, { firstName: 'Victoria', lastName: 'T.', country: 'Puerto Rico', continent: 'Americas', age: 70, language: 'Python' }, ] var list2 = [ { firstName: 'Noa', lastName: 'A.', country: 'Israel', continent: 'Asia', age: 20, language: 'Ruby' }, 310
{ firstName: 'Andrei', lastName: 'E.', country: 'Romania', continent: 'Europe', age: 21, language: 'C' }, ] getAverageAge(list1) // 50 getAverageAge(list2) // 21 Задание 12. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — напишите функцию, которая возвращает только администраторов GitHub разработчиков какого-либо языка программирования. function findAdmin(list, lang) { } var list1 = [ { firstName: 'Harry', lastName: 'K.', country: 'Brazil', continent: 'Americas', age: 22, language: 'JavaScript', githubAdmin: 'yes' }, { firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 49, language: 'Ruby', githubAdmin: 'no' }, { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 34, language: 'JavaScript', githubAdmin: 'yes' }, { firstName: 'Piotr', lastName: 'B.', country: 'Poland', continent: 'Europe', age: 128, language: 'JavaScript', githubAdmin: 'no' } ] findAdmin(list1, 'JavaScript') // [ { firstName: 'Harry', lastName: 'K.', country: 'Brazil', continent: 'Americas', age: 22, language: 'JavaScript', githubAdmin: 'yes' }, { firstName: 'Jing', lastName: 'X.', country: 'China', continent: 'Asia', age: 34, language: 'JavaScript', githubAdmin: 'yes' } ] findAdmin(list1, 'Ruby') // [] findAdmin(list1, 'Python') // [] 311
Задание 13. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Будут представлены три языка программирования: Python, Ruby и JavaScript. Задача — вернуть true, если участники представляют любой из трех языков программирования и их не более чем в 2 раза больше количества разработчиков, представляющих любой из оставшихся языков программирования или false в противном случае. function isLanguageDiverse(list) { } var list1 = [ { firstName: 'Daniel', lastName: 'J.', country: 'Aruba', continent: 'Americas', age: 42, language: 'Python' }, { firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 22, language: 'Ruby' }, { firstName: 'Sou', lastName: 'B.', country: 'Japan', continent: 'Asia', age: 43, language: 'Ruby' }, { firstName: 'Hanna', lastName: 'L.', country: 'Hungary', continent: 'Europe', age: 95, language: 'JavaScript' }, { firstName: 'Jayden', lastName: 'P.', country: 'Jamaica', continent: 'Americas', age: 18, language: 'JavaScript' }, { firstName: 'Joao', lastName: 'D.', country: 'Portugal', continent: 'Europe', age: 25, language: 'JavaScript' } ] var list2 = [ { firstName: 'Daniel', lastName: 'J.', country: 'Aruba', continent: 'Americas', age: 42, language: 'Python' }, 312
{ firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 22, language: 'Ruby' }, { firstName: 'Hanna', lastName: 'L.', country: 'Hungary', continent: 'Europe', age: 95, language: 'JavaScript' }, { firstName: 'Jayden', lastName: 'P.', country: 'Jamaica', continent: 'Americas', age: 18, language: 'JavaScript' }, { firstName: 'Joao', lastName: 'D.', country: 'Portugal', continent: 'Europe', age: 25, language: 'JavaScript' } ] var list3 = [ { firstName: 'Daniel', lastName: 'J.', country: 'Aruba', continent: 'Americas', age: 42, language: 'Python' }, { firstName: 'Kseniya', lastName: 'T.', country: 'Belarus', continent: 'Europe', age: 22, language: 'Ruby' }, { firstName: 'Jayden', lastName: 'P.', country: 'Jamaica', continent: 'Americas', age: 18, language: 'JavaScript' }, { firstName: 'Joao', lastName: 'D.', country: 'Portugal', continent: 'Europe', age: 25, language: 'JavaScript' } ] isLanguageDiverse(list1) // false isLanguageDiverse(list2) // false isLanguageDiverse(list3) // true Задание 14. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — вернуть объект, который включает количество вариантов питания, выбранных разработчиками в форме регистрации на конференцию. 313
function orderFood(list) { } var list1 = [ { firstName: 'Noah', lastName: 'M.', country: 'Switzerland', continent: 'Europe', age: 19, language: 'C', meal: 'vegetarian' }, { firstName: 'Anna', lastName: 'R.', country: 'Liechtenstein', continent: 'Europe', age: 52, language: 'JavaScript', meal: 'standard' }, { firstName: 'Ramona', lastName: 'R.', country: 'Paraguay', continent: 'Americas', age: 29, language: 'Ruby', meal: 'vegan' }, { firstName: 'George', lastName: 'B.', country: 'England', continent: 'Europe', age: 81, language: 'C', meal: 'vegetarian' }, ] orderFood(list1) // { vegetarian: 2, standard: 1, vegan: 1 } Задание 15. 6 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — написать функцию, которая возвращает только разработчиков, имена которых в ASCII-представлении при суммировании всех символов имени будут нечетным числом. Верните пустой массив, если нет разработчика с «нечетным» именем. Сумма ASCII кодов в 'Aba': 65 + 98 + 97 = 260 Сумма ASCII кодов в 'Abb': 65 + 98 + 98 = 261 function findOddNames(list) { } var list1 = [ 314
{ firstName: 'Aba', lastName: 'N.', country: 'Ghana', continent: 'Africa', age: 21, language: 'Python' }, { firstName: 'Abb', lastName: 'O.', country: 'Israel', continent: 'Asia', age: 39, language: 'Java' } ] findOddNames(list1) // [ { firstName: 'Abb', lastName: 'O.', country: 'Israel', continent: 'Asia', age: 39, language: 'Java' } ] Задание 16. 7 Дан массив объектов, представляющих данные о разработчиках, которые зарегистрировались для участия в конференции по кодированию, которую вы организуете. Задача — напишите функцию, которая добавляет свойство question к каждому объекту во входном массиве, где разработчик не предоставил соответствующих сведений. Значением свойства question должна быть следующая строка: Hi, could you please provide your <property name>. Функция возвращает только разработчиков с недостающими деталями. Функция возвращает пустой массив, если нет разработчика с недостающими сведениями. function askForMissingDetails(list) { } var list1 = [ { firstName: null, lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: null }, { firstName: 'Madison', lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby' } ] askForMissingDetails(list1) // [ { firstName: null, lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java', 315
question: 'Hi, could you please provide your firstName.' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: null, question: 'Hi, could you please provide your language.' } ] var list2 = [ { firstName: 'Sofia', lastName: 'I.', country: 'Argentina', continent: 'Americas', age: 35, language: 'Java' }, { firstName: 'Lukas', lastName: 'X.', country: 'Croatia', continent: 'Europe', age: 35, language: 'Python' }, { firstName: 'Madison', lastName: 'U.', country: 'United States', continent: 'Americas', age: 32, language: 'Ruby' } ] askForMissingDetails(list2) // [] 316
ДЕСТРУКТУРИЗАЦИЯ Деструктуризация данных состоит в том, чтобы распаковать перечисляемые (итерируемые) значения в отдельные переменные, при этом не изменяя само значение. Пример 1. Деструктуризация объекта const person = { firstName: "Иван", lastName: "Петров", age: 50 } // Destructuring let {firstName, lastName} = person console.log (firstName) // Иван console.log (lastName) // Петров Пример 2. Деструктуризация строки let name = "Зазеркалье"; // Destructuring let [a1, a2, a3, a4, a5] = name; console.log (a1) // З console.log (a2) // а console.log (a3) // з console.log (a4) // е console.log (a5) // р Пример 3. Деструктуризация массива const fruits = ["Банан", "Апельсин", "Яблоко", "Манго"] // Destructuring let [fruit1, fruit2] = fruits; console.log (fruit1) // Банан 317
console.log (fruit2) // Апельсин let [fruit3,,,fruit4] = fruits; console.log (fruit3) // Банан console.log (fruit4) // Манго let {[2]:fruit5 ,[1]:fruit6} = fruits console.log (fruit5) // Яблоко console.log (fruit6) // Апельсин const numbers = [10, 20, 30, 40, 50, 60, 70] // Destructuring const [a,b, ...rest] = numbers console.log (a) // 10 console.log (b) // 20 console.log (rest) // [30, 40, 50, 60, 70] 318
MAP В языке JavaScript есть еще тип данных Map, который представляет собой коллекцию пар «ключ-значение», в которой ключи могут быть любого типа, включая объекты. В отличие от обычных объектов, где ключами являются строки или символы, Map обеспечивает сохранение порядка добавления элементов. Он позволяет выполнять операции поиска, добавления и удаления элементов. Метод Параметры new Map() Действие создает коллекцию map.set(𝛼, β) 𝛼 − ключ, β −значение записывает по ключу 𝛼 значение β map.get(𝛼) 𝛼 − ключ возвращает значение по ключу или undefined, если ключ отсутствует map.has(𝛼) 𝛼 − ключ возвращает true, если ключ присутствует в коллекции, иначе false map.delete(𝛼) 𝛼 − ключ удаляет элемент (пару «ключ/значение») по ключ map.clear() очищает коллекцию от всех элементов map.size возвращает текущее количество элементов // Создание пустого Map const map1 = new Map() // Добавление ключей с помощью метода set 319
map1.set('name', 'Alice') // ключ — строка map1.set(1, 'one') // ключ — число map1.set(true, 'bool') // ключ — булево значение // Получение значения console.log(map1.get('name')) // 'Alice' // Проверка существования ключа console.log(map1.has(1)) // true // Удаление ключа map1.delete(true) // Итерация по Map for (const [key, value] of map1) { console.log(`${key} = ${value}`) } const obj = {a: 1, b: 2} const mapFromObj = new Map(Object.entries(obj)) const objFromMap = Object.fromEntries(mapFromObj) console.log(objFromMap) // {a: 1, b: 2} let recipeMap = new Map([ ["огурец", 500], ["помидор", 350], ["лук", 50] ]) const product1 = { id: 1, name: "coat", price: 100 } const product2 = { id: 2, name: "t-shirt", price: 50 } const productsMetaData = new Map() productsMetaData.set(product1, { creator: "John", createdAt: new Date() }) productsMetaData.set(product2, { creator: "Kate", createdAt: new Date() }) 320
console.log(productsMetaData.get(product1)) // { creator: "John", createdAt: <дата> } // перебор по ключам (овощи) for (let vegetable of recipeMap.keys()) { alert(vegetable) // огурец, помидор, лук } // перебор по значениям (числа) for (let amount of recipeMap.values()) { alert(amount) // 500, 350, 50 } // перебор по элементам в формате [ключ, значение] for (let entry of recipeMap) { // то же самое, что и recipeMap.entries() alert(entry) // огурец,500 (и так далее) } 321
ДАТА И ВРЕМЯ. Объект Date Время в JavaScript представлено в миллисекундах (10-3), прошедших с 1 января 1970 года по Гринвичу (GMT — Greenwich Mean Time или UTC — Universal Coordinate Time, Всеобщее скоординированное время). Метод now() оъекта Date возвращает указанные миллисекунды Date.now() // 1707724396014 const minute = 1000 * 60 const hour = minute * 60 const day = hour * 24 const year = day * 365 let years = Math.round(Date.now() / year) // 54 Объект Date — это мгновенный снимок, определяющий момент, когда он был сделан. var  = new Date (), где  — имя переменной, которой будет присвоено значение текущей даты и времени. console.log(Date()) // Mon Feb 12 2024 11:07:39 GMT+0300 (Москва, стандартное время)  = new Date(год, месяц, день[, часы, минуты, секунды]). В качестве аргумента объекта Date мы можем поместить любую дату и время. let дата = new Date(2000,11,13) Метод toLocaleString возвращает дату в длинном формате по умолчанию. console.log (дата.toLocaleString()) // 13.12.2000, 0:00:00 Однако, можно добавить параметры в этот метод и получить форматированную нужным образом дату и время 322
.toLocaleString([][,]), где  — дата.  — строка с языковым тегом или массив таких строк. Соответствует параметру locales конструктора Intl.NumberFormat().  — объект, определяющий выходной формат. Соответствует параметру options конструктора Intl.NumberFormat(). Возможные значения По умолчанию Свойство Описание localematcher алгоритм подбора локали lookup, best fit best fit formatmatcher алгоритм подбора формата basic, best fit best fit hour12 12-часовой формат true, false timezone временная зона europe, moscow weekday день недели narrow, short, long era эра narrow, short, long year год 2-digit, numeric undefined numeric month месяц 2-digit, numeric, narrow, short, long undefined numeric day день 2-digit, numeric undefined numeric hour час 2-digit, numeric minute минуты 2-digit, numeric second секунды 2-digit, numeric timezonename название таймзоны short, long date = new Date() var options = { 323 utc
era: 'long', year: 'numeric', month: 'long', day: 'numeric', weekday: 'long', hour: 'numeric', minute: 'numeric', second: 'numeric' }; var options2 = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short', }; console.log(date.toLocaleString("ru", options)) // вторник, 7 мая 2024 г. от Рождества Христова, 12:47:38 console.log(date.toLocaleString("en-US", options)) // Tuesday, May 7, 2024 Anno Domini at 12:47:38 PM console.log(date.toLocaleString("ru", options2)) // вт, 7 мая 2024 г. Метод Date.parse() — статический метод объекта Date в JavaScript. Он принимает строковое представление даты и возвращает число, равное количеству миллисекунд, прошедших с 1 января 1970 года UTC до заданной даты. Если строка не распознана как корректная дата, возвращает NaN. let timestamp = Date.parse('2016-11-16T12:59:59') console.log(timestamp) // 1479290399000 Date.parse('2019-01-01')) // 1546300800000 Date.parse('invalid date')) // NaN Date.parse() удобен для преобразования строк в числовое значение времени для последующих вычислений и сравнений дат. Он часто используется совместно с конструкцией new Date(Date.parse(...)) или напрямую с методом Date. let d = new Date(Date.parse('2024-01-01T00:00:00')) 324
Метод объекта Date .getFullYear() .getYear() .getMonth() .getDate() .getDay() .getHours() .getMinutes() .getSeconds() .getMilliseconds() .getTime() .toISOString() toUTCString() Возвращаемое значение возвращает год в полном формате возвращает год в кратком или полном формате (в зависимости от браузера) возвращает номер месяца (от 0 до 11) возвращает число месяца (от 1 до 31) возвращает день недели (от 0 до 6) возвращает час (от 0 до 23) возвращает минуты (от 0 до 59) возвращает секунды (от 0 до 59) возвращает миллисекунды (от 0 до 999) возвращает миллисекунды (от 1 января 1970 года GMT) возвращает дату в формате ISO (2024-0507T10:08:36.052Z) возвращает дату в зоне UTC (Tue, 07 May 2024 10:07:57 GMT) .toDateString() возвращает дату без времени (Wed Jul 28 1993) .setFullYear() устанавливает год в полном формате .setYear() устанавливает год в кратком или полном формате (в зависимости от браузера) устанавливает номер месяца (от 0 до 11) .setMonth() .setDate() .setHours() .setMinutes() .setSeconds() .setMilliseconds() .setTime() устанавливает число месяца (от 1 до 31) устанавливает час (от 0 до 23) устанавливает минуты (от 0 до 59) устанавливает секунды (от 0 до 59) устанавливает миллисекунды (от 0 до 999) устанавливает миллисекунды (от 1 января 1970 года GMT) Где  — имя переменной типа Date,  — число. Пример1 let дата = new Date (); let день = дата.getDate () let месяц = дата.getMonth () let год = дата.getFullYear () 325
let название_месяца = ["января", "февраля", "марта", "апреля", "мая", "июня", "июля", "августа", "сентября", "октября", "ноября", "декабря"] document.write ("<p> Сегодня " + день + " " + название_месяца [месяц] + " " + год + " года </p>") П р и м е р 2. Календарь с выделением текущей даты let дата = new Date (); let день_сегодня = дата.getDate() d=1 document.write ("<table border = 1>") for (r = 1; r < 6; r++) { document.write ("<tr>") for (c = 1; c < 8; c++) { if (! (r == 1 && c < 4) && d <= 31) { if (день_сегодня == d) document.write ("<td bgcolor = pink>", d, "</td>") else document.write ("<td>", d, "</td>") d++ } else document.write ("<td> </td>") } document.write ("</tr>") } document.write ("</table>") 326
З а д а н и е 1. Усовершенствуйте скрипт таким образом, чтобы получилась функция calendar (days) с входным параметром days, хранящим число дней в месяце. Функция должна выводить на веб-страницу календарь в соответствии с днями недели и числом дней месяца, без лишних строк. З а д а н и е 2. Напишите функцию, которая по дате возвращает день недели словом. З а д а н и е 3. Напишите функцию, которая по дате возвращает название месяца. З а д а н и е 4. Напишите функцию, возвращающую количество часов, прошедших с 1970 года до настоящего времени. З а д а н и е 5. Напишите функцию, возвращающую количество дней, прошедших с начала 2000 года до настоящего времени. З а д а н и е 6. Напишите функцию, возвращающую массив дат, одна из которых была ровно семь лет назад и дату, которая будет через 3 года Над датами можно выполнять арифметические действия. Например, мы хотим знать сколько осталось ждать дней до выборов президента. П р и м е р 3. Выборы президента const ОДНА_СЕК = 1000 const ОДНА_МИН = ОДНА_СЕК * 60 const ОДИН_ЧАС = ОДНА_МИН * 60 const ОДИН_ДЕНЬ = ОДИН_ЧАС * 24 сегодня = new Date () let сколько_миллисекунд_осталось = new Date () 327
выборы_президента = new Date () день_выборов_президента = 01 месяц_выборов_президента = 04 год_выборов_президента = 2024 выборы_президента.setDate (день_выборов_президента) выборы_президента.setMonth (месяц_выборов_президента) выборы_президента.setFullYear (год_выборов_президента) сколько_миллисекунд_осталось = выборы_президента - сегодня сколько_дней_осталось = Math.ceil (сколько_миллисекунд_осталось / ОДИН_ДЕНЬ) document.write ("Сегодня ", сегодня, "<br>") document.write ("До выборов президента осталось " + сколько_дней_осталось + " дней ") Практическая работа на дату и время Задание 1. Составьте функцию, которая возвращает текущую дату в формате день:число месяц:название год:число день_недели:название 27 февраля 2015 пятница Задание 2. Напишите сценарий, который по введенному дню рождения высчитывает и выводит возраст человека. Задание 3. Напишите сценарий, который определяет число дней между двумя введенными датами. Задание 4. Напишите сценарий, который выводит в таблице календарь на один месяц. Название месяца и год выбирает посетитель из соответствую328
щего размещенного на веб-странице списка. Предусмотрите в сценарии возможность составления посетителем списка выбранных из календаря дат. Задание 5. Напишите сценарий для всех страниц сайта, который размещает на каждой из них верхний заголовочный баннер и левую навигационную панель. Баннер для каждой страницы содержит соответствующий заголовок. Задание 6. 8 Напишите функцию, которая принимает дату в качестве параметра и возвращает логическое значение, представляющее, является ли дата сегодняшней или нет. function isToday(date) { } const today = new Date() isToday(today) // true Задание 7. 7 Напишите функцию, которая принимает дату в формате d/m/Y(строка) и возвращает, какой это был день недели (строка). function dayOfTheWeek (date) { } dayOfTheWeek("02/06/1940") // "Sunday" dayOfTheWeek("20/02/2045") // "Monday" dayOfTheWeek("24/01/2017") // "Tuesday" 329
Задание 8. 8 Напишите функцию, которая будет возвращать дни в году, учитывая високосные года. Например: yearDays(2000) возвращает "2000 has 366 days" Большинство лет, которые можно разделить без остатка на 4, являются високосными. Исключение: столетние годы НЕ являются високосными, если их нельзя разделить на 400 без остатка. Таким образом, годы 0, -64 и 2016 вернут 366 дней. В то время как 1974, -10 и 666 вернут 365 дней. function yearDays (year) { } yearDays(0) // '0 has 366 days' yearDays(-64) // '-64 has 366 days' yearDays(2016), '2016 has 366 days' Задание 9. 8 Вы переделываете дизайн блога. Сообщения в блоге имеют формат времени «День недели, месяц, день» для отображения даты и времени публикации сообщения, например, пятница, 2 мая, 19:00. У вас заканчивается свободное место на экране, и на некоторых страницах вы хотите отображать более короткий формат, день недели, месяц, день, без времени. Напишите функцию, которая принимает дату/время веб-сайта в исходном строковом формате и возвращает сокращенный формат. function shortenToDate(longDate) { } shortenToDate("Friday May 2, 9am") // "Friday May 2" shortenToDate("Tuesday January 29, 10pm") // "Tuesday January 29" 330
shortenToDate("Monday December 25, 10pm") // "Monday December 25" Задание 10. 7 Преобразование 12-часового времени, такого как «8:30 утра» или «20:30 вечера», в 24-часовое время (например, «08:30» или «20:30»). Напишите функцию, которой будет задан час (всегда в диапазоне от 1 до 12 включительно), минуты (всегда в диапазоне от 0 до 59 включительно) и период (либо «am», или "pm") в качестве входных данных. Задача — вернуть четырехзначную строку, которая кодирует заданное время в 24-часовом формате. Полдень — это 12:00, а полночь — 00:00. function to24hourtime(hour, minute, period) { } to24hourtime( 1, 0, "am") // "0100" to24hourtime( 1, 0, "pm") // "1300" to24hourtime(12, 0, "am") // "0000" Задание 11. 7 Вы когда-нибудь хотели узнать, сколько вам дней? Напишите функцию, которая возвращает ваш возраст в днях. День рождения дается в следующем порядке: год, месяц, день. function ageInDays(year, month, day) { } var birthday = new Date(); birthday.setDate(birthday.getDate() - 2); ageInDays(birthday.getFullYear(), birthday.getMonth()+1, birthday.getDate()) // "You are 2 days old” 331
var birthday = new Date(); birthday.setDate(birthday.getDate() - 365); ageInDays(birthday.getFullYear(), birthday.getMonth()+1, birthday.getDate()) // "You are 365 days old" Задание 12. 7 У Вас есть денежная сумма a0 > 0, и Вы вносите ее с процентной ставкой p процентов, деленной на 360 в день с 1 января 2016 года. Вы хотите иметь сумму a >= a0. Разработайте функцию date_nb_days с параметрами a0, a, p, которая вернет в виде строки дату, в которую будет достигнута сумма a. function dateNbDays(a0, a, p) { } dateNbDays(4281, 5087, 2) // "2024-07-03" dateNbDays(4620, 5188, 2) // "2021-09-19" dateNbDays(9999, 11427, 6) // "2018-03-13" Задание 13. 7 Если задано время в классе формата времени, верните его без года, месяца и дня. Должна возвращаться строка, включающая миллисекунды с тремя десятичными знаками. function convert(time) { } convert(new Date(2016, 2, 8, 16, 42, 59)) // "16:42:59,000" convert(new Date(1951, 10, 31, 2, 2, 24, 399)) // "02:02:24,399" convert(new Date(1523, 5, 29, 23, 2, 2, 9)) // "23:02:02,009" convert(new Date(1, 1, 1, 1, 1, 1, 110)) // "01:01:01,110" convert(new Date(9999, 9, 9, 9, 9, 9, 999)) // "09:09:09,999" 332
Задание 14. 7 Задача — конвертировать минуты (int) в часы и минуты в формате hh:mm (string). Если входные данные 0 или отрицательное значение, то вы должны вернуть "00:00". function timeConvert(num) { } timeConvert(0) // "00:00" timeConvert(-6) // "00:00" timeConvert(8) // "00:08" timeConvert(32) // '0'+0+':'+32 333
КЛАССЫ Из Википедии следует, что класс — это элемент программного обеспечения, описывающий абстрактный тип данных и его частичную или полную реализацию. В JavaScript классы, как и функции, можно описывать как классы-декларации (class declarations) или как классывыражения (class expressions). Классы в JavaScript появились с внедрением стандарта ES2015 (ES6). Таким образом появился новый способ определения совокупности объектов — с помощью класса. Класс представляет собой описание абстрактного объекта, его состояния и поведения, а объект является конкретным воплощением или экземпляром класса. На основе класса можно создать множество похожих объектов. class  [extends ] {   static  get 1 () { } set 2 () { } }, где  — название класса;  — родитель;  — конструктор. Конструктор определяется с помощью метода с именем constructor. Это метод, который может принимать параметры. Основная цель конструктора — инициализировать объект начальными данными. Функция constructor запускается при создании объекта — экземпляра класса (new );  — методы. Все методы класса работают в строгом режиме (strict), даже если он не указан. Это значит, что все переменные требуют объявления (var, let, const); static  — статические методы. Статические методы вызываются через имя класса, вызывать статические методы через имя объекта запрещено; get — методы, возвращающие значения; set — методы, устанавливающие новые значения. 334
Пример 1 class Student {} или в варианте класса-выражения let Student = class{} Добавим в класс Student конструктор и методы. class Student { constructor (имя, фамилия, годПоступления, специальность, общежитие, сессия) { this.facultet = "физ-мат" this.имя=имя this.фамилия=фамилия this.годПоступления=годПоступления this.специальность=специальность this.общежитие=общежитие this.оценкаСессии=[] } курс() { let сегодня=new Date() let текущийГод=сегодня.getFullYear() let курс=текущийГод-this.годПоступления return (`${курс} курс`) } get полноеИмя() { return `${this.имя} ${this.фамилия}` } set сменитьИмя(newValue) { this.имя = newValue } set выселитьИзОбщежития(newValue) { this.общежитие = newValue } set результатыСессии(newValue) { this.оценкаСессии.push(newValue) // добавить оценку } } 335
Создадим объект stud1 на основе класса Student и дадим значения встроенным свойствм, воспользуемся встроенными методами. stud1 = new Student("Дина","Дымова",2017,"физика","есть") alert (`${stud1.фамилия} ${stud1.курс()} ${stud1.полноеИмя} ${stud1.общежитие}`) stud1.сменитьИмя = "Маша" stud1.выселитьИзОбщежития="нет" alert(`${stud1.полноеИмя} ${stud1.общежитие}`) stud1.результатыСессии=5 stud1.результатыСессии=4 alert (`сессия ${stud1.оценкаСессии}`) Как видно из примера, обычные методы вызываются по имени с круглыми скобками, тогда как гетеры и сетеры вызываются без скобок. Дочерние классы Javascript поддерживает наследование, которое позволяет создавать новый класс на базе уже существующего — так дочерний класс получает все свойства и методы родительского класса и может добавлять свои. Если создавать класс, опираясь на родительский (extends), то нужно иметь ввиду, что конструктор родителя наследуется автоматически и его можно опустить в потомке. Если потомку необходим свой конструктор, то для вызова в нем конструктора родителя используется ключевое слово super() с аргументами для родительского класса. Ключевое слово super необходимо указывать до обращения к this. В дочернем конструкторе нужно обязательно вызывать родительский конструктор. Кроме того, можно через super вызывать родительские методы (super.метод()) в методах потомка. П р и м е р 1. Дочерний класс без своего конструктора class Parent { constructor(name) { this.name = name; 336
} greet() { console.log(`Привет, ${this.name}`); } } class Child extends Parent { // no constructor here } const kid = new Child('Маша'); kid.greet(); // Привет, Маша П р и м е р 2. Дочерний класс со своим конструктором // Родительский класс class User { constructor(name) { this.name = name } getName() { return this.name } } // Дочерний класс на основе User class ContentWriter extends User { constructor(name, posts = []) { super(name); // Вызов конструктора родителя this.posts = posts; // Новое свойство дочернего класса } } const writer = new ContentWriter('Лермонтов', ['Герой нашего времени']) console.log(writer.getName()) // Лермонтов console.log(writer.posts) // ['Герой нашего времени'] 337
П р и м е р 3. Дочерний класс с вызовом родительского метода // Родительский класс class Animal { speak() { console.log("Животное издает звук"); } } // Дочерний класс class Dog extends Animal { speak() { super.speak(); // Вызов метода родителя console.log("Собака лает"); } } const dog = new Dog() dog.speak() // Животное издает звук // Собака лает Статические свойства и методы В JavaScript статические свойства и методы — это такие элементы класса, которые определены на самом классе и доступны только через имя класса, а не через его отдельные экземпляры. Эти свойства и методы нужны для того, чтобы: • • • сохранять данные, общие для всех экземпляров класса (например, счетчик созданных объектов); выносить вспомогательные или утилитарные функции, которые не связаны с конкретным объектом, а относятся к самому классу; создавать фабричные методы для удобного создания экземпляров. П р и м е р 1. class User { 338
static count = 0; // статическое свойство для хранения количества пользователей constructor(name) { this.name = name; User.count++; // увеличиваем счетчик при создании объекта } static getCount() { return User.count; // статический метод для доступа к счетчику } } const u1 = new User('Алиса'); const u2 = new User('Борис'); console.log(User.getCount()); // 2 П р и м е р 2. class Parent { static say() { console.log('Parent static method'); } } class Child extends Parent { static say() { super.say(); // вызов метода родителя console.log('Child static method'); } } Child.say() // Parent static method // Child static method П р и м е р 3. class Clock { 339
constructor() {} static go() { return 'tik' } } class Watch extends Clock { constructor() {} static tiltak() { return super.go() + ' tak'; } } Watch.tiltak() // 'tik tak' Существует оператор instanceof, который проверяет, принадлежит ли объект к определённому классу.  instanceof β, где  — объект, β — класс. stud1 instanceof Student // true stud1 instanceof Object // true stud1 instanceof Number // false Примеры П р и м е р 1. 8 Имеется класс Animal. Задача — описать еще класс Shark, который является потомком от Animal. Функция-конструктор для Shark должна принимать 3 аргумента в следующем порядке: name, age, status. Все акулы должны иметь количество ног (legs) 0 (поскольку у них, очевидно, нет ног) и должны иметь вид «акула» (species — shark). class Animal { constructor(name, age, legs, species, status) { this.name = name; 340
this.age = age; this.legs = legs; this.species = species; this.status = status; } introduce() { return `Hello, my name is ${this.name} and I am ${this.age} years old.`; } } class Shark extends Animal { constructor(name, age, status) { super(name, age, status); this.legs = 0; this.species = "shark"; this.status = status } } П р и м е р 2. 7 Определите класс куб, конструктор которого принимает один параметр и сохраняет в нем значение длины стороны куба. Для кубов длина, ширина и высота всегда одинаковы. Задача — вычислить длину стороны куба, зная его площадь поверхности и (или) объем. Для этого необходмо использовать сеттеры, а также геттеры как для площади поверхности, так и для объема куба. class Cube { constructor(length) { this.length = length; } set surfaceArea(sfa){ this.length = Math.sqrt (sfa/6); } 341
set volume(v){ this.length = Math.cbrt (v); } get surfaceArea(){ return 6 * (this.length)**2 } get volume(){ return this.length ** 3 } } Пример 3 class Город { constructor (имя, площадь, население) { this.имя=имя this.площадь=площадь this.население=население } плотность() { let pl=this.население/this.площадь return (`${this.имя} ${Math.round(pl)} чел./км^2`) } } class Поселок extends Город { } let пос1 = new Поселок ("Лопуховка",50,167) console.log (пос1.имя) // Лопуховка let город1 = new Город ("Пенза", 290, 523553) console.log (город1.плотность()) // Пенза 1805 чел./км^2 console.log (пос1.плотность()) // Лопуховка 3 чел./км^2 В примере выше создан класс Город и на его основе создан класспотомок Поселок. Тело потомка пустое, но он унаследовал и конструктор и метод родителя, поэтому мы можем узнать плотность населения не только города Пензы, но и поселка Лопуховка. 342
Пример 4 Создание коллекции детских карточек с животными и их названиями. class Card { constructor(img, txt) { this.img = img; this.txt = txt; } cardMaker() { let raz = `<img src="${this.img}"> <figcaption> ${this.txt} </figcaption>`; let div_node = document.createElement("figure") let ap_div = document.body.appendChild(div_node) ap_div.innerHTML = raz } } let imgs = [ "animal-2029774_640.png", "animal-3745613_640.png", "camel-48445_640.png", "cat-46676_640.png", "dog-48490_640.png", "fox-807315_640.png", "parrot-1417286_640.png", "rabbit-5661931_640.jpg", "sheep-35599_640.png", "sloth-5043324_640.png", "squirrel-1456764_640.png" ] let texts = ["Петух", "Лошадь", "Верблюд", "Кошка", "Собака", "Лиса", "Попугай", "Заяц", "Овца", "Слон", "Белка"] 343
let card = [] for (let i = 0; i < texts.length; i++) { card[i] = new Card(imgs[i], texts[i]) card[i].cardMaker() } П р и м е р 5. 7 Задача – создать класс под названием Song. Класс будет иметь два параметра: название и исполнитель. const mountMoose = new Song('Mount Moose', 'The Snazzy Moose') mountMoose.title // 'Mount Moose' mountMoose.artist // 'The Snazzy Moose' Еще добавить в класс метод с именем howMany(). Метод возвращает число новых слушателей песни. Имена должны обрабатываться без учета регистра. class Song { constructor (title, artist){ this.title = title this.artist = artist this.names = [] } howMany(names) { let count = 0 for (let l of names) { if(!this.names.includes(l.toUpperCase())){ this.names.push(l.toUpperCase()) count ++ } } return count } } 344
Практическая работа на классы Задание 1. Добавьте в описание класса метод, вычисляющий средний балл всех сессий. Задание 2. Создайте класс «Стенческая группа», в котором опишите параметры: название группы, староста, студенты. Студентов включите как массив объектов класса Student. Разработайте методы по смене старосты группы и определению успеваемости группы в целом исходя из успеваемости каждого студента. Задание 3. Создайте класс «Автомобиль», в котором опишите параметры: марка, цвет, мощность (в л/с), максимальная скорость (км/ч), объем бака (л); расход топлива (л) на 100 км пути. Разработайте метод расчета длины пути на полный бак топлива. Задание 4. Создайте класс для хранения таблицы m на n. Разработайте методы для записи значения в указанную ячейку таблицы, чтения значения из указанной ячейки таблицы, получения всех значений указанной строки таблицы, получения всех значений указанного столбца таблицы. Задание 5. Создайте класс для счета в банке и класс для клиента банка. Клиент может иметь в банке несколько счетов. Разработайте методы для зачисления средств на счет, снятия средств со счета, получения остатка по счету (баланс счета), перевода указанной суммы с одного счета на другой. Задание 6. Напишите определение класса, который предназначен для хранения таблицы размером m на n ячеек. Разработайте методы записи значения в указанную ячейку таблицы, чтения значения из указанной ячейки, получения всех значений указанной строки таблицы, получения всех значений указанного столбца таблицы. 345
Задание 7. 8 Задача состоит в том, чтобы доработать класс Person. Необходимо заполнить метод конструктора, который принимает имя человека в виде строки и возраст в виде числа, добавить геттер info, который должен возвращать возраст в виде строки, как, например, 'johns age is 34' class Person { constructor() { } } var john = new Person('john', 34) john.info // 'johns age is 34' Задание 8. 8 Имеется класс Animal. Задача – доработать класс Cat, который расширяет класс Animal, и заменить метод speak так, чтобы он возвращал имя кошки и meows. например, 'Mr Whiskers meows.'. class Animal { constructor(name, age, legs, species, status) { this.name = name; this.age = age; this.legs = legs; this.species = species; this.status = status; } class Cat extends Animal { } var cat = new Cat('Mr Whiskers') 346
cat.speak() // 'Mr Whiskers meows.' cat = new Cat('Lamp'); cat.speak() // 'Lamp meows.' cat = new Cat('$$Money Bags$$'); cat.speak() // '$$Money Bags$$ meows.' Задание 9. 7 Имеется класс Animal. Задача — описать еще классы, которые являются потомками от Animal. I. Shark Функция-конструктор для Shark должна принимать 3 аргумента в следующем порядке: name, age, status. Все акулы должны иметь количество ног (legs) 0 (поскольку у них, очевидно, нет ног) и должны иметь вид «акула» (species — shark). II. Cat Функция-конструктор для Cat должна принимать те же 3 аргумента, что и для Shark: name, age, status. У кошек всегда должно быть количество ног 4 и вид «кошка». Кроме того, метод introduce для Cat должен быть идентичен оригиналу, за исключением того, что после стандартной фразы должно быть ровно 2 пробела и слова "Meow meow!". var example = new Cat("Example", 10, "Happy"); example.introduce() === "Hello, my name is Example and I am 10 years old. Meow meow!"; // Notice the TWO spaces - very important III. Dog Конструктор Dog должен принимать 4 аргумента в указанном порядке: name, age, status, master. Мастер — это имя хозяина собаки, которое представляет собой строку. Кроме того, у собак должно быть 4 ноги и вид "dog". У собак есть идентичный метод introduce, как и у любого другого животного, но у них есть свой собственный метод, называемый greetMaster, который не принимает аргументов и возвращает "Hello (master_name)", где master_name — это имя хозяина собаки. class Animal { 347
constructor(name, age, legs, species, status) { this.name = name; this.age = age; this.legs = legs; this.species = species; this.status = status; } introduce() { return `Hello, my name is ${this.name} and I am ${this.age} years old.`; } } class Shark extends Animal { constructor(/* Insert your parameters here */) { super(/* Make a call to the parent class's constructor with the correct arguments */); } } class Cat extends Animal { // Do the same here as you did for Shark - define your constructor function and any other methods you need } class Dog extends Animal { // On your own now - you can do it :D } var billy = new Shark("Billy", 3, "Alive and well"); billy.name // "Billy" billy.age // 3 billy.legs // 0 billy.species // "shark" billy.status // "Alive and well" billy.introduce() // “Hello, my name is Billy and I am 3 years old.” var charles = new Shark("Charles", 8, "Finding a mate"); charles.name // "Charles" 348
charles.age // 8 charles.legs // 0 charles.species // "shark" charles.status // "Finding a mate" charles.introduce() // “Hello, my name is Charles and I am 8 years old.” Задание 10. 8 Даны классы class Dog { constructor(name, age, gender, species, size, master, loyal) { this.name = name; this.age = age; this.gender = gender; this.species = species; this.legs = 4; this.size = size; this.master = master; this.loyal = loyal; } } class Labrador { constructor(name, age, gender, master) { this.name = name; this.age = age; this.gender = gender; this.species = "Labrador"; this.legs = 4; this.size = "Large"; this.master = master; this.loyal = true; } } 349
Сократите код класса Labrador так, чтобы в нем было не более 233 символов. Задание 11. 7 Дан класс Animal. Задача — завершить написание класса Cat, который расширяет Animal. Включить в него оригинальный метод speak с использованием метода super так, чтобы метод speak для Cat возвращал, например, 'Mr Whiskers makes a noise, Mr Whiskers goes meow.'. class Animal { constructor(name) { this.name = name; } speak() { return this.name + ' makes a noise, '; } } class Cat extends Animal { } var cat = new Cat('Mr Whiskers'); cat.speak() // 'Mr Whiskers makes a noise, Mr Whiskers goes meow. Задание 12. 7 Задача — создать класс с именем "Animal", который принимает аргументы "name" и "type". Он должен иметь метод toString, который возвращает строку “<name> is <type>” . Он также должен позволять изменять свойство name. var dog = new Animal('Max', 'dog'); dog.toString() // 'Max is a dog' dog.type // 'dog' 350
dog.name // 'Max' dog.name = 'Lassie' Задание 13. 7 Определите следующие классы. I. Cuboid Конструктор для класса Cuboid должен иметь три аргумента в следующем порядке: длина, ширина, высота и сохранить эти три значения в this.length, this.width и this.height соответственно. Класс Cuboid должен содержать геттер, который возвращает площадь поверхности кубоида, и геттер, который возвращает объем кубоида. II. Cube Класс Cube является подклассом класса Cuboid. Конструктор Cube должен получать только один аргумент, его длину, и использовать значение для установки this.length, this.width и this.height. Подсказка: используйте super, передав правильные аргументы. class Cuboid { } class Cube extends Cuboid { } var cuboid = new Cuboid(1, 2, 3); cuboid.length // 1 cuboid.width // 2 cuboid.height // 3 cuboid.volume // 6 cuboid.surfaceArea // 22 cuboid.length = 4; cuboid.volume // 24 cuboid.surfaceArea // 52 cuboid.width = 5; cuboid.volume // 60 cuboid.surfaceArea // 94 351
cuboid.height = 6; cuboid.volume // 120 cuboid.surfaceArea // 148 [cuboid.length, cuboid.width, cuboid.height] = [7, 8, 9]; cuboid.volume // 504 cuboid.surfaceArea // 382 var cube = new Cube(1); cube.length // 1 cube.width // 1 cube.height // 1 cube.volume // 1 cube.surfaceArea // 6 cube.length = cube.width = cube.height = 2; cube.volume // 8 cube.surfaceArea // 24 cube.length = cube.width = cube.height = 3; cube.volume // 27 cube.surfaceArea // 54 cube.length = cube.width = cube.height = 5; cube.volume // 125 cube.surfaceArea // 150 cube.length = cube.width = cube.height = 10; cube.volume // 1000 cube.surfaceArea // 600 Задание 14. 8 Создайте конструктор класса Person, который принимает 4 аргумента: firstName (по умолчанию "John"), lastName (по умолчанию "Doe"), age (по умолчанию 0) и gender (по умолчанию "Male"). Они должны быть сохранены в this.firstName, this.lastName, this.age and this.gender соответственно. Добавьте в класс метод sayFullName, который не принимает аргументов, но возвращает полное имя (например, "John Doe"). 352
Добавьте статический метод greetExtraTerrestrials, который принимает один параметр raceName и возвращает "Welcome to Planet Earth <raceName>". Например, если название расы "Martians", оно должно гласить "Welcome to Planet Earth Martians". class Person { } new Person().firstName, "John" new Person().lastName // "Doe" new Person().age // 0 new Person().gender // "Male" new Person().sayFullName() // "John Doe" new Person("Jane", "Doe", 25, "Female").firstName // "Jane" new Person("Jane", "Doe", 25, "Female").sayFullName() // "Jane Doe" Задание 15. 8 Создайте метод, чтобы проверить, является ли строка ПОЛНОСТЬЮ ЗАГЛАВНОЙ. String.prototype.isUpperCase = function() { } 'hello I AM DONALD'.isUpperCase() // false 'HELLO I AM DONALD'.isUpperCase() // true Задание 16. 7 Ruby и Javascript позволяют повторно открывать классы, чтобы можно было добавлять новые функциональные возможности к существующим классам и объектам. Добавьте новый метод myNewMethod в существующий класс String, который вызывает метод toUpperCase() для исходной строки. "abc".myNewMethod() // "ABC" 353
Задание 17. 7 Вы моделируете взаимодействие между большим количеством кварков и решили создать класс Quark, чтобы можно было создавать свои собственные объекты quark. Кварки — это фундаментальные частицы и единственная фундаментальная частица, испытывающая все четыре фундаментальных взаимодействия. Создайте класс Quark, который должен позволять создавать кварки любого допустимого цвета (color) ("red", "blue", and "green") и любого допустимого вкуса (flavor) ('up', 'down', 'strange', 'charm', 'top', and 'bottom'). Каждый кварк имеет один и тот же барионный номер baryon_number, равный 1/3. У каждого кварка должен быть метод interact(), который позволяет любому кварку взаимодействовать с другим кварком с помощью сильного взаимодействия. Когда два кварка взаимодействуют, они обмениваются цветами. class Quark { } let q1 = new Quark("red", "up") let q2 = new Quark("blue", "strange") q1.color // "red" q2.flavor // "strange" q2.baryon_number // 0.3333333333333333 q1.interact(q2) q1.color // "blue" 354
Задание 18. 7 О, нет! Урок Тимми закончился! Можете ли вы помочь Тимми и исправить его класс? У Тимми есть созданный им класс List, который используется для массивов. Когда Тимми вызывает свойство Count, оно по-прежнему остается равным 0 при добавлении элементов. Кроме того, он терпит неудачу, когда Тимми пытается связать добавления, например myList.add(0).add(1) class List { constructor(type) { this.type = type; this.items = []; this.count = 0; } add(item){ if(typeof item != this.type) return `This item is not of type: ${typeof item}`; this.items.push(item); return item; } } var myList = new List('string') myList.add('Hello').count // 1 myList.add(5) // `This item is not of type: ${'string'}` myList.add(' ').add('World!').count // 3 Задание 19. 8 Создайте класс Ghost. Объекты-призраки создаются без каких-либо аргументов. Объектам-призракам присваивается случайный атрибут цвета «белый», «желтый», «фиолетовый» или «красный» при создании экземпляра. 355
var Ghost = function() { } ghost = new Ghost() ghost.color // "white" or "yellow" or "purple" or "red" Задание 20. 8 Вы лидер небольшой пиратской команды. И у вас есть план. С помощью ООП вы хотите сделать довольно эффективную систему идентификации кораблей с тяжелой добычей на борту! К сожалению для вас, в наши дни люди весят очень много, так как же узнать, что корабль полон золота, а не людей? Вы начинаете с написания обобщенного класса / структуры Ship: class Ship { constructor(draft, crew) { this.draft = draft this.crew = crew } } Каждый раз, когда ваши шпионы видят, что новый корабль входит в док, они создают новый объект корабля на основе своих наблюдений: • • draft – оценка веса судна, основанная на том, насколько низко оно находится в воде; crew - количество членов экипажа на борту const titanic = new Ship(15, 10); Задача. У вас есть доступ к судну "draft" и "crew". «Draft» — это общий вес корабля, а «crew» — количество людей на корабле. Каждый член экипажа добавляет 1,5 единицы к осадке корабля. Если после снятия веса экипажа осадка все равно больше 20, то корабль стоит разграбить. Любой корабль с таким весом должен иметь много добычи! Добавьте метод isWorthIt чтобы решить, достоин ли корабль для добычи. Например: titanic.isWorthIt() // false 356
Задание 21. 8 Согласно мифам о творении авраамических религий, Адам и Ева были первыми людьми, странствовавшими по Земле. Вы должны выполнить Божью работу. Создайте метод create(), который будет возвращать массив из 2 элементов, содержащий объекты Adam и Eve. Первый объект массива — экземпляр класса Man. Второй — экземпляр класса Woman. Оба объекта должны быть подклассами класса Human. Задача — реализовать классы Human, Man и Woman. class God { static create() { } } let humans = God.create() [0] instanceof Man // true Задание 22. 8 Вы уже реализовали класс Cube, но теперь нам снова нужна ваша помощь! Я говорю о конструкторах. У нас его нет. Давайте напишем два кода: один принимает целое число, а другой обрабатывает незаданные аргументы! Также мы получили проблему с отрицательными значениями. Исправьте код так, чтобы отрицательные значения переключились на положительные! Конструктор должен присвоить 0 свойству side куба. class Cube { getSide() { return this.side } setSide(n) { this.side = Math.abs(n) } 357
} let cube = new Cube(12) cube.getSide() // 12 cube.setSide(-42) cube.getSide() // 42 let cube = new Cube() cube.getSide() // 0 Задание 23. 7 Гринч хочет испортить Рождество программистам JavaScript. Для этого он разработал адский план: загрязнить прототип Дэйта, чтобы Рождество никогда не наступило. Он хочет изменить метод getDate of Date, чтобы он возвращал 26 для объектов Date, которые представляют 25 декабря, но корректно работают для всех остальных дней года. Однако Гринч не знает, как это сделать. Сможешь ли ты ему помочь? Date.prototype.getDate = function getGrinchDate() {} let d = new Date('1957-10-25'); d.getMonth() // 9 d.getDate() // 25 d = new Date('1957-12-25'); d.getMonth() // 11 d.getDate() // 26 Задание 24. 7 Напишите класс Block, который создает блок. Конструктор должен принимать в качестве аргумента массив, он будет содержать 3 целых числа вида [width, length, height], из которых должен быть создан блок. 358
Определите методы getWidth() — возвращает ширину блока width getLength() — возвращает длину блока length getHeight() — возвращает высоту блока height getVolume() — возвращает объем блока volume getSurfaceArea() возвращает площадь блока (surface area) class Block { constructor(data) { } } let block = new Block([2,4,6]) block.getWidth() // 2 block.getLength() // 4 block.getHeight() // 6 block.getVolume() // 48 block.getSurfaceArea() // 88 Задание 25. 6 Вы отправляетесь в путешествие со студентами, и вам нужно следить за количеством денег у каждого студента. Студент определяется следующим образом: class Student { constructor(name, fives, tens, twenties) { this.name = name; this.fives = fives; this.tens = tens; this.twenties = twenties; } } Как вы можете заметить, у каждого студента есть пятерки, десятки и двадцатки. Задача — вернуть имя студента с наибольшим количеством денег. Если у всех студентов сумма одинаковая, верните "all". Примечания: у каждого студента уникальное имя. 359
Всегда будет явный победитель: либо у кого-то больше всего, либо у всех одинаковое количество. Если есть только один студент, то у него больше всего денег. function mostMoney(students) { } const andy = new Student("Andy", 0, 0, 2) const stephen = new Student("Stephen", 0, 4, 0) const eric = new Student("Eric", 8, 1, 0) mostMoney([andy, stephen, eric, david, phil]) // "Eric" mostMoney([cam, geoff, andy, stephen, eric, david, phil]) // "Eric" mostMoney([andy]) // "Andy" mostMoney([stephen]) // "Stephen" mostMoney([cam, geoff]) // "all" Задание 26. 6 Создайте класс, называемый Lamp. Он будет иметь строковый атрибут для color и логический атрибут on, который будет указывать, включена лампа или нет. Определите конструктор класса с параметром цвета color и назначьте атрибуту on значение false при инициализации. Добавьте лампе метод под названием toggleSwitch, который переключит значение атрибута on. Разработайте еще один метод, называемый state, который вернет "The lamp is on.", если on включен и "The lamp is off." в противном случае. const myLamp = new Lamp("Blue") myLamp.color // "Blue" myLamp.on // false myLamp.state() // "The lamp is off." myLamp.toggleSwitch() myLamp.state() // "The lamp is on." 360
Задание 27. 6 Вики — настоящее маленькое чудо. Большинство людей даже не догадываются, что она не настоящая девушка, а робот, живущий среди нас. Конечно, если вы задержитесь у нее дома на какое-то время, то, возможно, увидите, как ее создатель вскрывает ей спину и вносит несколько изменений, и даже увидите, как она заряжается в шкафу, а не спит в кровати. В этом задаче мы поможем Вики следить за словами, которые она изучает. Напишите функцию learnWord(word), которая является методом объекта Robot. Функция должна сообщать, сохранено ли слово в памяти или оно уже известно роботу. Пример: var vicky = new Robot() vicky.learnWord('hello') // 'Thank you for teaching me hello' vicky.learnWord('abc') // 'Thank you for teaching me abc' vicky.learnWord('hello') // 'I already know the word hello' vicky.learnWord('wow!') // 'I do not understand the input' Регистр не имеет значения. Допустимы только буквы. Здесь есть небольшая хитрость! class Robot { learnWord(word) { } } let vicky = new Robot() vicky.learnWord('hello') // 'Thank you for teaching me hello' vicky.learnWord('world') // 'Thank you for teaching me world' vicky.learnWord('goodbye') // 'Thank you for teaching me goodbye' vicky.learnWord('world') // 'I already know the word world' vicky.learnWord('World') // 'I already know the word World' 361
Задание 28. 8 Представьте, что вы создаете игру, в которой пользователю нужно угадать загаданное число. Но существует ограничение на количество попыток. • • • Если пользователь попытается угадать больше лимита, метод должен выдать ошибку. Если предположение пользователя верно, метод должен вернуть значение true. Если предположение пользователя неверно, метод должен вернуть значение false и потерять жизнь. Сможете ли вы закончить игру, соблюдая все правила? class Guesser { constructor(number, lives) { this.number = number; this.lives = lives; } guess(n) { } } Задание 29. 7 Сюжет знаменитого анимационного фильма Disney-Pixar «Вверх» основан на путешествии главного героя Карла Фредриксена по его дому, оборудованному воздушными шарами. Но может ли это произойти на самом деле? Какие предметы можно поднять с помощью гелиевых шариков? Сколько шариков для этого понадобится? В этом ката вы создадите класс Journey (object, crew, balloons) 362
так что любой может создавать такие объекты, как var gravityFalls = new Journey(house, 2, 20622) что означает начало нового путешествия в Гравити Фолз в доме с двумя членами команды (Карлом и Расселом). Но возможно ли это путешествие? Достаточно ли 20622 гелиевых шариков (именно столько использовали аниматоры Pixar в сцене взлета)? Твой Journey класс должен иметь открытый метод isPossible(), который возвращает true или false на основе правил: 1) Каждый объект (словарь на Python), переданный в Journey будет иметь свое weight свойство как var house = {"weight": 45000}; (в этом ката мы будем использовать 45 000 кг — это примерно 100 000 фунтов). метрическую систему, 2) Каждый член экипажа весит 80 кг. 3) Мы используем стандартные праздничные шары, наполненные гелием. Каждый шар поднимает 4,8 грамма + собственный вес. Сможете ли вы поднять крошечную тележку весом 95 кг (~200 фунтов) с 50 воздушными шарами, как в одной из начальных сцен фильма? Может ли один воздушный шар на самом деле нести послание на одном листе бумаги размером с письмо, которое Карл послал своей умирающей жене Элли в другой сцене? Правдива ли история, которую я слышал о человеке, летающем в своем складном кресле, оснащенном 1000 воздушных шаров? Ваши навыки программирования подскажут вам ответы на эти и многие другие важные вопросы в тестах. Начнем путешествие! function Journey(object, crew, balloons) { } var letterToEllie = {'weight': 0.004536} var house = {'weight': 45000} var pushCart = {'weight': 95} var lawnChair = {'weight': 5} var flyingCart = new Journey(pushCart, 0, 50) 363
var loveOfMyLife = new Journey(letterToEllie, 0, 1) var gravityFalls = new Journey(house, 2, 20622) flyingCart.isPossible() // false loveOfMyLife.isPossible() // true gravityFalls.isPossible() // false Задание 30. 7 В этой задаче речь идет о статическом методе, который должен возвращать разные значения. При первом вызове он должен быть равен 1, при втором и последующих — он должен быть равен удвоенной величине предыдущего значения. class Class { static getNumber() { } } Class.getNumber() // 1 Class.getNumber() // 2 Class.getNumber() // 4 Задание 31. 7 Владелец собачьего дневного пребывания хочет знать, может ли он принимать новых собак в свой питомник, и ему необходимо проверить, прошли ли они обработку от глистов и вакцинированы ли они, чтобы принять их либо отдельно, либо вместе с другими собаками. Имеется класс Dog, который необходимо расширить с помощью метода checkDog (check_dog). Dog в настоящее время имеет следующие свойства (атрибуты): • name (имя); 364
• • • • age (возраст); breed (порода); vaccinated (вакцинированный); wormed (привит от глистов). Вам нужно будет каждый раз возвращать имя собаки, а также слова "can be accepted" («может быть принята»), " can only be accepted by itself" («может быть принята только сама по себе») и "can not be accepted" («не может быть принята»). • • • Если собака привита и обработана от глистов, ее можно принять. Если собака только привита или только обработана от глистов, то ее можно принять только одну. Если собака не привита и не обработана от глистов, ее не примут в заведение. var spot = new Dog("Spot", 5, "Labrador", true, false); var riley = new Dog("Riley", 3, "GoldenDoodle", true, true); var clive = new Dog("Clive", 8, "German Shepard", false, false); spot.checkDog() // "Spot can only be accepted by itself" riley.checkDog() // "Riley can be accepted" clive.checkDog() // "Clive can not be accepted" Задание 32. 7 В следующем коде не помешало бы немного объектно-ориентированного искусства. Хотя это простой метод, который отлично работает сам по себе, в более крупной системе лучше организовать методы в классы/объекты. (Или, по крайней мере, что-то подобное, в зависимости от языка программирования) Реорганизуйте следующий код так, чтобы он относился к классу/объекту Person. Каждый экземпляр Person будет иметь метод приветствия. Экземпляр Person должен быть создан с именем, чтобы его больше не приходилось передавать в каждый вызов метода приветствия. Вот как будет использоваться окончательный рефакторинг кода: 365
function greet(myName, yourName) { return `Hello ${yourName}, my name is ${myName}`; } let jack = new Person('Jack') let jill = new Person('Jill') jack.name // 'Jack' jill.name // 'Jill' jack.greet('Jill') // 'Hello Jill, my name is Jack' jill.greet('Jack') // 'Hello Jack, my name is Jill' Задание 33. 8 Научите Снупи и Скуби-Ду лаять, используя объектные методы. В настоящее время лаять умеет только Снупи, но не Скуби-Ду. Используйте прототипы методов, чтобы дать возможность всем собакам лаять. function Dog (breed) { this.breed = breed; } var snoopy = new Dog("Beagle") Dog.prototype.bark = function() { return "Woof"; } var scoobydoo = new Dog("Great Dane") snoopy.bark() // Woof scoobydoo.bark() // undefined 366
Дополнительные задачи в онлайн тренажере codeWars 1. 2. 3. 4. 5. 6. 7. 8. Привет, Счастливый Кодевариор! (Hello Happy Codevarrior!) 8кю Интерфейс SantaClausable (SantaClausable Interface) 7кю Создание базы (Create the base - Dungeon crawler #1) 7кю Улучшение Math.round(x) (Improving Math.round(x)) 8кю Сломанный счетчик (Broken Counter) 8кю Мед для пчелы (Honey to the Bee) 7кю Пользовательские фильтры массива (Custom Array Filters) 6кю Помощники массивов (Array Helpers) 6кю Итоговая практическая работа Задание 1. 7 На YouTube была кнопка "Like" и "Dislike", которая позволяла пользователям выражать свое мнение о просмотренном контенте. Она была настроена таким образом, что человеку не может одновременно нравится и не нравится видео. Нажатие кнопки, которая уже была нажата, отменит предыдущее действие. Если нажать кнопку "Like" после нажатия кнопки "Dislike", кнопка "Like" перезапишет предыдущее состояние "Dislike". То же самое верно и для обратного пути. Создайте функцию, которая принимает последовательность нажатых кнопок и возвращает конечное состояние. function likeOrDislike(buttons) { } likeOrDislike([Dislike]) // Dislike likeOrDislike([Like,Like]) // Nothing likeOrDislike([Dislike,Like]) // Like likeOrDislike([Like,Dislike,Dislike]) // Nothing likeOrDislike([Like,Like,Dislike,Like,Like,Like,Like,Dislike]) // Dislike likeOrDislike([]) // Nothing 367
Задание 2. 7 Чингел тренируется перед соревнованиями по гребле, которые состоятся в эту субботу. Он изо всех сил старается выиграть этот турнир, для чего ему нужно выяснить, сколько времени требуется, чтобы преодолеть определенную дистанцию. Необходимо написать функцию, которой будет предоставлена общая дистанция путешествия, скорость лодки и то, идет ли она вниз по течению или вверх по течению. Скорость течения и направление гребли будут указаны в виде строки. Функция должна возвратить время, затраченное на преодоление заданного расстояния. Результат необходимо округлить до 2 позиций. function time(distance,boatSpeed,stream) { } time(24,10,"Downstream 2") // 2 time(24,14,"Upstream 2") // 2 time(54,28,"Downstream 3") // 1.74 Задание 3. 7 Напишите функцию, которая принимает массив целых чисел и возвращает одно из следующих значений: • • • "yes, ascending" — если числа в массиве отсортированы в порядке возрастания; "yes, descending" — если числа в массиве отсортированы в порядке убывания; "no" — в противном случае. Можно быть уверенным, что массив всегда будет действительным, и всегда будет один правильный ответ. 368
function isSortedAndHow(array) { } isSortedAndHow([1, 2]) // 'yes, ascending' isSortedAndHow([15, 7, 3, -8]) // 'yes, descending' isSortedAndHow([4, 2, 30]) // 'no' Задание 4. 7 Непустой массив a длины n называется массивом всех возможностей, если он содержит все числа между [0,a.длина-1].Напишите функцию с именем isAllPossibilities, которая принимает целочисленный массив и возвращает true, если массив представляет собой массив всех возможностей, в противном случае false. function isAllPossibilities(x) { } isAllPossibilities([0,1,2,3]) // true isAllPossibilities([1,2,3,4]) // false Задание 5. 8 Напишите код функции, которая принимает числовой параметр n. Функция должна определить, является ли число n одной из пяти констант объекта Number и вернуть одну из строк соответственно: "Input number is Number.MAX_VALUE" "Input number is Number.MIN_VALUE" "Input number is Number.NaN" "Input number is Number.NEGATIVE_INFINITY" "Input number is Number.POSITIVE_INFINITY" Для других значений "Input number is xxx", где xxx означает число n. function whatNumberIsIt(n) { } 369
whatNumberIsIt(1/0) // "Input number is Number.POSITIVE_INFINITY" whatNumberIsIt(100) // "Input number is 100" whatNumberIsIt(1.7976931348623157e+308) // "Input number is Number.MAX_VALUE" Задание 6. 8 Напишите код функции, которая принимает 3 параметра: r, g, b. Они означают значение цвета красный, зеленый и синий соответственно. Диапазон значений составляет 0-255. Используйте метод toString(16) для преобразования чисел r, g, b в шестнадцатеричную строку и объедините их в цветовой код для веба и верните его. Цветовой код должен начинаться с "#", далее идут 2 символа для каждого цвета. function colorOf(r,g,b) { } colorOf(255,0,0) // "#ff0000" colorOf(0,111,0) // "#006f00" colorOf(1, 2 ,3) // "#010203" Задание 7. 7 Напишите функцию, которая заменяет в строке text каждый n-й символ oldValue на символ newValue. Функция должна быть чувствителен к регистру. Если n равно 0 или отрицательно, или если оно больше, чем количество oldValue, функция должна вернуть исходный текст без изменений. function replaceNth(text, n, oldValue, newValue) { } 370
replaceNth("Vader said: No, I am your father!", 2, 'a', 'o') // "Vader soid: No, I am your fother!" replaceNth("Vader said: No, I am your father!", 4, 'a', 'o') // "Vader said: No, I am your fother!" replaceNth("Vader said: No, I am your father!", 6, 'a', 'o') // "Vader said: No, I am your father!" Задание 8. 7 Помоги Судзуки сосчитать его овощи. Судзуки — главный монах своего монастыря, поэтому он должен следить за тем, чтобы кухня работала на полную мощность, чтобы накормить своих учеников и жителей деревни, которые ежедневно приходят на обед. На этой неделе у него возникли проблемы с поставками, и все овощи перепутались. Есть два важных аспекта приготовления пищи на его кухне: все должно быть сделано в гармонии, и ничто не может быть потрачено впустую. Поскольку монахи ведут учет, первым делом они сортируют смешанные овощи, а затем подсчитывают их, чтобы убедиться, что их достаточно, чтобы накормить всех студентов и жителей деревни. Монах получает следующие продукты: "cabbage", "carrot", "celery", "cucumber", "mushroom", "onion", "pepper", "potato", "tofu", "turnip" Составьте функцию, которая возвращает массив овощей с количеством каждого овоща в порядке убывания. Если овощ из списка отстутствует, не включайте его в итоговый массив. Если в смеси есть какие-либо другие овощи, откажитесь от них. Если количество двух овощей одинаковое, отсортируйте их в обратном алфавитном порядке. function countVegetables(string) { } s1 = 'potato tofu cucumber cabbage turnip pepper onion carrot celery mushroom potato tofu cucumber cabbage' 371
countVegetables(s1) // [[2, 'tofu'], [2, 'potato'], [2, 'cucumber'], [2, 'cabbage'], [1, 'turnip'], [1, 'pepper'], [1, 'onion'], [1, 'mushroom'], [1, 'celery'], [1, 'carrot']] s2 = `mushroom chopsticks chopsticks turnip mushroom carrot mushroom cabbage mushroom carrot tofu pepper cabbage potato cucumber mushroom mushroom mushroom potato turnip chopsticks cabbage celery celery turnip pepper chopsticks potato potato onion cabbage cucumber onion pepper onion cabbage potato tofu carrot cabbage cabbage turnip mushroom cabbage cabbage cucumber cabbage chopsticks turnip pepper onion pepper onion mushroom turnip carrot carrot tofu onion tofu chopsticks chopsticks chopsticks mushroom cucumber chopsticks carrot potato cabbage cabbage carrot mushroom chopsticks mushroom celery turnip onion carrot turnip cucumber carrot potato mushroom turnip mushroom cabbage tofu turnip turnip turnip mushroom tofu potato pepper turnip potato turnip celery carrot turnip` countVegetables(s2) // [[15, 'turnip'], [15, 'mushroom'], [13, 'cabbage'], [10, 'carrot'], [9, 'potato'], [7, 'onion'], [6, 'tofu'], [6, 'pepper'], [5, 'cucumber'], [4, 'celery']] Задание 9. 7 На фабрике принтер печатает этикетки для коробок. Для одного вида коробок принтер должен использовать цвета, которые для простоты обозначаются буквами от a до m. Цвета, используемые принтером, записываются в управляющую строку. Например, «хорошей» управляющей строкой будет aaabbbbhaijjjm, это означает, что принтер использовал три раза цвет a, четыре раза цвет b, один раз цвет h, затем один раз цвет a и так далее. Иногда возникают проблемы: отсутствие цветов, техническая неисправность и выдается «плохая» управляющая строка, например, aaaxbbbbyyhwawiwjjjwwm с буквами не от a до m. Необходимо написать функцию printer_error, которая, учитывая строку, вернет частоту ошибок принтера в виде строки, представляющей 372
рациональное число, числителем которого является количество ошибок, а знаменателем — длина управляющей строки. Строка имеет длину, большую или равную единице, и содержит только буквы от a до z. function printerError(s) { } printerError ("aaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbmmmmmmmm mmmmmmmmmmmxyz") // "3/56" Примечание: используйте регулярное выражение и метод includes() Задание 10. 7 Дана строка, преобразуйте каждый символ строки в соответствующий код символа ASCII и соедините их вместе, чтобы создать число total1 'ABC': 'A' = 65, 'B' = 66, 'C' = 67 → 656667 Затем замените числа 7 на число 1 и назовите это новое число total2 total1 = 656667 total2 = 656661 Затем верните разницу между суммой цифр в total1 и total2: (6 + 5 + 6 + 6 + 6 + 7) - (6 + 5 + 6 + 6 + 6 + 1) ----------------------------6 function calc(x){ } calc('abcdef') // 6 calc('ifkhchlhfd') // 6 calc('aaaaaddddr') // 30 373
Задание 11. 6 Дано неотрицательное целое число n, напишите функцию, возвращающую сумму цифр числа n. Если полученная сумма содержит более одной цифры, то необходимо снова найти сумму цифр этого числа до тех пор, пока не будет получено однозначное число. 16 → 1 + 6 = 7 942 → 9 + 4 + 2 = 15 → 1 + 5 = 6 function digitalRoot(n) { } digitalRoot(16) // 7 digitalRoot(456) // 6 Задание 12. 7 Если a = 1, b = 2, c = 3 ... z = 26 то l + o + v + e = 54 и f + r + i + e + n + d + s + h + i + p = 108 Так что дружба в два раза сильнее любви Входные данные всегда будут в нижнем регистре и никогда не будут пустыми. function wordsToMarks(string){ } wordsToMarks("attitude") // 100 wordsToMarks("friends") // 75 wordsToMarks("family") // 66 374
Задание 13. 7 Напишите функцию, которая принимает строку в качестве своего первого параметра. Эта строка будет строкой слов, второй параметр будет целым числом — номером слова, чтобы найти соответствующее слово в данной строке. Первое слово имеет номер 0. Третий параметр — это число повторений выбранного слова. Функция должна возвращать строку из повторений выбранного слова с дефисами между каждым словом. function modifyMultiply (str,loc,num) { } modifyMultiply("This is a string", 3, 5) // "string-string-string-stringstring" modifyMultiply("Creativity is the process of having original ideas that have value. It is a process; it's not random.", 8, 10) // "that-that-thatthat-that-that-that-that-that-that" modifyMultiply("Everything happening around me is very random. I am enjoying the phase, as the journey is far more enjoyable than the destination.", 2, 5) // "around-around-around-around-around" Задание 14. 7 Дан массив целых чисел нечетной длины, в котором все числа одинаковы, за исключением одного числа. Напишите код функции, которая принимает такой массив, и возвращает это единственное другое число. function stray(numbers) { } stray([1, 1, 2]) // 2 375
Задание 15. 6 Напишите код функции, которая вычитает один массив из другого и возвращает результат. Функция должна удалить все значения из массива a, которые присутствуют в массиве b, сохраняя их порядок. function arrayDiff(a, b) { } arrayDiff([1,2], [1]) // [2] arrayDiff([1,2,2], [1]) // [2,2] arrayDiff([1,2,3], [1,2]) // [3] Задание 16. 6 Напишите функцию, которая принимает строку, содержащую одно или несколько слов и возвращает ту же строку, но с перевернутыми словами, длиной пять или более букв (точно так же, как название этой задачи). function spinWords(string $str): string { } spinWords("Welcome") // "emocleW" spinWords("Hey fellow warriors") // "Hey wollef sroirraw" spinWords("This is a test") // "This is a test" Задание 17. 6 Если мы перечислим все натуральные числа до 10, кратные 3 или 5, мы получим 3, 5, 6 и 9. Сумма этих кратных равна 23. 376
Напишите функцию так, чтобы она возвращала сумму всех чисел, меньших заданного числа и кратных 3 или 5. Если заданное число отрицательно, верните 0. function solution(number) { } solution(10) // 23 Задание 18. 5 Спагетти — моя любимая еда, поэтому я всегда предпочитаю оставлять самый длинный кусок напоследок... Напишите код функции, чтобы помочь мне узнать, какой кусок спагетти самый длинный. Старайтесь не писать код, который выглядит как спагетти-код! Я ем особую марку спагетти (очень трудно найти в продаже), каждая часть которой имеет уникальный идентификатор в верхнем регистре. Все мои тарелки прямоугольные. Они могут иметь любой (не буквенный) фоновый рисунок. Если окажется несколько самых длинных кусков спагетти, пусть функция вернет любой из них (все спагетти имеют одинаковый вкус). Если на тарелке нет спагетти, пусть функция вернет пустую строку. AAAAAAAAA ________A__CCC_ B C A C _B___C__A____C_ B C C _B___CCCCCCCCC_ AAAAAAAA____ ____________ BBBBBBBBBBB_ ____________ CCCCCC______ ответ: B ответ: C var spaghettiCode = function(plate) { } 377
Задание 19. 5 Напишите функцию rgb так, чтобы передача десятичных значений RGB приводила к возврату их шестнадцатеричного представления. Допустимые десятичные значения для RGB: 0–255. Любые значения, выпадающие из этого диапазона, должны быть округлены до ближайшего допустимого значения. Ответ всегда должен состоять из 6 символов. function rgb(r, g, b) { } rgb(0, 0, 0) // '000000' rgb(0, 0, -20) // '000000' rgb(173,255,47) // 'ADFF2F' Задание 20. 5 При работе со значениями цвета иногда бывает полезно извлечь для цвета отдельные значения компонентов красного, зеленого и синего (RGB). Напишите функцию, которая будет это делать. Функция принимает в качестве параметра шестнадцатеричную строку цвета без учета регистра (например, "#FF9933" или "#ff9933"). Функция возвращает объект со структурой {r: 255, g: 153, b: 51}, где r, g и b находятся в диапазоне от 0 до 255. Функция не должна поддерживать сокращенную форму шестнадцатеричной записи (например, "#FFF"). function hexStringToRGB(hexString) { } hexStringToRGB("#FF9933") // {r:255, g:153, b:51} 378
Задание 21. 5 Напишите функцию, которая при задании URL-адреса в виде строки возвращает в виде строки только доменное имя. function domainName(url) { } domainName("http://google.com") // "google" domainName("http://google.co.jp") // "google" domainName("www.xakep.ru") // "xakep" Задание 22. 4 Напишите функцию так, чтобы она удаляла весь текст, следующий за любым из переданных маркеров комментариев. Все пробелы в конце строки также должны быть удалены. var result = solution("apples, pears # and bananas\ngrapes\nbananas !apples", ["#", "!"]) // result should == "apples, pears\ngrapes\nbananas" На входе На выходе apples, pears # and bananas apples, pears grapes grapes bananas !apples bananas function solution(input, markers) { } 379
solution ("apples, plums % and bananas\npears\noranges !applesauce", ["%", "!"]) // "apples, plums\npears\noranges" solution ("Q @b\nu\ne -e f g", ["@", "-"]) // "Q\nu\ne" Задание 23. kumite Составьте функцию, которая возвращет наибольшее число из 3 заданных целых чисел. Но! Код не должен содержать ни одной буквы английского алфавита! _ = () => _(1,2,3) // 3 _(1,5,2) // 5 _(10,2,3) // 10 Задание 24. kumite Напишите функцию, которая возвращает сумму натуральных чисел от A до B. Но! Код не должен содержать ни одной буквы английского алфавита! _ = (_1,_2) => _(0,5) // 15 _(5,10) // 45 _(10,23) // 231 Решение: _ = (_1,_2) => (_2 == _1) ? _1: _2 + _(_1,_2-1) 380
Задание 25. kumite В студенческой группе учатся мальчики и девочки. Иногда важно знать кого из них больше или меньше, чтобы подготовиться к празднику. Разработайте код функции, возвращающей эту информацию. Входным параметром функции будет последовательность 1 и –1, где 1 символизирует мальчика, –1 — девочку. Есть только одно условие — код должен содержать английских слов меньше, чем русских! когоБольше = (...группа) => { } когоБольше(1, -1, 1, 1, 1, -1, -1) // Девочек на 1 меньше когоБольше(1, -1, 1, 1, 1, -1, -1, -1, -1) // Девочек на 1 больше когоБольше(1, -1, 1, 1, 1, -1, -1, -1) // Девочек и мальчиков равное количество Задание 26. kumite Разработайте код функции, которая по заданому иностранному брэнду будет возвращать отечественный аналог. брэнды = { МакДоналдс: "Вкусно и точка", Тинькофф: "Т-Банк", ЛеруаМерлен: "ЛеманаПро", YouTube: "Rutube", Доллар: "Рубль" } Если заданный брэнд не включен в перечень, то функция должна вернуть фразу «брэнд не распознан». Примечание! Код функции не может содержать более 4 английских слов. 381
импортозамещение = (брэнд) => { } импортозамещение("YouTube") // "Rutube" импортозамещение("Intel") // "брэнд не распознан" Задание 27. 6 Необходимо найти слово в исходном предложении, набравшее наибольшее количество баллов. Каждая буква слова оценивается в соответствии с ее положением в алфавите: a = 1, b = 2, c = 3 и т. д. Например, оценка abad является 8 (1 + 2 + 1 + 4). Необходимо вернуть слово с наивысшим баллом в виде строки. Если два слова имеют одинаковый рейтинг, вернуть слово, которое встречается раньше в исходной строке. Все буквы будут строчными, и все введенные данные будут действительными. function high(x) { } high('man i need a taxi up to ubud'), 'taxi'); high('what time are we climbing up the volcano') // 'volcano' high('take me to semynak') // 'semynak' high('aa b') // 'aa' high('b aa') // 'b' 382
ОБЪЕКТНАЯ МОДЕЛЬ БРАУЗЕРА Совокупность объектов JavaScript включает две модели: объектную модель браузера BOM (Browser Object Model) и объектную модель документа DOM (Document Object Model). Модели имеют древовидную структуру. Объектная модель браузера — это иерархическая система объектов, предназначенных для управления окнами браузера и обеспечения их взаимодействия. Каждое из окон браузера представляется объектом window, центральным объектом BOM. Объектная модель браузера до сих пор не стандартизирована, однако спецификация находится в разработке. На более низком уровне иерархии объектная модель браузера обеспечивает поддержку следующих возможностей: • управление фреймами; • поддержка задержки в исполнении кода и организация периодического вызова фрагмента кода на выполнение; • диалоги с пользователем; • управление адресом загрузки браузером веб-страницы; • доступ к информации о браузере; • доступ к информации о параметрах монитора; • ограниченное управление историей просмотра страниц; • поддержка работы с http-cookie. 383
Объект — это некоторая сущность или модель реального мира. Объект имеет описательные характеристики, которые называют свойствами объекта. Объект может совершать какие-либо действия, которые называют методами объекта. Объекты существуют в какой-то среде, в которой с ними происходят события. события Объект свойства методы На диаграмме перечислены далеко не все объекты. Более подробную информацию можно найти в литературе, указанной в библиографии. Доступ к свойствам объекта осуществляется через точечную нотацию, которая начинается с вершины иерархии (window можно опускать) и заканчивается названием свойства объекта. Свойства объектов сформулированы на языке HTML в виде атрибутов тегов соответствующих объектов. window.document.forms[0].elements[1].checked 384
Пример показывает доступ к свойству checked одного из элементов формы. Каждая форма, расположенная на веб-странице, имеет свой порядковый номер, соответствующий последовательности создания форм (нумерация начинается с 0). Каждый элемент формы также пронумерован в порядке создания. Но если объектам даны имена через атрибут NAME, то вместо имен коллекций с порядковыми номерами можно использовать оригинальные имена. Рассмотрим пример: <HTML> <HEAD> <TITLE> тест </TITLE> <SCRIPT> function проверка () можно document.forms[0] { var doc=document.form1; if ((doc.вариант2.checked) && (doc.вариант4.checked) && (doc.вариант6.checked)) можно doc.elements[3].checked alert ("Правильно") else alert ("Неправильно"); } </SCRIPT> </HEAD> <BODY> <FORM METHOD="post" NAME=”form1”> <P><STRONG>Вопрос 1</STRONG>. К тригонометрическим функциям относятся:</P> <P> <INPUT TYPE = ”checkbox” NAME = “вариант1”> парабола <BR> <INPUT TYPE = ”checkbox” NAME = “вариант2”> косинусоида <BR> <INPUT TYPE = ”checkbox” NAME = “вариант3”> гипербола <BR> <INPUT TYPE = ”checkbox” NAME = “вариант4”> синусоида <BR> <INPUT TYPE = ”checkbox” NAME = “вариант5”> гипотенуза <BR> <INPUT TYPE = ”checkbox” NAME = “вариант6”> тангенсоида </P> <P> <INPUT TYPE=”button” VALUE=”Проверить” ONCLICK=”проверка ()”> </P> </FORM> </BODY> </HTML> 385
Объект Window Объект window — наивысший объект в иерархии JavaScript, представляющий собой открытое окно браузера. Свойство opener возвращает ссылку на объект Window, скрипт которого открыл текущее окно. window.opener document.write (opener.location) window.closed Свойство closed возвращает null, если окно никогда не открывалось; значение true, если окно закрывается; false — еще открыто. Свойство Описание innerWidth полная ширина окна браузера вместе с полосой прокрутки (если она есть) innerHeight полная высота окна браузера вместе с горизонтальной полосой прокрутки (если она есть) outerWidth возвращает внешнюю ширину окна браузера, включая все элементы интерфейса (панели инструментов, полосы прокрутки и т. д.). Доступно только для чтения 386
Продолжение табл. Свойство outerHeight Описание возвращает внешнюю высоту окна браузера, включая все элементы интерфейса (панели инструментов, полосы прокрутки и т. д.). Доступно только для чтения pageXOffset возвращает количество пикселей, на которые документ был прокручен от верхнего левого угла окна браузера. Идентично свойству scrollX. Доступно только для чтения scrollX возвращает количество пикселей, на которые документ был прокручен от верхнего левого угла окна. Идентично свойству pageXOffset. Для обеспечения кроссбраузерной совместимости лучше использовать pageXOffset. Доступно только для чтения pageYOffset возвращает количество пикселей, на которые документ был прокручен от верхнего левого угла окна браузера. Идентично свойству scrollY. Доступно только для чтения scrollY возвращает количество пикселей, на которые документ был прокручен от верхнего левого угла окна. Идентично свойству pageYOffset. Для обеспечения кроссбраузерной совместимости лучше использовать pageYOffset. Доступно только для чтения screenX возвращает координату x (по горизонтали) окна браузера относительно экрана screenY возвращает y (вертикальную) координату окна браузера относительно экрана let myWin = window.open("", "", "left=700, top=350, width=200, height=100") let x = myWin.screenX; let y = myWin.screenY screenLeft возвращает положение окна браузера по оси x (по горизонтали) относительно экрана screenTop возвращает положение окна по оси y (по вертикали) относительно экрана 387
Методы 1. open window.open (""[, ""] [, "" ]), где  — указатель ресурса Интернета;  — имя окна;  — необязательные параметры. Метод открывает новое окно с именем  и загружает в него документ, расположенный по адресу . Если ни один из списка параметров  не указан, используются значения по умолчанию. Если же указан хотя бы один параметр из списка , все не указанные параметры принимают значение no. Параметр toolbar location directories status menubar scrollbars resizable width height top left Применение стандартная панель инструментов, включая кнопки Forward, Back, перехода к домашней странице и печати адресная строка панель стандартных гиперссылок строка состояния строка меню линейки прокрутки изменение размера окна ширина окна в пикселях высота окна в пикселях отступ от верхнего края экрана отступ от левого края экрана Примеры <SCRIPT> function o (f) { window.open (f, 'tmp', "status=yes, toolbar=yes, location=yes, height=433, width=283") } </SCRIPT> <A HREF="javascript: o('w1.html')"> <IMG SRC="w1small.jpg"> </A> 388
<A HREF="javascript: window.open ('19.4.htm?269000.JPG', 'foto', 'height=400, width=300')"> <IMG SRC="image2.jpg"> </A> 2. close .close () Метод закрывает окно . Где  — имя окна. Например. window.close () self.close () FotoWin.close () 3. setInterval window.setInterval (, , , …), где  — совокупность операторов или функций, вызываемых периодически через  миллисекунд; ... — необязательные аргументы. Метод задает периодическое выполнение  через  миллисекунд и возвращает уникальный идентификатор, который можно использовать для отмены его действия. 4. clearInterval window.clearInterval (), где  — уникальный идентификатор. Метод отменяет setInterval с указанным идентификатором. Пример Скрипт генерирует новые окна с интервалом в 1 с и располагает их случайным образом по экрану var число_окон = 5 var интервал_id = setInterval ("открыть_окно ()", 1000) function открыть_окно () { s = число_окон-n = 'foto' + s x = Math.random () * 1500 389
y = Math.random () * 1600 window.open ('', n, 'height=400, width=500, top=' + y + ', left=' + x) if (число_окон == 0) clearInterval (интервал_id) } 5. setTimeout window.setTimeout (, , , …), где  — совокупность операторов или функций, вызываемых через  миллисекунд; ... — необязательные аргументы — параметры функции . setTimeout(greeting, 3000, "Привет, Мир!") function greeting(value) { console.log(value) } Метод задает задержку выполнения  на  миллисекунд и возвращает уникальный идентификатор, который можно использовать для отмены его действия. Данный метод можно применять для задания времени ожидания ответа на вопрос теста. 6. clearTimeout window.clearTimeout (), 390
где  — уникальный идентификатор. Метод отменяет setTimeout с указанным идентификатором. 7. Методы alert, confirm, prompt предназначены для создания диалоговых окон ввода-вывода информации. window.alert (). Метод выводит значение  в диалоговое окно.  = window.prompt ( [,]). Метод создает окно ввода данных. Где  — выводимая в окно информация-приглашение;  — запрашиваемое значение по умолчанию;  — переменная, в которую передается введенное значение, если нажата кнопка “Ok”, или служебное значение null, если нажата кнопка “Cancel”.  = window.confirm (). Метод создает диалоговое окно выбора из двух вариантов — «Да» или «Нет» и возвращает соответственно значения true или false. Где  — выводимая в окно информация-подсказка. 8. moveTo window.moveTo (,). Метод перемещает окно в точку с координатами (,). Эта координата попадает в левый верхний угол окна. 9. moveBy window.moveBy (,). Метод перемещает окно на расстояние  пикселей по оси х и на расстояние  пикселей по оси у. 391
10. resizeTo window.resizeTo (,). Метод изменяет размеры окна до значений  и  пикселей по ширине и высоте соответственно. 11. resizeBy window.resizeBy (,). Метод изменяет размеры окна на значения  и  пикселей по ширине и высоте соответственно (приращение окна). <HTML> <SCRIPT> function o () { self.resizeTo (100,100) for (i=1; i<50; i++) self.resizeBy (i, i) } </SCRIPT> <BODY> <A HREF="javascript: o()"> click me! </A> </BODY> </HTML> 12. scrollTo window.scrollTo (,). Метод прокручивает документ до заданных координат (,). Чтобы метод scrollTo() работал, размер документа должен быть больше размера экрана, и полоса прокрутки должна быть видимой. window.scrollTo(0, 500) // страница прокрутится вверх на 500px 13. scrollBy window.scrollBy (,). 392
Метод прокручивает документ на заданные числа  и  в системе координат относительно ее текущего положения. 14. scrollIntoView Метод прокручивает страницу так, чтобы элемент  оказался вверху (или внизу) видимой части окна браузера .scrollIntoView ([]), где  — ссылка на html-элемент,  — необязательный параметр, который указывает направление прокрутки (true — вверху, false — внизу). <H2 id="theme1">Подготовка и повышение квалификации педагогических кадров</H2> … setTimeout(function () { theme1.scrollIntoView(); }, 3000); 14. window.addEventListener("scroll", function(event) {}) В веб-разработке событие прокрутки страницы (scroll) часто используется для создания динамических и интерактивных интерфейсов. Конструкция window.addEventListener ("scroll", function (event) {}) позволяет «подписаться» на событие прокрутки окна браузера и выполнять определенный код каждый раз, когда пользователь прокручивает страницу. Это может быть полезно для реализации эффектов параллакса, подгрузки контента по мере прокрутки, изменения стиля элементов или отображения кнопки «Наверх». Рассмотрим простой пример, в котором при прокрутке страницы выводится текущая вертикальная позиция прокрутки в консоль window.addEventListener("scroll", function(event) { const scrollTop = window.pageYOffset || document.documentElement.scrollTop; console.log ("Текущая позиция прокрутки: " + scrollTop + "px"); }); 393
В этом примере функция-обработчик вызывается каждый раз при прокрутке страницы. Внутри нее мы получаем значение вертикальной прокрутки с помощью pageYOffset (или scrollTop для совместимости) и выводим его в консоль. Такой подход позволяет отслеживать, насколько пользователь прокрутил страницу, и на основе этого создавать различные интерактивные эффекты. Объект Location В объекте location представлен адрес (URL) загруженного htmlдокумента. Существует возможность записывать в location.href свои значения (см. пример на стр. 147). В приведенном ниже примере щелчок по кнопке загружает в текущее окно новую страницу: <FORM> <INPUT TYPE=”button” VALUE="Rambler" ONCLICK="location.href='http://www.rambler.ru'; "> </FORM> Каждое свойство объекта location представляет различную часть URL. Следующий список показывает связи между частями URL и свойствами location: p ro to co l: //h o stn a me: p o r t p a th n a me sea rch h a sh protocol hostname port строка, содержащая начальную часть URL, до двоеточия включительно доменное имя или IP адрес часть URL, содержащая номер порта 394
pathname search hash часть URL, содержащая путь к файлу на веб-сервере строка, содержащая любую информацию запроса, присоединенную к URL, начинающаяся с вопросительного знака (?). часть URL, начинающаяся с символа (#). Не путайте объект location со свойством location объекта document, которое нельзя изменять (document.location), но можно менять значение свойства объекта location. Пример Следующие два утверждения эквивалентны и изменяют URL текущего окна: window.location.href = "http://mozilla-russia.org/" window.location = "http://mozilla-russia.org/" location.search.substring (1) С помощью свойства search можно передавать информацию между веб-страницами. На одной странице строится URL cо знаком вопроса и данными, а в принимающей странице эти данные можно извлечь строкой, показанной в предыдущем примере. Метод substring возвращает подстроку из строки. Подробнее о методе смотри на странице 220. Методы reload ([]). Повторная загрузка страницы. Где  — необязательный параметр. Принимает значение “False” для загрузки из КЭШа, “True” для загрузки с сервера. Пример: location.reload (true) replace (). Замена страницы. Где  — указатель на новую страницу. 395
Свойство/ Метод Описание hash устанавливает или возвращает часть url-адреса, начинающуюся с символа #, включая знак решетки (#) assign() загружает новый документ в текущее окно браузера, метод replace() удаляет текущий url-адрес из истории документа, в отличие от assign() host возвращает хост (ip-адрес или домен) и порт urlадреса, можно установить свойство host для перехода к тому же url-адресу с новым хостом и портом. Если номер порта не указан в url-адресе или это порт по умолчанию (80 для http) или (443 для https), большинство браузеров вернут пустую строку hostname возвращает хост (ip-адрес или домен) url-адреса или устанавливает новое свойство hostname для перехода к тому же url-адресу с новым именем хоста origin возвращает протокол, имя хоста и номер порта url-адреса. Доступно только для чтения. Если номер порта не указан в url-адресе или это порт по умолчанию, например 80 (Http) или 443 (https), некоторые браузеры не будут отображать номер порта pathname устанавливает или возвращает путь url-адреса страницы port устанавливает или возвращает номер порта urlадреса. Если номер порта не указан в url-адресе или это порт по умолчанию (80 для http) или (443 для https), большинство браузеров вернут пустую строку protocol устанавливает или возвращает протокол текущего url-адреса, включая двоеточие “:”. Примеры протоколов: • file: • ftp: • http: • https: • mailto search возвращает часть url-адреса, содержащую строку запроса, включая вопросительный знак “?” или устанавливает эту часть 396
П р и м е р. Передача данных между страницами page1.htm <HTML> <BODY ONLOAD="location.href='page2.htm?DOG07.GIF'”> </BODY> </HTML> page2.htm <HTML> <SCRIPT> h=window.location.search.substring(1) document.write (h + "<BR>") document.write ("<img src=" + h + ">") </SCRIPT> </HTML> События onChangeHash Объект History Объект History хранит список веб-страниц, посещенных в текущем сеансе работы. Часто такой список называют журналом. Можно выделить три части списка. Первая часть содержит страницы, на которые можно вернуться по щелчку на кнопке «Назад» окна браузера, вторая часть — текущая страница и третья часть содержит страницы, на которые можно вернуться по щелчку на кнопке «Вперед». Однако если происходит возврат на посещенную страницу, а затем переход на новую, то третья часть журнала очищается. Методы window.history.back([]) перемещение назад по первой части журнала. Где  — число страниц. window.history.forward([]) перемещение вперед по третьей части журнала. 397
window.history.go() перемещение на любую страницу в журнале. Если  — отрицательное число, то перемещение идет по первой части журнала, если  — положительное — по третьей части, если  = 0, то происходит обновление текущей страницы. Пример <BODY> <A HREF="page3.htm"> страница 3 </A> <A HREF="page4.htm"> страница 4 </A> <A HREF="page1.htm"> страница 1 </A> <INPUT TYPE=”button” VALUE=”назад” ONCLICK="history.back()"> <INPUT type=”button” value=”вперед” ONCLICK = “window.history.forward()”> </BODY> Метод pushState добавляет и активирует запись в стек истории сеансов браузера. pushState (, “”, [url]), где  представляет собой объект JavaScript, связанный с новой записью в истории, созданной pushState(). const s = { 'page': 2, 'user': 3 } const url = 'webpage.html' history.pushState(state, '', url) Объект Screen Объект screen предназначен для определения разрешения монитора компьютера, в котором выполняется скрипт. Свойства (только для чтения) 398
Свойство Описание availHeight высота доступной области экрана height высота экрана (в пикселях) availWidth ширина доступной области экрана width ширина экрана (в пикселях) colorDepth глубина цвета (в битах) pixelDepth цветовое разрешение экрана (в битах на пиксель) orientation ориентация экрана Объект Navigator или война браузеров Известно, что для отображения веб-страниц предназначены браузеры. Наиболее популярными «отображателями» веб-страниц являются: 1. Microsoft Internet Explorer (пер. с англ. Explorer — путешественник, исследователь). 2. Microsoft Edge. 3. Mozilla Firefox (пер. с англ. Firefox — огненная лиса, в честь которой, по словам разработчиков, и назван браузер). 4. Opera (пер. с англ. Opera — опера). 5. Apple Safari (пер. с арабск. Safari — поход, путешествие, турпоездка, длительное путешествие в экзотические страны). 6. Konqueror (Конкерор, от англ. Conqueror + KDE — завоеватель, победитель). 7. Google Chrome (пер. с англ. Chrome — металл хром или цветной фотографический транспарант (постер) с блестящей, сияющей поверхностью). При разработке браузеров, как и другого программного обеспечения, выделяют основные модули и компонуют их в самостоятельный так называемый движок, который затем может быть включен в состав других разрабатываемых программ, решаемых подобные задачи. Браузерные движки, как и браузеры, имеют собственное имя. 399
Браузер Microsoft Internet Explorer Microsoft Edge Mozilla Firefox Логотип Движок Trident Проводник (Windows Explorer), справка Microsoft Windows, Outlook и Outlook Express, InfoPath, Media Player, Encarta Blink Chrome 28+, Opera 15+, Яндекс.Браузер, браузеры на основе Chromium, выпущенные после 2013 года Gecko, 60+ Quantum Opera Использование движка Почтовый клиент Thunderbird, календарь Sunbird и IRC-клиент Chatzilla, свободный набор программ для работы в Интернете SeaMonkey Presto, c 2013 г. Adobe GoLive, Dreamweaver Blink Konqueror KHTML 400 как менеджер файлов в KDE
Продолжение табл. Браузер Движок Логотип Apple Safari WebKit Использование движка Adobe Integrated Runtime (AIR) — платформо-независимая среда для запуска приложений, Android — платформа для мобильных телефонов, Google Chrome WebKit, c 2013 г. Blink LeechCraft — кроссплатформенный модульный интернетклиент с плагиномбраузером Poshuku Все браузеры стремятся поддерживать стандарты разработки вебстраниц, такие как HTML, CSS, JavaScript, DOM, форматы отображения веб-графики. Однако в реальности существует различие в поддержке веб-стандартов различными браузерами. Кроме того, каждый движок «понимает» отличные от стандарта методы, «непонятные» другим движкам. Все это несколько усложняет разработку вебдокументов и веб-приложений. В JavaScript существует объект Navigator, который хранит информацию о браузере посетителя (клиента) текущей веб-страницы. В таблице собраны свойства, общие для нескольких браузеров. Свойство объекта Navigator Возвращаемое значение appCodeName Внутреннее кодовое имя браузера appName Название браузера appVersion Внутренний номер версии браузера cookieEnabled true/false — разрешено/запрещено использовать кукиз onLine true/false — установлен браузер для online или для offline просмотра (Файл → Работать автономно) 401
Продолжение табл. Свойство объекта Navigator Возвращаемое значение platform Имя платформы, на которой запущен браузер. Например, Win32 plugins Коллекция названий всех подключенных к браузеру модулей userAgent Строка, содержащая значения свойств appCodeName, appName, appVersion и некоторых других У каждого браузера помимо перечисленных в таблице есть свой дополнительный набор свойств. На рисунках названия свойств выделены полужирным шрифтом. Скрипт, с помощью которого можно получить список всех свойств любого объекта JavaScript, приведен на странице 60. 402
Например, метод создания модального диалогового окна showModalDialog хорошо работает пока только в Internet Explorer. Поэтому для корректности работы кода и в других браузерах, можно использовать стандартный метод open объекта window. var браузер = navigator.appName if (браузер == "Microsoft Internet Explorer") окно_проверка_доступа = window.showModalDialog ("tests/PanelCheckAvtor.htm", null, "dialogWidth:20em; dialogHeight:20em, center:1") else { окно_проверка_доступа = window.open ("tests/CheckAvtor.htm", "проверка_доступа", "width=430, height=300, status=no, resizable=yes, scrollbars=yes, menubar=yes, toolbar=yes, status=yes") окно_проверка_доступа2.focus () } Как видно из скриншотов, значение свойства userAgent представляет собой строку с большим числом данных, включающих в себя название браузера и его кодовое имя, версию браузера и название движка, 403
название операционной системы и так далее. Для браузера от Microsoft в качестве названия браузера указано короткое имя MSIE, что раскрывается как MS Internet Explorer. Извлечь нужную информацию из строки можно с помощью перечисленных ранее методов объекта String. Например, следующие строки кода отвечают на вопрос о движке браузера клиента, является ли он Gecko или Trident. Это_Gecko = navigator.userAgent.indexOf ("Gecko") Это_Trident = navigator.userAgent.indexOf ("Trident") if (Это_Trident !== -1) alert ("IE") if (Это_Gecko! == -1) alert ("Gecko") Для написания корректного кода разработчики применяют еще и непосредственную проверку поддержки используемого в скрипте объекта и его свойств и методов. Например, проверка поддержки объекта all показывает, что в Firefox он не распознается в отличие от MSIE и Google Chrome. Объект navigator знаком всем этим браузерам. if (document.all) alert ("all работает") if (navigator) alert ("navigator работает") Проверку свойства или метода объекта веб-дизайнеры рекомендуют проверять вместе с существованием самого объекта, чтобы условие могло выполниться без ошибки. Если объект не функционирует на данном движке, то первый аргумент сложного условия даст значение false и второй аргумент проверяться не будет. Например, следующей строкой кода можно проверить поддержку свойства appMinorVersion объекта navigator и убедиться в том, что браузер Firefox его не поддерживает, а MSIE поддерживает. if (navigator && navigator.appMinorVersion) alert ("appMinorVersion в работе") Следующая строка проверяет функционирование свойства product того же объекта navigator. Проверка показывает, что браузер Firefox его поддерживает, а MSIE нет. if (navigator && navigator.product) alert ("product в работе") Объекты localStorage и sessionStorage Объект localStorage создается браузером для каждого домена. Он представляет собой локальное хранилище данных с методами записи и чтения. Информация остается в хранилище и после закрытия окна 404
браузера. Под хранение данных веб-странице выделяется не менее 5М долговременной памяти. Если этот предел превышен браузер выдает сообщение об ошибке QUOTA_EXCEEDED_ERR. В отличие от куки, объекты веб-хранилища не отправляются на сервер при каждом запросе. Для записи данных в локальное хранилище используется метод setItem объекта localStorage setItem(,), где  — ключ или переменная,  — значение ключа localStorage.setItem('myName', 'Boris') Для чтения данных из локального хранилища используется метод getItem let  = getItem(), где  — ключ или переменная,  — значение ключа. Свойство length возвращает число пар, находящихся в хранилище. localStorage.length. Для удаления из локального хранилища ключа и его значения используется метод removeItem removeItem(), где  — ключ или переменная. Удалить сразу всю информацию из хранилища можно методом clear clear(). Организация данных в локальном хранилище похожа на организацию данных в объекте разработчика (пары ключ: значение). Обращаться с содержимым хранилища можно также, как и с данными объекта. 405
localStorage[], где  — ключ localStorage['myName'] = 'Boris' console.log (localStorage['myName']) // 'Boris' Удалить пару с заданным ключом можно тем же оператором delete, который используется для объекта delete localStorage[], где  — ключ. Если требуется сохранить много пар ключ:значение, то удобно оформить их как объект и сохранить его в хранилище как ключ:значениеобъект var obj = { firstName: “Petr”, lastName: “Kovalenko”, age: 12 } Прежде чем сохранять объект в локальное хранилище, его следует преобразовать в формат JSON с помощью метода stringify объекта JSON var jsonObj = JSON.stringify(obj) // {"firstName":"Petr","lastName":"Kovalenko","age":12} localStorage.setItem ("myObj", jsonObj); Чтобы получить из хранилища объект в том же виде, в котором он был туда отправлен, необходимо его преобразовать методом parse объекта JSON var jsonObj=localStorage.getItem("myObj") var obj = JSON.parse(jsonObj) Для проверки существования объекта в хранилище можно читать данные из хранилища по ключу и сравнивать со значением null localStorage.getItem(“key”) != null 406
Объект sessionStorage имеет те же свойства и методы, что и localStorage. Однако sessionStorage хранит данные только в текущей сессии браузера. Данные продолжают существовать и после перезагрузки страницы, но после закрытия вкладки они исчезают. Вторая и последующие вкладки с той же страницей будут иметь разные хранилища сессии. Объект Console Объект console обеспечивает доступ к консоли браузера, которая находится в панели инструментов веб-разработчика. Объект console является свойством объекта window. Доступ к консоли осуществляется с помощью строки кода window.console или просто console. Объект console имеет набор методов, часть из которых представлена в следующей таблице. Свойство/метод Описание log() выводит сообщение в консоль clear() очищает консоль error() выводит сообщение об ошибке в консоль group() создает новую встроенную группу в консоли, что увеличивает отступы после консольных сообщений на дополнительный уровень до тех пор, пока не будет вызван console.groupEnd() groupEnd() выход из текущей встроенной группы в консоли info() выводит информационное сообщение в консоль table() выводит данные (массив или объект) в консоль в виде таблицы console.table(["Audi", "Volvo", "Ford"]) warn() выводит предупреждающее сообщение в консоль Слушатель и обработчик события Скрипт позволяет обрабатывать множество различных событий, в том числе события, связанные с окном браузера, — такие как загрузка документа, закрытие окна и так далее. 407
Базовые события JS, связанные с объектом window onCopy копирование в буфер обмена onLoad завершение загрузки страницы или графического изображения onResize изменение размера окна браузера, применяется для объекта window onScroll перемещение ползунка линейки прокрутки onbeforeUnload событие перед закрытием окна браузера или переход на другую страницу <body onbeforeunload = "return Func()"> onUnload переход на другую страницу или завершение работы браузера Методы addEventListener и removeEventListener позволяют добавить или удалить обработчик события соответственно для какого-либо htmlэлемента. .addEventListener(,[,]), где  — идентификатор элемента,  — имя события (пишется только строчными буквами без префикса on),  — имя обработчика события,  — необязательный параметр, фаза, на которой обработчик должен сработать. По умолчанию, анонимная функция имеет параметр, значением которого является объект Event, хранящий всю информацию о произошедшем событии. Пример <input id="кнопка" type="button" value="Нажми меня"> <script> кнопка.onclick = function() { alert( 'Привет нажиматель' ) } </script> 408
Добавим еще обработчиков для этой кнопки. function обработчик2() { alert(' Хорошего настроения!') } function обработчик3() { alert(' Успешного изучения!') } кнопка.addEventListener("click", обработчик2) кнопка.addEventListener("click", обработчик3) кнопка.addEventListener("click", function (event) { }) Теперь при нажатии кнопки будет выдано последовательно три диалоговых окна. Задание Добавьте с помощью метода addEventListener обработчик события onMouseOut для вышеприведенной кнопки. Метод removeEventListener удаляет созданный обработчик события. .removeEventListener(,[,]). Чтобы удалить событие, необходимо передать те же аргументы, что были у addEventListener. Например, чтобы удалить обработчик2 из предыдущего примера, нужно написать оператор кнопка.removeEventListener("click", обработчик2) Задание Удалите с помощью метода removeEventListener обработчик события onMouseOut для вышеприведенной кнопки. Практическая работа на объекты браузера Задание 1. Вывести в консоль браузера значения выражений a. b. c. 125.3*5 корень квадратный из 63 "Как посеешь, так и пожнешь" 409
Задание 2. Создайте на веб-странице работающий секундомер, используя метод setInterval для организации цклического процесса и метод padStart для форматированного вывода цифр. Задание 3. Компьютер загадывает случайное число, игрок пытается его угадать. Пользователь вводит число до тех пор. пока не угадает его или не захочет сдаться. Компьютер сравнивает число с введенным и сообщает пользователю больше оно или меньше загаданного. Задание 4. Скрипт генерирует случайное четырехзначное число с неповторяющимися цифрами и предлагает игроку угадать его. Игрок вводит число, скрипт проверяет его на корректность (4 неповторяющиеся цифры). После ввода числа скрипт производит проверку на совпадение цифр двух чисел (исходного и введенного). Если совпадают цифры и позиции, на которых они стоят, то это быки. Если совпадают цифры без позиций, то это коровы. Например, исходное число: 6902, введенное число: 2907. Тогда быки: 9 0, коровы: 2. Игроку дается несколько попыток, счет которым ведется. 410
Задание 5. Организуйте контролируемый доступ к некоторым страницам сайта. Для этого создайте диалоговое окно для ввода пароля и логина и проверку введенных данных. Задание 6. Разработайте скрипт, который сможет собрать следующую информацию о клиенте: тип операционной системы, национальный язык, доступность cookie, разрешающую способность и глубину цвета монитора. Собранную информацию сохраните в объекте и поместите его в локальное хранилище браузера. На новой странице отобразите собранную информацию. Задание 7. Создайте сценарий, который создает новое окно и перемещает его по рабочему столу таким образом, как будто его трясет. Задание 8. 1. Добавьте на свою веб-страницу, контент которой выходит далеко за пределы окна браузера по вертикали, кнопку со стрелкой вверх. Кнопке дайте фиксированное позиционирование в правом нижнем углу окна браузера. Для кнопки добавьте функцию обработки события click, которая будет возвращать страницу на исходное положение во время вертикальной прокрутки. С помощью css-свойства scroll-behavior сделайте прокрутку плавной. 2. Добавьте для элемента body обработку события scroll с тем, чтобы стрелка появлялась в окне только тогда, когда страница уйдет вверх за окно браузера на 300px. 411
Задание 9 Разработайте сценарий, который предлагает посетителю веб-страницы возможность открытия гиперссылки в новом окне браузера. Задание 10. Разработайте сценарий, который предлагает посетителю веб-страницы ответить на вопрос за заданное время в секундах. Если посетитель успевает ввести ответ, то сценарий проверяет правильность и выдает информацию о результате проверки. Если посетитель не укладывается в отведенное время, то сценарий выдает сообщение об этом и скрывает вопрос или загружает в окно страницу, содержащую развернутый ответ. Задание 11. На экране случайным образом появляется изображение котенка, и задача игрока — кликнуть по нему как можно быстрее. После каждого успешного клика игроку начисляются очки. Котенок перемещается в разные места игрового поля каждые 800 мс. Игра длится 30 с, по завершении выводится итоговый счет. 412
ОБЪЕКТЫ HTML-ДОКУМЕНТА Объект document Объект document представляет содержимое веб-документа или фрейма, то есть это совокупность элементов html-документа. Так как элементов на веб-странице может быть достаточно много, они группируются в массивы и коллекции. Именно через свойства и методы этого объекта можно изменять содержимое html-документа. Свойства и методы characterSet doctype documentURI URL domain hasFocus() normalize() readyState referrer this возвращает кодировку символов html-документа возвращает версию html-документа, указанную в теге <doctype> или null если тег <doctype> отсутствует document.doctype.name // html возвращает URI html-документа возвращает URL html-документа возвращает домен сервера, на котором располагается html-документ или null, если документ создан динамически возвращает логическое значение, указывающее, находится ли документ в фокусе удаляет пустые текстовые узлы и объединяет соседние узлы возвращает статус (загрузки) текущего документа uninitialized — загрузка не началась loading — загрузка loaded — загружен interactive — готов к взаимодействовию complete — загружен полностью возвращает url-адрес документа, который загрузил текущий документ. Если документ не был открыт по ссылке, возвращается пустая строка в обработчике события возвращает элемент, вызвавший событие. Слово document как бы включа413
ется в возвращаемое значение. Например, <img src=dog09.gif onClick="alert (this.src)"> lastModified location title cookie возвращает дату последнего изменения документа возвращает адрес документа возвращает или устанавливает заголовок документа возвращает набор кукиз Пример <HR> <SCRIPT> document.write ("<p> Последнее обновление: <i>", document.lastModified, "</i> </p>") </SCRIPT> Коллекции all forms images links scripts коллекция всех тегов и элементов, расположенных в теле html-документа коллекция всех форм (теги <form>) документа коллекция всех изображений (теги <img>) документа коллекция всех ссылок (теги <a href>) документа коллекция всех скриптов в тегах <script> Элементы коллекции так же как и члены массива имеют общее имя и порядковый номер (индекс). В отличие от массивов коллекции содержат наборы элементов html-документа. Через коллекции вебпрограммисты имеют доступ к значениям многих атрибутов тегов html-документа. 414
Свойства коллекции length item () tags (“”) tagName type innerHTML возвращает число элементов коллекции возвращает элемент, соответствующий указанному индексу или идентификатору возвращает коллекцию, содержащую указанные теги.  — содержимое тега возвращает имя тега возвращает тип элемента формы возвращает текст и внутренние теги данного элемента Примеры document.forms[0].list1.value document.forms[0].elements[1].type document.all.item(6).tagName document.all.tags(“p”).length function showAllTags () {//функция вывода всех тегов документа в отдельное окно w=window.open () for (i=0; i < document.all.length; i++) {w.document.write (document.all(i).tagName, "<br>")} } 415
Методы clear () очищает документ от текста и дескрипторов close () закрывает все выходные потоки, используемые для записи текста в документ open () открывает все выходные потоки, позволяющие записывать текст в документ write (, , , …) записывает данные в документ, включая htmlтеги writeln (, , , …) записывает данные в документ, включая htmlтеги, и добавляет в конец вывода символ перехода на новую строку Пример1 Заполнение формы с открытием окна-запроса на подтверждение введенных данных <HTML> <HEAD> <TITLE>Веб-дизайн в действии</TITLE> <SCRIPT> var w function send () { fio=document.f.n1.value+" "+document.f.n2.value if (!window_available()) w=open("","k","width=200,height=150") else w.focus() w.document.writeln ("<p>Вы ввели:</p>") w.document.writeln ("<p>",fio,"</p>") w.document.writeln ("<input type=button value=Да name=b1 onClick='doSend (this)'>") w.document.writeln ("<input type=button value=Нет name=b2 onClick='doSend (this)'>") w.document.writeln ("<script>") w.document.writeln ("function doSend(o)") 416
w.document.writeln ("{if (o.value=='Нет') {alert('Повторите ввод');opener.document.forms[0].reset();self.close()}") w.document.writeln("if(o.value=='Да'){opener.close();self.close()}}") w.document.writeln ("<\/script>") w.document.close() }; function window_available() { if (!w) {return false} else if (w.closed) {return false} else {return true} } </SCRIPT> </HEAD> <BODY> <H1>Веб-дизайн в действии</H1> <FORM METHOD = POST NAME = “f”> <P>введите имя</P> <P><INPUT TYPE = text NAME = “n1”></P> <P>введите фамлию</P> <P><INPUT TYPE=text NAME = “n2”></P> <P><INPUT TYPE = “button” VALUE = "Отправить" onClick = "send()"></P> </FORM> </BODY> </HTML> 417
Пример2 Напишем функцию, возвращающую индекс выбранной радиокнопки <form action="" onsubmit="check(); return false"> <fieldset> <legend>Выберите ваших любимых животных</legend> <p> <label for="r1"> <input type="radio" name="rad" id="r1">Зебра </label> <label for="r2"> <input type="radio" name="rad" id="r2"> Кошка </label> <label for="r3"> <input type="radio" name="rad" id="r3">Анаконда </label> <label for="r4"> <input type="radio" name="rad" id="r4">Человек </label> <br> <label for="r5"> <input type="radio" name="rad" id="r5">Слон </label> <label for="r6"> <input type="radio" name="rad" id="r6">Антилопа </label> <label for="r7"> <input type="radio" name="rad" id="r7">Голубь </label> <label for="r8"> 418
<input type="radio" name="rad" id="r8">Краб </label> </p> </fieldset> <input type="submit" value="Отправить информацию"> </form> <script> function check() { radios=document.forms[0].rad // массив радиокнопок radios.forEach((element,i) => { if (element.checked) console.log("индекс выбранного элеменнта", i) }); } </script> Объект Image Графические изображения на веб-странице являются объектами image. Все графические объекты на странице составляют коллекцию графических объектов, то есть они пронумерованы, начиная с 0, и имеют общее имя images. В JavaScript можно через точечную нотацию обращаться к свойствам объекта image, которые являются атрибутами того же объекта, сформулированными на языке HTML. document.images[0].width = w document.images[0].src = "new_pic.jpg" 419
В последнем примере происходит смена изображения на новое. При этом новая картинка принимает размеры предыдущей. Смену изображений часто используют при наведении курсора мышки на графическую гиперссылку. Пример Изменение размеров окна под размер загружаемого изображения и перемещение окна в центр экрана. if (location.search) { var fi=location.search.substring (1) var w=location.hash.substring (1, 4) var h=location.hash.substring (4) var ws=screen.availWidth/2 - w/2 var hs=screen.availHeight/2 - h/2 document.write ("<img src="+fi+">") self.resizeTo (w, h) self.resizeBy (30, 100) self.moveTo (ws, hs) } JavaScript поддерживает предварительную загрузку изображений. Это, например, может понадобится для считывания свойств графического объекта и соответствующего изменения параметров окна, в котором оно отображается. Для предварительной загрузки рисунков сценария применяется следующий конструктор var  = new Image ([, ]), где  — имя переменной или массива; ,  — ширина и длина изображения в пикселях. let phallnames = [“pic1.jpg”, “pic2.jpg”, “pic3.jpg”, “pic4.jpg”, “pic5.jpg”] var phall = new Array() for (let i = 0; i < document.images.length; i++) { phall[i] = new Image() phall[i].src = phallnames[i] console.log(phall[i].src) phall[i].onload = function() { 420
document.images[i].src = phall[i].src } } Картинки в фоновом режиме загружаются на компьютер посетителя в массив phall и как только загрузка картинки завершена, то срабатывает событие onload и скрипт вызывает обработчика данного события для отображения картики в теге <img>. Объект FormData Объект FormData хранит данные, которые можно отправить на сервер посредством технологии AJAX (XMLHttpRequest). Для кодирования данных метод объекта FormData использует формат "multipart/formdata", что позволяет подготовить для отправки по AJAX не только текстовые данные, но и файлы (input type="file"). Передачу на сервер данных, находящихся в объекте FormData, необходимо осуществлять методом POST. Данные в объекте FormData представляют собой набор пар «ключзначение». let  = new FormData([]), где  — имя переменной, хранящей объект FormData;  — ссылка на элемент form. Если передать в конструктор ссылку на существующую форму, то создаваемый объект автоматически прочитает из нее поля. var formData = new FormData(document.forms[0]) Методы передачи данных формы позволяют указать объект FormData в свойстве запроса. Он будет соответствующим образом закодирован и отправлен с заголовком Content-Type: multipart/form-data. const xhr = new XMLHttpRequest() xhr.open('POST', dataSource) xhr.send(formData) 421
Метод append Описание добавляет новую порцию данных (ключ-значение). Если указанного ключа нет в объекте, то данный метод добавит в FormData новый элемент («ключзначение»). Если указанный ключ есть уже у объекта FormData, то данный метод запишет его значение в качестве следующего значения этого ключа. После этого, с указанным ключом уже будет связано несколько значений (массив значений) formData.append('key','value1') //"key":"value1" formData.append('key','value2') //"key":["value1", "value2"] set изменяет текущее значение ключа delete удаляет элемент из объекта FormData с указанным ключом formData.delete('key') has проверяет в объекте FormData наличие указанного ключа get возвращает первое значение связанное с указанным ключом getAll возвращает массив значений связанных с указанным ключом formData.get('key') // "value1" // получить массив значений связанных с ключом formData.getAll('key') // ["value1","value2"] Для работы с объектом FormData можно использовать перебирающий метод ForEach, который вызывает заданную функцию обратного вызова для каждой пары ключ-значение в объекте FormData. formData.forEach((value, key) => { console.log(`${key}: ${value}`) }) Объект Audio В формате HTML существует элемент <audio>, который размещает звуковой контент на веб-странице. В javascript есть встроенный объект 422
Audio, с помощью которого можно создавать тот же html-элемент <audio> и управлять им из скрипта. var  = new Audio ([]), где  — имя переменной, хранящей объект Audio;  — адрес звукозаписи. audio = new Audio(better-day-186374.mp3) Свойства currentSrc возвращает URL текущей звукозаписи currentTime устанавливает или возвращает текущую позицию (в секундах) воспроизведения звука, воспроизведение перейдет в указанную позицию duration возвращает длину звукозаписи (в секундах) ended возвращает true, если воспроизведение закончилось, в противном случае возвращается false loop устанавливает или возвращает значение, должно ли воспроизведение звука проигрываться заново в бесконечном цикле paused возвращает true, если звук приостановлен, в противном случае возвращает false src устанавливает или возвращает значение атрибута src аудио volume устанавливает или возвращает громкость звука (от 0 до 1) Методы play() pause() load() проигрывает звукозапись ставит проигрывание звукозаписи на паузу перезагружает звукозапись <button>Play</button> <button>Stop</button> 423
<input type="range" name="volume" id="vol" min="0" max="1" step="0.1" oninput="document.getElementById('voltxt').value = this.value; audio.volume = +this.value"> <input type="text" id="voltxt" readonly> <script> audio = new Audio() audio.src = "better-day-186374.mp3" document.querySelectorAll("button")[0]. addEventListener("click", function () { audio.play() }) document.querySelectorAll("button")[1]. addEventListener("click", function () { audio.pause() }) </script> КУКИЗ (COOKIES) Cookies (кукиз, в переводе с англ. домашнее печенье, булочка) — механизм, позволяющий серверу сохранять на жестком диске клиента небольшой объем информации и использовать его при повторном посещении страницы. Информация сохраняется в одноименной папке (Internet Explorer) в текстовом файле. Каждая веб-страница записывает данные в свой файл. В большинстве случаев имя cookie-файла строится как @.txt, где  — имя пользователя (регистрационного профиля),  — имя домена соответствующей веб-страницы. Cookie представляют собой последовательность пар переменная = значение, разделенных точкой с запятой. Cookie позволяют сохранять необходимую информацию на компьютере клиента, например, идентификационные данные, настройки страницы, статистическую информацию. Однако у этого механизма есть существенные недостатки. К ним относятся:  однопользовательская поддержка;  программная несовместимость (разные браузеры по-разному реализуют эту технологию);  аппаратная несовместимость (невозможность использования одних и тех же кукиз для нескольких клиентских компьютеров, так как хранятся они не на стороне сервера); 424
  возможность со стороны клиента отключения механизма cookies; возможность удаления файла, хранящего кукиз. Записывать куки в файл можно через свойство cookie объекта document. document.cookie = “ [; expires=; path=; domain=; secure]”, где  — поле, содержащее данные в виде пары имя = значение.  — cрок годности, то есть момент истечения действия куков по гринвичскому меридиональному времени (например, Monday, 19-May2011 23:45:00 GMT). Если этот параметр не установлен, то куки утратят годность сразу же по окончании сеанса работы браузера;  — строка, задающая папку верхнего уровня, документы которой имеют доступ к кукиз. По умолчанию кукиз доступна любой странице узла, расположенной в той же папке (и любой вложенной в нее), что и исходная. Например, path=/stuff;  — строка, задающая домен, которому разрешен доступ к кукиз. По умолчанию имя домена есть имя сервера, сгенерировавшего кукиз. Этот параметр часто используется, когда на одном домене находится несколько веб-узлов. Чтобы, например, разрешить доступ к кукам всех узлов домена sura нужно составить следующее поле: domain=.sura.ru; secure — уровень безопасности. Если параметр установлен, то данные передаются по протоколу HTTPS (HTTP-SSL - Secure Socket Level). Примеры document.cookie = "fileN=" + document.forms[0].elements[1].value document.cookie = ”test=comp1” document.cookie = document.f.n1.name + "=" + document.f.n1.value + "; expires=Monday, 19-May-2011 23:45:00 GMT" 425
Прочитать кукиз можно через то же самое свойство cookie.  = document.cookie, где  — имя переменной. В  записываются все пары имя = значение, установленные сервером для данной страницы. Для того чтобы прочитать значение какого-либо параметра кукиз, необходимо писать код JavaScript. В приведенном ниже примере функция set_cookie() записывает в кукиз все значения элементов формы, а функция get_cookie(n) позволяет считывать кукиз и выделять из всех полей значение заданного в аргументе параметра. Функция check_cookie() проверяет существование первого поля кукиз и при положительном результате сама заполняет хранящимися значениями соответствующие области формы при повторной загрузке веб-страницы. <HTML> <HEAD> <TITLE>cookies</TITLE> <script> function сохранить_cookie() { document.cookie = document.регистрация.n1.name + "=" + document.регистрация.n1.value + "; expires=Monday, 19-May2011 23:45:00 GMT" document.cookie=document.регистрация.n2.name + "=" + document.регистрация.n2.value + "; expires = Monday, 19-May2011 23:45:00 GMT" document.cookie=document.регистрация.n3.name + "=" + document.регистрация.n3.value + "; expires=Monday, 19-May2011 23:45:00 GMT" } function прочитать_cookie (n) { cookie_array=document.cookie.split ("; ") for (i=0; i<cookie_array.length; i++) {pole=cookie_array[i].split ("=") cookie_name=pole[0] cookie_value=pole[1] if (n==cookie_name) return (cookie_value)} return null 426
} function проверить_cookie () { n1= прочитать_cookie ("n1") n2= прочитать_cookie ("n2") n3= прочитать_cookie ("n3") if (n1) { document.регистрация.n1.value=n1 document.регистрация.n2.value=n2 document.регистрация.n3.value=n3} } </SCRIPT> </HEAD> <BODY leftmargin=30 onLoad="проверить_cookie()"> <H1> Веб-дизайн в действии </H1> <FORM METHOD=POST NAME="регистрация"> <P>введите имя</P> <INPUT TYPE = ”text” NAME = ”n1”> <P>введите фамилию</P> <INPUT TYPE = ”text” NAME = ”n2”> <P>введите город</P> <INPUT TYPE=”text” NAME=”n3”> <BR> <BR> <INPUT TYPE = button VALUE = "Отправить" onClick="сохранить_cookie ()"> <INPUT TYPE = ”reset” VALUE = "Очистить"> </FORM> </BODY> </HTML> Метод split, используемый в функции прочитать_cookie(), разбивает строку на части и сохраняет их в массиве. Разделителем для первого массива выступает точка с запятой, для второго — знак равенства. 427
Практическая работа на объекты html-документа Задание 1. Создайте на веб-странице графическую гиперссылку и с помощью скрипта JavaScript сделайте ее интерактивной, то есть когда мышиный курсор будет проходить над ней и при щелчке мыши, изображение должно меняться. Задание 2. Создайте на веб-странице список ролловеров (список ссылок), при наведении курсора мышки на пункт которого, он начинает подсвечиваться или слева от пункта появляется стрелка. → ГЛАВНАЯ КАРТА САЙТА СПИСОК ССЫЛОК КОНТАКТЫ Задание 3. Составьте список ссылок (либо с помощью тега <OL>/<UL>, либо с помощью соответствующих тегов формы) на рисунки каких-либо предметов, по щелчку на которые на этой же веб-странице происходит смена текущего рисунка на выбранный. 428
• • • • • Яблоко груша слива банан ананас Задание 4. Изучите способы организации массивов в JavaScript. Создайте массив из 10 изображений и реализуйте их последовательный просмотр на веб-странице с помощью гиперссылок «вперед», «назад». вперёд назад Задание 5. Разработайте, используя различные виды позиционирования и трансформацию, стилизованные часы из окружности, двух или трех стрелок различной длины и жирной точки в центре циферблата. С помощью скрипта заставьте стрелки двигаться по окружности: большую (секундную) со скоростью 1 секунда на 1 градус, маленькую (часовую) со скоростью 1 час на 30 градусов. Задание 6. С помощью технологии CSS наложите несколькоо фотографий друг на друга и поместите название альбома. Напишите скрипт, который при перемещении по фотографии будет менять фото. 429
Задание 7. С помощью CSS обрамите фотографии альбома в красивую графическую рамку. Напишите скрипт, который выведет на веб-страницу в несколько строк и столбцов обрамленные в красивую рамку фотографии. Задание 8. Напишите скрипт, который будет организовывать просмотр фотографий в виде слайдшоу. В верхней части веб-страницу расположите прокрутку миниатюр, в основной части — оригинальный (или больший) размер выбранной фотографии. С помощью CSS сделайте выделение выбранной фотографии. 430
Задание 9. Разработайте страницу магазина, торгующего овощами онлайн. Предусмотрите выбор нужного количества товара, автоматический подсчет итоговой суммы заказа. Задание 10. Разработайте скрипт для игрового автомата, в котором случайным образом меняются три картинки. Кроме кнопки Вращать, добавьте поле для отображения числа попыток и поле для отображения числа выигрышей. https://minigames.mail.ru/slot-odnorukij-bandit 431
Задание 11. Создайте работающий стилизованный калькулятор на веб-странице с набором арифметических операций, некоторых математических функций и констант. Задание 12. Создайте бегущую строку каких-либо новостей. Задание 13. Создайте веб-страничку с тестом на любую тему и напишите скрипт на JavaScript для проверки правильности ответов или интерпретации результатов. Вопросы в тесте должны быть разного типа: на выбор одного варианта из нескольких, на выбор нескольких вариантов из множества, ответ одним словом или числом и т. д. Задание 14. Изучите возможности JavaScript по работе с cookies. Напишите сценарий, который отслеживает число посещений веб-страницы отдельным пользователем и выводит эту информацию на экран. Задание 15. В веб-страницы, созданные ранее, добавьте сценарий JavaScript, выводящий в диалоговом окне тег элемента, по которому щелкает посетитель. Используйте ключевое слово this. Задание 16. Сделайте несколько ячеек таблицы (фон ячейки плюс содержимое) гиперссылками. Используйте свойство location объекта document и свойство стилей padding. 432
Варианты 1 2 3 Задание 17. Для готовой веб-страницы составьте сценарий JavaScript, выводящий в отдельное окно теги всех заголовков html-документа. Задание 18. Составьте сценарий на JavaScript, выводящий в диалоговом окне текст и внутренние теги элемента, по которму щелкает мышкой посетитель веб-страницы. Задание 19. Создайте сценарий, который меняет размер размещенной на вебстранице кнопки за счет вывода на нее надписи путем прибавления или удаления по одной букве. Задание 20. Создайте сценарий, который при нажатии на соответствующую кнопку поставит флажки или сбросит их во всей совокупности чекбоксов. Задание 21. Создайте сценарий, по которому введенный в текстовое поле пароль будет видимым при щелчке на чекбоксе и маскируемым при повторном щелчке. Добавьте в сценарий шаблон для ввода пароля — требование и проверку ввода не менее 8 символов строчных или прописных букв латинского алфавита и цифр от 0 до 9. Пароль должен содержать не менее одной строчной буквы, не менее одной прописной и не менее одной цифры. Задание 22. Создайте сценарий, который плавно меняет цвет размещенной на вебстранице кнопки. 433
Задание 23. Разместите на странице блок из 5 звездочек и создайте скрипт, который будет закрашивать все звезды желтым цветом слева от курсора мыши при щелчке на какой-либо звезде. Задание 24. Создайте на веб-странице работающие электронные часы с графическим индикатором. Набор графических цифр и знаков возьмите c сайта Pixabay. Задание 25. Разместите на веб-странице кнопку, по нажатию на которую будет случайным образом играть мелодия, которую нужно угадать игроку. Для выбора названия мелодии можно на веб-странице разместить список мелодий. 434
Литература 1. 2. 3. 4. 5. 6. 7. 8. Диков, А. В. Клиентские технологии веб-дизайна. HTML5 и CSS3 / А. В. Диков. — 2-е изд., стер. — СПб. : Лань, 2023. — 188 с. Златопольский, Д. М. Сборник задач по программированию. — СПб. : БХВ-Петербург, 2011. Мартынов, Н. Н. Алгоритмизация и основы объектно-ориентированного программирования на JavaScript. Информатика и ИКТ: профильный уровень. 10-й класс. — М. : Бином-Пресс, 2010. Симпсон, К. ES6 и не только. — СПб. : Питер, 2017. Achieve mastery through challenge. Improve your development skills by training with your peers on code kata that continuously challenge and push your coding practice. — URL: https://www.codewars.com/. Javascript.ru. — URL: https://learn.javascript.ru. Learn to CodeWith the world's largest web developer site. — URL: https://www.w3schools.com/. Resources for Developers, by Developers. Documenting web technologies, including CSS, HTML, and JavaScript, since 2005. — URL: https://developer.mozilla.org/en-US/. 435
Андрей Валентинович ДИКОВ WEB-ПРОГРАММИРОВАНИЕ НА JAVASCRIPT УЧЕБНОЕ ПОСОБИЕ Зав. редакцией литературы по информационным технологиям и системам связи О. Е. Гайнутдинова ЛР № 065466 от 21.10.97 Гигиенический сертификат 78.01.10.953.П.1028 от 14.04.2016 г., выдан ЦГСЭН в СПб Издательство «ЛАНЬ» lan@lanbook.ru; www.lanbook.com 196105, Санкт-Петербург, пр-кт Ю. Гагарина, д. 1, лит. А. Тел./факс: (812) 336-25-09, 412-92-72. Бесплатный звонок по России: 8-800-700-40-71 ГДЕ КУПИТЬ ДЛЯ ОРГАНИЗАЦИЙ: Для того, чтобы заказать необходимые Вам книги, достаточно обратиться в любую из торговых компаний Издательского Дома «ЛАНЬ»: по России и зарубежью «ЛАНЬ-ТРЕЙД». 196105, Санкт-Петербург, пр-кт Ю. Гагарина, д. 1, лит. А тел.: (812) 412-85-78, 412-14-45, 412-85-82; тел./факс: (812) 412-54-93 e-mail: trade@lanbook.ru www.lanbook.com пункт меню «Где купить» раздел «Прайс-листы, каталоги» в Москве и в Московской области «ЛАНЬ-ПРЕСС». 115432, Москва, пр-кт Андропова, д. 10 (БЦ Технопарк Плаза), этаж 6, оф. 6.006 тел.: (499) 350-62-10, (495) 252-79-20; e-mail: lanpress@lanbook.ru в Краснодаре и в Краснодарском крае «ЛАНЬ-ЮГ». 350010, Краснодар, ул. Зиповская, д. 9, литер Д, пом. 31 тел.: (861) 274-10-35; e-mail: lankrd98@mail.ru ДЛЯ РОЗНИЧНЫХ ПОКУПАТЕЛЕЙ: интернет-магазин Издательство «Лань»: http://www.lanbook.com магазин электронных книг Global F5: http://globalf5.com/ Подписано в печать 14.04.26. Бумага офсетная. Гарнитура Школьная. Формат 60×90 1/16. Печать офсетная/цифровая. Усл. п. л. 27,25. Тираж 30 экз. Отпечатано в полном соответствии с качеством предоставленного оригинал-макета в АО «Т8 Издательские Технологии». 109316, г. Москва, Волгоградский пр-кт, д. 42, к. 5.