Java Script Mentality
Java Script Mentality
в JavaScript
Учебное пособие
СОДЕРЖАНИЕ
П р а к т и ч е с к а я р а б о т а 1 .................................................................................................................... 4
ВВЕДЕНИЕ В СЦЕНАРИИ JS ...................................................................................................................... 4
П р а к т и ч е с к а я р а б о т а 2 .................................................................................................................. 12
ПЕРЕМЕННЫЕ И КОНСТАНТЫ ................................................................................................................. 12
П р а к т и ч е с к а я р а б о т а 3 .................................................................................................................. 18
ТИПЫ ДАННЫХ.......................................................................................................................................... 18
П р а к т и ч е с к а я р а б о т а 4 .................................................................................................................. 27
ПРЕОБРАЗОВАНИЕ ТИПОВ ...................................................................................................................... 27
П р а к т и ч е с к а я р а б о т а 5 .................................................................................................................. 35
ДИАЛОГОВЫЕ ОКНА ................................................................................................................................. 35
П р а к т и ч е с к а я р а б о т а 6 .................................................................................................................. 40
DOM-ДЕРЕВО ............................................................................................................................................. 40
П р а к т и ч е с к а я р а б о т а 7 .................................................................................................................. 45
ДОСТУП К DOM ......................................................................................................................................... 45
П р а к т и ч е с к а я р а б о т а 8 .................................................................................................................. 54
СВОЙСТВО УЗЛОВ .................................................................................................................................... 54
П р а к т и ч е с к а я р а б о т а 9 .................................................................................................................. 65
АТРИБУТЫ И СТИЛИ ................................................................................................................................. 65
П р а к т и ч е с к а я р а б о т а 1 0 ............................................................................................................... 79
ВЫБОР ЭЛЕМЕНТОВ DOM ........................................................................................................................ 79
П р а к т и ч е с к а я р а б о т а 1 1 ............................................................................................................... 88
ДОБАВЛЕНИЕ И УДАЛЕНИЕ УЗЛОВ ........................................................................................................ 88
П р а к т и ч е с к а я р а б о т а 1 2 ............................................................................................................... 96
ОПЕРАЦИИ JAVASCRIPT. ОПЕРАТОРЫ .................................................................................................... 96
П р а к т и ч е с к а я р а б о т а 1 3 ............................................................................................................. 102
ОПЕРАЦИИ JAVASCRIPT. РАБОТА СО СТРОКАМИ ................................................................................ 102
П р а к т и ч е с к а я р а б о т а 1 4 ............................................................................................................. 115
ОПЕРАЦИИ JAVASCRIPT. РАБОТА С ЧИСЛАМИ .................................................................................... 115
П р а к т и ч е с к а я р а б о т а 1 5 ............................................................................................................. 125
ОПЕРАЦИИ JAVASCRIPT. ОБЪЕКТ MATH............................................................................................... 125
П р а к т и ч е с к а я р а б о т а 1 6 ............................................................................................................. 132
ОПЕРАЦИИ JAVASCRIPT. ОБЪЕКТ DATE ............................................................................................... 132
П р а к т и ч е с к а я р а б о т а 1 7 ............................................................................................................. 141
JSON ПРЕДСТАВЛЕНИЕ ДАННЫХ.......................................................................................................... 141
П р а к т и ч е с к а я р а б о т а 1 8 ............................................................................................................. 151
ОБЪЕКТ REGEXP. ОСНОВЫ.................................................................................................................... 151
П р а к т и ч е с к а я р а б о т а 1 9 ............................................................................................................. 162
ОБЪЕКТ REGEXP. МЕТАСИМВОЛЫ........................................................................................................ 162
2
П р а к т и ч е с к а я р а б о т а 2 0 ............................................................................................................. 170
УСЛОВНЫЕ ИНСТРУКЦИИ ...................................................................................................................... 170
П р а к т и ч е с к а я р а б о т а 2 1 ............................................................................................................. 184
БЛОКОВАЯ ОБЛАСТЬ ВИДИМОСТИ ....................................................................................................... 184
П р а к т и ч е с к а я р а б о т а 2 2 ............................................................................................................. 197
ПРОСТЫЕ ЦИКЛЫ ................................................................................................................................... 197
П р а к т и ч е с к а я р а б о т а 2 3 ............................................................................................................. 209
СПЕЦИАЛЬНЫЕ ЦИКЛЫ.......................................................................................................................... 209
П р а к т и ч е с к а я р а б о т а 2 4 ............................................................................................................. 220
ВЛОЖЕННЫЕ ЦИКЛЫ ............................................................................................................................. 220
П р а к т и ч е с к а я р а б о т а 2 5 ............................................................................................................. 233
ОБРАБОТКА ОШИБОК............................................................................................................................. 233
П р а к т и ч е с к а я р а б о т а 2 6 ............................................................................................................. 248
МАССИВЫ ................................................................................................................................................ 248
П р а к т и ч е с к а я р а б о т а 2 7 ............................................................................................................. 264
СВОЙСТВА И МЕТОДЫ МАССИВОВ ...................................................................................................... 264
П р а к т и ч е с к а я р а б о т а 2 8 ............................................................................................................. 273
СВОЙСТВА И МЕТОДЫ МАССИВОВ ЧАСТЬ 2........................................................................................ 273
П р а к т и ч е с к а я р а б о т а 2 9 ............................................................................................................. 286
ХРАНЕНИЕ ДАННЫХ В БРАУЗЕРЕ ......................................................................................................... 286
П р а к т и ч е с к а я р а б о т а 3 0 ............................................................................................................. 301
ВВЕДЕНИЕ В ФУНКЦИИ JS .................................................................................................................... 301
П р а к т и ч е с к а я р а б о т а 3 1 ............................................................................................................. 309
ПАРАМЕТРЫ И ВОЗВРАТ ЗНАЧЕНИЙ .................................................................................................... 309
П р а к т и ч е с к а я р а б о т а 3 2 ............................................................................................................. 323
ПОДРОБНЕЕ О ФУНКЦИЯХ .................................................................................................................... 323
П р а к т и ч е с к а я р а б о т а 3 3 ............................................................................................................. 337
CALLBACK ФУНКЦИИ .............................................................................................................................. 337
П р а к т и ч е с к а я р а б о т а 3 4 ............................................................................................................. 348
CALLBACK ФУНКЦИИ .............................................................................................................................. 348
П р а к т и ч е с к а я р а б о т а 3 5 ............................................................................................................. 361
ЛЕКСИЧЕСКОЕ ОКРУЖЕНИЕ И КОНТЕКСТ .......................................................................................... 361
П р а к т и ч е с к а я р а б о т а 3 6 ............................................................................................................. 377
ЗАМЫКАНИЕ............................................................................................................................................ 377
3
Практическая работа 1
ВВЕДЕНИЕ В СЦЕНАРИИ JS
высоко 1. Введение
2. Подключение сценариев
профессиональные 3. Синхронные, асинхронные и
отложенные сценарии
специалисты! 4. Синтаксис JavaScrip
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Введение
JavaScript — это кросс-платформенный, объектно-ориентированный
скриптовый язык, который позволяет веб-разработчику управлять тем, как
ведет себя веб-страница.
Программы, написанные на языке JavaScript, называются скриптами
или сценариями. Скрипты JavaScript могут быть вставлены в любое место
HTML- документа, и как только браузер отображая код страницы доходит до
скрипта – выполняются. Процесс выполнения скрипта называют
интерпретацией.
Задачи, которые можно решать с помощью JavaScript:
проверять правильность заполнения пользовательских HTML-форм;
менять стили HTML-элементов, скрывать, показывать элементы и т.п.;
отображать всплывающие и диалоговые окна;
реагировать на действия посетителя, обрабатывать клики мыши,
перемещения курсора и т.п.;
посылать запросы на сервер и загружать данные без перезагрузки
страницы.
Подключение сценариев
Чтобы пpoгpaммa (сценарий) JavaScript запустилась, ее нужно внедрить
в НТМL-документ. Сценарии можно внедрить в HTML-документ
различными стандартными способами:
поместить код между открывающим и закрывающим тегами script;
поместить скрипты во внешний файл (с расширением .js), а затем
подключить его к документу HTML;
поместить код непосредственно в атрибут события HTML-элемента.
4
JavaScript в элементе script
Самый простой способ внедрения JavaScript в HTML-документ –
использование тега script. Теги script могут размещаться в любом месте
документа.
Таким образом, на одной веб-странице могут располагаться сразу
несколько сценариев. Выполнение сценариев браузерами происходит по мере
их загрузки. Браузер читает HTML-документ сверху вниз и, когда он
встречает тег script, рассматривает текст программы как сценарий и
выполняет его.
ПРИМЕР 1
<html>
<body>
<header>
<h1 align = "center">Введение в JavaScript</h1>
</header>
<!-- инструкции HTML-кода ...-->
<script>
alert("Добро пожаловать в JavaScript!");
</script>
<!-- инструкции HTML-кода ...-->
</body>
</html>
Внешний JavaScript
Как правило, только простейшие скрипты помещаются в HTML
документ. Если JavaScript-кода много – его выносят в отдельный файл,
который, как правило, имеет расширение .js.
Чтобы включить в HTML-документ JavaScript-кoд из внешнего файла,
нужно использовать атрибут src (source) тега script. Значением атрибута
должен быть aдpec файла, в котором содержится JS-код.
5
ПРИМЕР 2
HTML:
<html>
<head>
<script src="[Link]"></script>
</head>
<body>
<h1 align = "center">Введение в JavaScript</h1>
</body>
</html>
[Link]:
ПРИМЕР 3
<html>
<body>
<header>
<h1 align = "center">Введение в JavaScript</h1>
</header>
<button onclick="alert('Добро пожаловать в JavaScript!')">Нажми
меня</button>
</body>
</html>
6
Синхронные, асинхронные и отложенные сценарии
Синхронное выполнение сценария
В современных сайтах скрипты обычно тяжелее, чем код HTML: они
весят больше, дольше обрабатываются.
По умолчанию файлы JS-кода прерывают синтаксический анализ
(парсинг) HTML-документа до тех пор, пока скрипт не будет загружен (если
он внешний) и выполнен, тем самым увеличивая промежуток времени до
первой отрисовки страницы.
Это ведёт к двум важным проблемам:
Скрипты не видят HTML-элементы ниже себя, поэтому к ним нельзя
добавить обработчики и т.д.
Если вверху страницы объёмный скрипт, он блокирует страницу.
Пользователи не видят содержимое страницы, пока скрипт не
загрузится и не запустится.
Такое поведение браузера называется синхронным и может вызвать
некоторые проблемы со скоростью отображения сайта.
ПРИМЕР 4
<html>
<body>
<p>Важная информация не покажется, пока не загрузится скрипт.</p>
<script src="[Link]
<p>...Важная информация!</p>
</body>
</html>
Атрибут async. Асинхронное выполнение
Async используется для того, чтобы указать браузеру, что скрипт
может быть выполнен асинхронно. Атрибут доступен только для файлов,
подключающихся внешне.
При обнаружении атрибута async браузер не останавливает обработку
HTML-документа для загрузки скрипта, получение скрипта происходит
параллельно с разбором документа. HTML-парсер будет приостановлен
для выполнения скрипта, как только файл скрипта будет загружен.
ПРИМЕР 5
<html>
<head>
<script async src="[Link]
</head>
<body style="background-color: #0000ff">
<h1 align = "center">Введение в JavaScript</h1>
</body>
</html>
7
Атрибут defer. Отложенное выполнение
Атрибут defer откладывает выполнение скрипта до тех пор, пока вся
HTML-страница не будет загружена полностью.
Как и при асинхронной загрузке скриптов — JS-файл может быть
загружен, в то время как HTML-документ ещё грузится. Однако, даже если
скрипт будет полностью загружен ещё до того, как браузер закончит
обработку страницы, он не будет выполнен до тех пор, пока HTML-
документ не обработается до конца.
ПРИМЕР 6
<html>
<head>
<script defer src="[Link]
</head>
<body style="background-color: #0000ff">
<h1 align = "center">Введение в JavaScript</h1>
</body>
</html>
У async и defer есть кое-что общее: они не блокируют отрисовку
страницы. Так что пользователь может просмотреть содержимое страницы и
ознакомиться с ней сразу же.
Но есть и значимые различия:
async. Порядок загрузки (кто загрузится первым, тот и сработает).
Может загрузиться и выполниться до того, как документ загрузится.
defer. Порядок документа (как расположены в документе).
Выполняется после того, как документ загружен и обработан.
Синтаксис JavaScript
Синтаксис JavaScript – это набор правил, по которым создаются
программы JavaScript.
Набор символов
При написании программ на JavaScript используется набор символов
Unicode. В отличие от 7-разрядной кодировки ASCII, подходящей только для
английского языка, и 8-разрядной кодировки ISO Latin-1, подходящей только
для английского и основных западноевропейских языков, 16-разрядная
кодировка Unicode поддерживает практически все письменные языки,
имеющиеся на планете.
ПРИМЕР 7
<html>
<body>
<h1 align = "center">Введение в JavaScript</h1>
<script>
// латиница
8
var str = "Hello, World!";
alert (str);
// кириллица
var строка = "Привет, Мир!";
alert (строка);
</script>
</body>
</html>
Пробельные символы
Интерпретатор JavaScript игнорирует все пробельные символы
которые могут присутствовать между языковыми конструкциями и
воспринимает текст программы как сплошной поток кода.
Точка с запятой
Программа (сценарий) на языке JavaScript представляет собой перечень
инструкций, которые выполняются веб-браузером.
Если несколько инструкций располагаются на одной строке, то между
ними следует поставить знак «точка с запятой» (;).
ПРИМЕР 8
<script>
alert("Сообщение"); break;
</script>
Если каждая инструкция размещается на отдельной строке, то
разделитель можно не писать. В таких случаях JavaScript интерпретирует
переход на новую строчку как разделитель команд для автоматического
ввода точек с запятой завершающих инструкции.
ПРИМЕР 9
<script>
alert("Сообщение");
break
</script>
В этом случае JavaScript ждёт завершение выражения и поэтому
автоматически не вставляет виртуальную точку с запятой между строчками.
ПРИМЕР 10
<script>
var user = "Name";
alert("Рады вас видеть, " +
user +
" !");
</script>
9
Чувствительность к регистру
В JavaScript все элементы, включая имена переменных, функций и
операторов, чувствительны к регистру и должны всегда содержать
одинаковые наборы прописных и строчных букв.
Например, ключевое слово while должно набираться как while, а не
While или WHILE. Аналогично num, NUM и Num – это три разные
переменные.
Комментарии
Однострочные комментарии начинаются с двойного слэша (//). Текст
считается комментарием до конца строки.
ПРИМЕР 11
<script>
// объявляем переменную
var num = 5;
alert( num ); // выводим переменную
</script>
Многострочный комментарий начинается с слэша и звездочки (/*), а
заканчивается ими же в обратном порядке (*/). Так можно закомментировать
одну и более строк.
ПРИМЕР 12
<script>
/* многострочный комментарий
эта часть кода не выполнится
var num = 5;
alert( num );*/
alert("Привет, Мир!");
</script>
Идентификаторы
Идентификатор - это последовательность букв, цифр, символов
подчёркивания (_) и знаков доллара ($). Цифра не может быть первым
символом идентификатора, т. к. тогда интерпретатору JavaScript труднее
отличать идентификаторы от чисел.
Идентификаторы выступают в качестве имён переменных, функций,
свойств объекта и т. д.
10
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Создайте файл внешнего скрипта [Link]. В файле напишите
следующий код:
alert("Добро пожаловать в JavaScript!");
// иногда будет не просто, но...
alert("У нас все получится!");
Подключите файл скрипта, проверьте работоспособность.
ЗАДАНИЕ 2
Создайте файл внешнего скрипта [Link]. В файле напишите
следующий код:
let time = Date();
// выводим текущее время
alert(time);
Подключите файл скрипта, проверьте работоспособность.
11
Практическая работа 2
ПЕРЕМЕННЫЕ И КОНСТАНТЫ
Содержание
Стань 1. Объявление переменной
профессионалом! 2. Вывод в документ
3. Консоль браузера
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Объявление переменной
Переменная — это именованная область памяти, в которой мы можем
хранить какие-либо данные, например, строки или числа. Переменные
похожи на условный контейнер в памяти компьютера. Этим контейнерам
можно присваивать имена и впоследствии использовать эти имена для
извлечения и изменения хранимых данных.
Объявление с помощью ключевого слова var
Для объявления или, другими словами, создания переменной
используется ключевое слово var (от variable — переменная):
var myLogin;
var age;
После объявления переменной ей можно присвоить некоторое
значение, это называется инициализацией переменной:
var myLogin;
myLogin = "master"; // сохраним в переменной строку
// можно совместить объявление переменной и ее инициализацию
var age = 33; // сохраним в переменной число
Значение переменной сохраняется в соответствующей именованной
области памяти и в дальнейшем доступ к этой области осуществляется при
обращении по имени переменной. Если переменную не инициализировать, то
ее начальное значение остается неопределенным undefined.
ПРИМЕР 1
<html>
<head>
<script>
// объявляем переменную myLogin
var myLogin;
// инициализируем переменную текстовым значением
myLogin = "master";
12
// объявляем переменную age
var age;
// выводим значения переменных
alert(myLogin); // выведет содержимое переменной
alert(age); // выведет undefined
</script>
</head>
<body>
<div align="center"><h2>Переменные и константы</h2></div>
</body>
</html>
ПРИМЕР 2
<html>
<head>
<script>
// объявляем и инициализируем переменную myLogin
let myLogin = "master";
// объявляем переменную age
let age;
// выводим значения переменных
alert(myLogin); // выведет содержимое переменной
alert(age); // выведет undefined
13
</script>
</head>
<body>
<div align="center"><h2>Переменные и константы</h2></div>
</body>
</html>
Особенности использования let:
let не позволяет обратиться к переменной до её объявления;
let препятствует объявлению в одной области видимости переменных
(и/или функций) с одинаковым именем;
let является блочной или локальной (видна только внутри блока с
областью видимости, ограниченной текущим блоком кода).
Имена переменных
Имена переменных могут начинаться с одного из следующих
символов:
буква в верхнем или нижнем регистре: a-z, A-Z
символ нижнего подчеркивания: _
знак доллара: $
Вслед за первым символом имени переменной можно использовать
последовательность букв, цифр и символа подчеркивания без пробелов и
знаков препинания.
Примеры правильных имен переменных:
var myName;
var my_adress;
var _x;
var tel512_7456;
Примеры неправильных имен переменных:
var 512group; // начало не может быть цифрой
var my-adress; // дефис '-' не является разрешеннымсимволом
var my adress; // пробел не является разрешенным символом
Константы
Константа – это переменная, которая не изменяется в процессе
выполнения скрипта. Создать именованную константу можно используя
ключевое слово const.
Как правило константы записываются большими буквами, чтобы их
можно было отличить от обычных переменных:
const PI = 3.14;
const AGE = 18;
Имена констант не должны совпадать с именами переменных,
объявленных в той же области видимости, например, следующий сценарий
выдаст синтаксическую ошибку.
14
const MY_LOGIN = "master";
var MY_LOGIN = "master"; // ошибка
Попытки изменить значение константы также приведут к ошибке.
const FLAG = 1;
FLAG = 2; //ошибка
alert(FLAG); // не сработает
ПРИМЕР 3
<html>
<body>
<div align="center">
<h2> Переменные и константы</h2>
<script>
// вывод текста, заключенного в HTML-теги
[Link]('<b>Изучаем JavaScript!</b>');
// или так
let str = 'text2';
[Link]('<b>' + str + '</b>');
// вывод текста с переносом строки
[Link]('text3 <br> text4');
// вывод числового значения
[Link] ('<br>12345<br>');
// вывод текста из переменной
var email = 'master@[Link]';
[Link] (email);
</script>
</div>
</body>
</html>
Консоль браузера
Для вызова инструментов разработчика нажмите F12, в открывшейся
панели вы чаще всего будете пользоваться двумя вкладками: Elements и
Console. В первой вкладке вы можете получать информацию по структуре
страницы, а во второй - отладочную информацию JavaScript. По умолчанию в
инструментах разработчика откроется вкладка Console (Консоль).
Объект Console служит для доступа к средствам отладки браузера.
Работа с ним может отличаться в разных браузерах, но эти методы и свойства
по факту поддерживаются всеми браузерами.
15
с[Link]() - выводит сообщение (логирует) в веб-консоль.
ПРИМЕР 4
<html>
<body>
<script>
// определим переменную
var msg = "Stop the World – I Want to Get Off";
// определим массив
var arr = new Array("php", "sql", "javascript", "css");
// выведем данные в консоль
[Link](msg);
[Link](arr);
</script>
<div align="center"><h2> Переменные и константы</h2></div>
</body>
</html>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Используя команду [Link] выведите текст в браузер.
ЗАДАНИЕ 2
Создайте внешний скрипт [Link] (картинки находятся в папке
«Раздаточный материал - Практическая работа №2 - Задание 2»). В скрипте
инициализируйте следующие переменные:
16
let img1 = "<img src='images/[Link]'>"
let img2 = "<img src='images/[Link]'>"
let img3 = "<img src='images/[Link]'>"
Подключите файл внешнего скрипта [Link] и создайте скрипт вывода
изображений соответствующих переменных в браузер. Для вывода
используйте команду [Link].
ЗАДАНИЕ 3
В файле [Link] раздаточного материала «Практическая работа №2»
вам предложен нерабочий скрипт. Включите отладочную панель, исправьте
ошибки, запустите скрипт на выполнение.
Алгоритм выполнения скрипта должен остаться без изменений:
Инициализация переменных.
Вывод переменных в консоль.
Переопределение переменных.
Вывод новых значений переменных в консоль
17
Практическая работа 3
ТИПЫ ДАННЫХ
Содержание
Стань
1. Динамическая типизация
профессионалом! 2. Типы данных
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Динамическая типизация
В JavaScript типы данных можно разделить на две категории:
простые (примитивные) типы;
составные (ссылочные) типы.
JavaScript – это слабо типизированный или динамический язык
программирования, который позволяет определять типы данных,
осуществлять синтаксический анализ и компиляцию «на лету», на этапе
выполнения программы. Это значит, что вам не нужно определять тип
переменной заранее. Тип определится автоматически во время выполнения
программы.
Таким образом, в различных участках программы одна и та же
переменная может принимать значения разных типов.
ПРИМЕР 1
<script>
// инициализируем переменную значениями разных типов
var value = "string"; // строка
value = 7; // число
value = {name: "Иван", login: "master"}; // объект
value = ["php", "javaScript", "python"]; // массив
value = true; // булев
value = null; // нулевой
</script>
ПРИМЕР 2
let name = "Иван";
// Вставим переменную
alert( `Привет, ${name}!` ); // Привет, Иван!
19
// Вставим выражение
alert( `результат: ${1 + 2}` ); // результат: 3
// Иначе
alert( "результат: ${1 + 2}" ); // результат: ${1 + 2} (двойные кавычки ничего
не делают)
Если внутри строки встречаются кавычки, то их необходимо
экранировать слешем (\).
ПРИМЕР 3
Пусть у нас есть текст "Бюро "Рога и копыта"". Вывод текста в браузер
может быть выполнен несколькими способами:
// экранируем дополнительные кавычки
let company = "Бюро \"Рога и копыта\"";
// можно использовать другой вид кавычек
let company1 = "Бюро 'Рога и копыта'";
// или так
let company2 = 'Бюро "Рога и копыта"';
Интерполяция
ПРИМЕР 4
let user = "Eugene";
// интерполируем переменную в строку
let msg = `Hello our dear ${user}!`;
[Link](msg); // Hello our dear Eugene!
Для встраивания значений выражений (значений переменных и
констант) в строку перед выражением ставится знак доллара $, после
которого в фигурных скобках указывается выражение. Так, в примере выше
${user} означает, что в этом месте строки надо встроить значение
переменной user.
Подобным образом можно встраивать и больше количество данных.
ПРИМЕР 5
<script>
let login = "master";
let id = 3157;
let access = true;
// формируем строку сообщения
let msg = `Login: ${login} (id=${id}), allow full access: ${access}`;
// вывод в консоль сформированного сообщения
[Link](msg); // Login: master (id=3157), allow full access: true
</script>
20
Тип данных Boolean
ПРИМЕР 6
<script>
let login = null; // объявление и инициализация переменной
let email; // объявление переменной
[Link]("login: ", login); // login: null
[Link]("email: ", email); // email: undefined
</script>
Оператор typeof
С помощью оператора typeof можно получить тип переменной.
JavaScript определяет спецификацию оператора следующим образом:
// Обычный синтаксис
typeof 5 // Выведет "number"
ПРИМЕР 7
<script>
// экспериментируем с типами данных
21
var value = "string"; // строка
[Link](typeof(value)); // string
value = 7; // простое число
[Link](typeof(value)); // number
value = {name: "Иван", login: "master"}; // объект
[Link](typeof(value)); // object
value = ["php", "javaScript", "python"]; // массив
[Link](typeof(value)); // object (обратить внимание)
value = true; // булев тип
[Link](typeof(value)); // boolean
value = null; // специальный тип null
[Link](typeof(value)); // object
</script>
ПРИМЕР 8
<script>
// литеральное объявление объекта
let book = {
"name": "Мастер и Маргарита",
"author": "М.Булгаков",
"year": 1940,
"genre": "Мистика",
"bestseller": true
};
// выводим в консоль
[Link](typeof book); // тип переменной book
[Link](book); // описание объекта
</script>
ПРИМЕР 9
<script>
// объявление объекта конструктором
let book = new Object();
// инициализация свойств объекта
[Link] = "Мастер и Маргарита";
22
[Link] = "М.Булгаков";
[Link] = 1940;
[Link] = "Мистика";
[Link] = true;
// выводим в консоль
[Link](typeof book); // тип переменной book
[Link](book); // описание объекта
</script>
ПРИМЕР 10
<script>
// литеральное объявление объекта
let book = {
"name": "Мастер и Маргарита",
"author": "М.Булгаков"
};
// добавление свойств объекта
[Link] = 1940;
[Link] = "Мистика";
[Link] = true;
// выводим в браузер
[Link]("<h2>", [Link], "</h2>");
[Link]("<p>Автор: ", [Link], "</p>");
[Link]("<p>Год: ", [Link], "</p>");
[Link]("<p>Жанр: ", [Link], "</p>");
[Link]("<p>Бестселлер: ", [Link], "</p>");
</script>
23
alert(lang[1]); // php
alert(lang[2]); // perl
Мы можем заменить элемент:
lang[0] = "python";
[Link](lang); // ['python', 'php', 'perl']
…или добавить новый элемент к существующему массиву:
lang[3] = "python";
[Link](lang); // ['javaScript', 'php', 'perl', 'python']
ПРИМЕР 11
<script>
// инициализация массива
let book = ["Мастер и Маргарита", "М.Булгаков", 1940];
book[3] = "Мистика";
book[4] = true;
// вывод значений массива в браузер
[Link]("<h2>", book[0], "</h2>");
[Link]("<p>Автор: ", book[1], "</p>");
[Link]("<p>Год: ", book[2], "</p>");
[Link]("<p>Жанр: ", book[3], "</p>");
[Link]("<p>Бестселлер: ", book[4], "</p>");
</script>
На практике чаще всего случается, что один тип отлично расширяет
другой.
ПРИМЕР 12
<script>
// литеральное объявление объекта
let book = {
"name": "Мастер и Маргарита",
"author": "М.Булгаков",
"year": 1940,
"genre": ["Мистика", "Триллер", "Драма", "Детектив"],
"bestseller": true
};
// формируем строку для вывода в браузер,
// используем синтаксис косых кавычек
let line = `
<h2> ${[Link]} </h2>
<p><i>Автор:</i> ${[Link]} <p>
<p><i>Год: </i> ${[Link]} <p>
<p><i>Жанр: </i>
<ul>
<ol>${[Link][0]}</ol>
<ol>${[Link][1]}</ol>
<ol>${[Link][2]}</ol>
<ol>${[Link][3]}</ol>
</ul>
<p>
<p><i>Бестселлер: </i>${[Link]}
24
`;
// выводим строку в браузер
[Link] (line);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В скрипте тега head инициализируйте набор простых переменных для
описания персональных данных условного педагога. Имена переменных
можете использовать свои или воспользоваться предложенными
подсказками. Для вывода каждой строки используйте команду
[Link].
Фамилия (surname).
Имя (name).
Отчество (patronymic).
Должность (ocupation).
Уровень образования (degree).
Категория (category).
Образование (education).
Преподаваемая дисциплина (discipline).
Примечание (note).
Ниже представлен примерный формат для вывода:
ЗАДАНИЕ 2
В файле предыдущего задания (Задание 1) вами был инициализирован
набор простых переменных для описания персональных данных педагога.
Замените простые переменные массивом JavaScript. Выведите данные
массива в браузер. Для вывода каждой строки используйте команду
[Link].
25
ЗАДАНИЕ 3
В файле предыдущего задания (Задание 1) вами был инициализирован
набор простых переменных для описания персональных данных педагога.
Преобразуйте набор простых переменных в объект JavaScript. Выведите
данные объекта в браузер. Для вывода каждой строки используйте команду
[Link].
ЗАДАНИЕ 4
Преобразуйте алгоритм вывода данных в браузер. Используя
возможность интерполяции переменных сформируйте строку для вывода.
26
Практическая работа 4
ПРЕОБРАЗОВАНИЕ ТИПОВ
Содержание
1. Явное и неявное преобразование
Стань 2. Преобразование к типу String
3. Преобразование к типу Number
профессионалом! 4. Преобразование к типу Boolean
5. Функции parseInt и parseFloat
6. Операторы вместо функций
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Введение
JavaScript различает типы данных:
примитивные;
ссылочные.
Существуют типы данных, которые могут содержать значения:
Строка (String).
Числовой (Number).
Логический (Boolean).
Объект (Object).
Есть объектные типы:
Объект (Object).
Массив (Array).
Есть типы данных, которые не могут содержать значения:
Нулевой (Null).
Неопределенный (Undefined).
Чтобы определить тип переменной, в JavaScript используется оператор
typeof.
[Link] (typeof 3); // number
27
Явное и неявное преобразование
Преобразование типов данных может быть явным и неявным. Так как
JavaScript – это слабо типизированный или динамический язык
программирования, значения могут быть конвертированы между различными
типами автоматически. Это называют неявным приведением типов.
Обычно неявное преобразование происходит, когда в выражениях
используют значения различных типов.
Перед выполнением операции JS проверяет типы операндов.
ПРИМЕР 1
<script>
// преобразование типов способно преподносить сюрпризы
[Link] ("2 + 2 не равно '2' + '2'");
// здесь логично
[Link] ("2 + 2 = ", 2 + 2 ); // 4
// здесь вроде бы тоже
[Link] ("'2' + '2' = ", '2' + '2'); // 22
// но, что будет здесь?
[Link] ("'2' + 2 = ", '2' + 2); // 22
// а здесь?
[Link] ("('2' + 2) / 10 = ", ('2' + 2) / 10); // 2.2
// всегда задавайте себе вопросы!!!
</script>
ПРИМЕР 2
<script>
// неявное преобразование
// 2 преобразуется в "2"
[Link]("5" + 2); // 52
// но,
// "5" преобразуется в 5
[Link]("5" - 2); // 3
// "5" и "2" преобразуется в 5 и 2
[Link]("5" * "2"); // 10
// null преобразуется в 0
[Link](5 + null); // 5
// но,
// null преобразуется в "null"
[Link]("5" + null); // 5null
</script>
28
Явное приведение типов
Явное преобразование – это когда преобразование типов данных
выполняет сам программист. Явное преобразование иначе называют
приведением типов.
ПРИМЕР 3
<script>
// неявное преобразование
[Link] ('2' + 2); // 22
// явное преобразование строку '2' к числу 2
[Link] (Number('2') + 2); // 4
// явное преобразование число 2 к строке '2'
[Link] (String(2) + String(2)); // 22
</script>
Преобразование даты
String позволяет преобразовывать дату (тип Date) в строку.
// преобразование даты
String(new Date());
ПРИМЕР 4
<script>
// приведение к строке
[Link](String(21)); // "21"
[Link](21 + ""); // "21"
[Link](String(-77.7)); // "-77.7"
[Link](null); // null
[Link](String(null)); // "null"
29
[Link](undefined); // undefined
[Link](undefined + ""); // "undefined"
[Link](true + false); // 1
[Link](true + false + ""); // "1"
// можно проверить
[Link](typeof(true + false)); // number
[Link](typeof(true + false + "")); // string
</script>
Преобразование строк
Преобразование строк осуществляется по правилам:
При преобразовании строк в числа интерпретатор обрезает пробелы, а
также управляющие символы (перенос строки \n, табуляция \t, вертикальная
табуляция \v и др.), которые находятся в начале или в конце строки
(Number(" 25 \n"); // 25).
Если строка содержит только цифры с унарным оператором - или +
либо без знака, она всегда преобразуется в целое десятичное число
(отрицательное или положительное). Начальные нули игнорируются,
например "007" преобразуется в 7 (Number("-0025.3 "); // -25.3).
Если строка представляет собой число в шестнадцатеричном формате,
она преобразуется в соответствующее целое десятичное число
(Number("0xA"); // 10).
Пустая строка преобразуется в 0 (Number(" "); // 0).
30
Преобразование даты
Функция Number позволяет преобразовывать значения даты (тип Date)
в числа:
Number(new Date());
ПРИМЕР 5
<script>
// приведение к числу
[Link](Number("25")); // 25
[Link](Number(null)); // 0
[Link](Number(undefined)); // NaN
[Link](Number(" 25 \n")); // 25
[Link](Number("-0025.3 ")); // -25.3
[Link](Number("0xA")); // 10
[Link](Number(" ")); // 0
[Link](Number("++2")); // NaN
[Link](Number(true)); // 1
[Link](Number(false)); // 0
[Link](Number(new Date())); // 1657882426358
</script>
ПРИМЕР 6
<script>
// приведение к логическому типу
[Link](Boolean('')); // false
[Link](Boolean(0)); // false
[Link](Boolean(NaN)); // false
[Link](Boolean(null)); // false
[Link](Boolean(undefined)); // false
[Link](Boolean(false)); // false
[Link](Boolean("привет")); // true
[Link](Boolean("12345")); // true
</script>
31
Функции parseInt и parseFloat
Функция parseInt
Для преобразования строки в целое число в JavaScript есть еще
замечательная функция parseInt():
[Link](parseInt("25") + 5); // 30
ПРИМЕР 7
<script>
// Number не приводит тип
[Link](Number("123qwerty")); // NaN
// parseInt справляется
[Link](parseInt("123qwerty")); // 123
[Link](parseInt("123qwerty") + 3); // 126
// но тоже не всегда
[Link](parseInt("qwerty123")); // NaN
</script>
Функция parseFloat
Для преобразования строк в дробные числа применяется функция
parseFloat(), которая работает аналогичным образом.
ПРИМЕР 8
<script>
[Link](parseInt("123.8qwerty")); // 123
[Link](parseFloat("123.8qwerty") + 3); // 123.8
</script>
32
Операторы вместо функций
Вместо функций для явного преобразования типов данных можно
использовать операторы.
Например, если один из операндов оператора сложения + является
строкой, то другой операнд также преобразуется в строку. Операции
инкремента -- или декремента ++ над строкой приведут её к числу.
Унарный оператор плюс + преобразует свой операнд в число, а унарный
оператор отрицания ! преобразует операнд в логическое значение.
ПРИМЕР 9
<script>
[Link]( true + "" ); // "true" = String(true))
[Link]( +"123" ); // 123 = Number("123"))
[Link]( !"0" ); // false
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Наберите код. Попробуйте предсказать вывод до отображения
результата выражения в консоли.
<script>
// примеры преобразований типов
[Link](true + false + true); // 2
[Link]('привет ' + (8 / "2")); // привет 4
[Link]('number' + 5 + 1); // number51
[Link](5 + 1 + "number"); // 6number
[Link]('' + (null + 1)); // "1" (null=0)
[Link]('' + (undefined + 1)); // NaN (undefined=NaN)
[Link]('' + ("4" - 3)); // 1
[Link]("4.5px" - 3); // NaN
[Link]((parseInt("4.5px") - 3)); // 1
[Link]((parseFloat("4.5px") - 3)); // 1.5
</script>
ЗАДАНИЕ 2
Для выполнения используйте файл раздаточного материала [Link]
(в папке раздаточный материал – практическая работа №4 – Задание №2).
1. Подключите файл [Link].
2. Создайте массив.
3. Запишите в массив предопределенные переменные из файла
[Link]. При записи в массив переменных соблюдайте дополнительные
условия:
фамилию, имя и отчество записать одним элементом массива;
33
общий стаж и стаж работы в техникуме записать в виде числа;
актуальность данных записать в виде логического значения;
дату записать в виде строкового представления.
4. Значения предопределенных переменных менять нельзя.
Использовать операции приведенния типов.
5. Добавьте в массив строковые элементы обозначающие:
название сайта;
электронную почту.
6. Выведите массив в консоль.
ЗАДАНИЕ 3
Для выполнения используйте файл раздаточного материала [Link]
(в папке «Раздаточный материал – Практическая работа №4 – Задание №2»).
1. Подключите файл [Link].
2. Создайте объект.
3. Запишите в свойства объекта предопределенные переменные из
файла [Link]. При записи переменных соблюдайте дополнительные
условия:
общий стаж и стаж работы в техникуме записать в виде дробных чисел;
актуальность данных записать в виде логического значения;
дату записать в виде строкового представления.
4. Значения предопределенных переменных менять нельзя.
5. Добавьте строковые свойства объекта, обозначающие:
название сайта;
электронную почту.
6. Выведите объект в консоль.
7. Выведите данные объекта в виде форматированной строки в
браузер.
34
Практическая работа 5
ДИАЛОГОВЫЕ ОКНА
Содержание
Стань 1. Метод alert ()
профессионалом! 2. Метод confirm ()
3. Метод prompt ()
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Метод alert ()
Метод alert() позволяет выводить диалоговое окно с заданным
сообщением и кнопкой OK.
Синтаксис:
alert ('Сообщение');
Методу alert() передается только один аргумент — отображаемое
сообщение. В простейшем случае текст сообщения, заключенный в двойные
или одинарные кавычки, вводится внутри круглых скобок. В более сложном
случае текст сообщения может быть представлен в виде предварительно
созданной переменной JS. Сообщение может быть как строкового, так и
числового типа.
Чтобы отобразить многострочное сообщение, строки можно разделять
управляющим символом переноса строки – \n.
ПРИМЕР 1
<script>
// инициализируем строку
// строка содержит управляющий символ - перенос строки
let msg = 'Привет! Мы будем изучать JS,\nКто с нами, присоединяйся!';
// отдаем строку в качестве аргумента
alert(msg);
</script>
Формируемые строки могут быть достаточно сложными и содержать не
только управляющий символ переноса строки, но и переменные.
ПРИМЕР 2
<script>
// формируемые строки могут быть достаточно сложными
let user = "Алиса";
let msg = 'Привет ' + user + '! Мы будем изучать:\n ' +
'- PHP\n' +
35
'- JavaScript\n' +
'- Python\n' +
'Желаю удачи!';
// вывод строки
alert(msg);
</script>
Окно предупреждения генерируется самим браузером, поэтому
внешний вид окна в различных браузерах может несколько различаться.
Метод confirm ()
Метод confirm() позволяет вывести диалоговое окно с сообщением и
двумя кнопками — OK и Отмена (или Да / Нет - в зависимости от браузера),
благодаря чему пользователь может подтвердить или отменить некоторое
действие.
В отличие от метода alert этот метод возвращает логическую
величину, значение которой зависит от того, на какой из двух кнопок
кликнул пользователь.
Чтобы можно было определить, какую кнопку выбрал пользователь,
метод confirm возвращает true, если был клик на кнопке OK, и false, если
клик на кнопке Отмена или системной кнопке закрытия окна — X.
Синтаксис:
var result = confirm('Сообщение');
result — это логическое значение true / false, указывающее, было
ли выбрано OK или Отмена. Возвращаемое значение можно использовать в
дальнейших выражениях.
ПРИМЕР 3
<script>
// нажимаем OK
let ok = confirm("На ваш счет будет переведен миллион долларов. Вы
согласны?");
[Link](ok); // true
// нажимаем Отмена
let undo = confirm("С вашего счета будут списаны все денежные средства.
Ok?");
[Link](undo); // false
</script>
Пример использования результата выбора представлен в следующем
примере. Метод confirm() выводит сообщение и ожидает, пока пользователь
подтвердит или отменит некоторую операцию, кликнув на одной из кнопок.
ПРИМЕР 4
<script>
// анализируем реакцию пользователя на диалоговое окно
if (confirm("Молочный коктейль за 5 долларов заказывали?")) {
alert ("Получите бургер Биг Кахуна в подарок!");
36
} else {
alert ("Он не стоит пяти баксов...");
};
</script>
Метод prompt ()
Метод prompt() выводит на экран диалоговое окно, которое
запрашивает у пользователя информацию.
Вместе с кнопками OK и Отмена оно содержит текстовое поле для
ввода данных. В отличие от методов alert() и confirm() данный метод
принимает два параметра: сообщение и значение, которое должно появиться
в текстовом поле ввода данных по умолчанию.
Синтаксис:
var result = prompt("Сообщение", "Значение по умолчанию");
result — строка, содержащая текст, введенный пользователем,
или значение null.
Сообщение — строка текста для отображения пользователю.
Этот параметр является необязательным и может быть опущен, если в окне
подсказки ничего не должно отображаться.
Значение по умолчанию — строка, которая отображается по
умолчанию в поле ввода. Второй аргумент можно оставить пустым или
записать так - "".
Если пользователь кликает на кнопке OK, метод prompt() возвращает
значение, введенное в текстовое поле, а если выбирается кнопка Отмена или
окно закрывается иным образом, то возвращается null.
ПРИМЕР 5
<script>
// нажмите OK
let str1 = prompt("Нажмите OK.\nОтклик в консоле - пустая строка.");
[Link](str1);
// нажмите OK
let str2 = prompt("Нажмите OK.\nПроверьте отклик в консоле.", "Привет, вы
нажали OK");
[Link](str2);
// нажмите Отмена
let undo = prompt("Нажмите Отмена.\nПроверьте отклик в консоле.", "Вы
нажали Отмена");
[Link](undo);
</script>
ПРИМЕР 6
<script>
// переменная name получит значение введенное пользователем
37
// или значение по умолчанию
var name = prompt("Здравствуйте, представьтесь, пожалуйста", "noName");
// диалоговое окно принятия решения
if (confirm("Вы хотите просмотреть скрытый раздел?")) {
// если пользователь выбрал Ok
alert("Рады видеть вас, уважаемый(ая) " + name + "!");
[Link]("<h2>Раздел персональных данных пользователя " + name +
"</h2>");
} else {
// если пользователь выбрал Отмена
[Link]("<h2>Ждем вас еще!</h2>");
}
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Инициализируйте три переменные, содержащие название языков
программирования, которые вы хотели бы изучить. С использованием
синтаксиса косых кавычек сформируйте строку для передачи аргументом
методу alert. Выведите строку в браузер. Примерный формат вывода
продемонстрирован на рисунке.
ЗАДАНИЕ 2
Создайте объект, содержащий данные о педагоге. При создании
объекта инициализируйте следующие его свойства (в скобках указаны
возможные значения):
category (Высшая);
site ([Link]);
emai (master@[Link]);
note (Нет данных).
Следующим свойствам объекта задайте значения динамически,
используя диалоговое окно prompt.
38
surname (Баранов);
name (Виктор);
patronymic (Александрович);
ocupation (Преподаватель специальных дисциплин);
degree (Высшее);
Данные объекта должны быть выведены в виде отформатированной
строки в контент документа.
39
Практическая работа 6
DOM-ДЕРЕВО
Содержание
Стань 1. Автоисправление
профессионалом! 2. Другие типы узлов
3. Взаимодействие с консолью
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
ПРИМЕР 1
<!DOCTYPE HTML>
<html>
<head>
<title>О лосях</title>
</head>
<body>
Правда о лосях.
</body>
</html>
40
Текст внутри элементов образует текстовые узлы, обозначенные как
#text. Текстовый узел содержит в себе только строку текста. У него не может
быть потомков, т.е. он находится всегда на самом нижнем уровне.
Обратите внимание на специальные символы в текстовых узлах:
перевод строки: ↵ (в JavaScript он обозначается как \n);
пробел: ␣.
Пробелы и переводы строки – это полноправные символы, как буквы
и цифры. Они образуют текстовые узлы и становятся частью дерева DOM.
Так, в примере выше в теге <head> есть несколько пробелов перед <title>,
которые образуют текстовый узел #text (он содержит в себе только перенос
строки и несколько пробелов).
Автоисправление
Если браузер сталкивается с некорректно написанным HTML - кодом,
он автоматически корректирует его при построении DOM.
Например, в начале документа всегда должен быть тег <html>. Даже
если его нет в документе – он будет в дереве DOM, браузер его создаст. То
же самое касается и тега <body>.
При генерации DOM браузер самостоятельно обрабатывает ошибки в
документе, закрывает теги и так далее.
ПРИМЕР 2
<p>Привет
<li>Мама
<li>и
<li>Папа
41
ПРИМЕР 3
<!DOCTYPE HTML>
<html>
<body>
Правда о лосях.
<ol>
<li>Лось -- животное хитрое</li>
<!-- комментарий -->
<li>...и коварное!</li>
</ol>
</body>
</html>
Взаимодействие с консолью
При работе с DOM нам часто требуется применить к нему JavaScript.
Например: получить узел и запустить какой-нибудь код для его изменения,
чтобы посмотреть результат. Вот несколько подсказок, как перемещаться
между вкладками Elements и Console.
Для начала:
1. На вкладке Elements выберите первый элемент <li>.
2. Нажмите Esc – прямо под вкладкой Elements откроется Console.
3. Последний элемент, выбранный во вкладке Elements, доступен в
консоли как $0; предыдущий, выбранный до него, как $1 и т.д.
Теперь мы можем запускать на них команды. Например
$[Link] = 'red' сделает выбранный элемент красным, как здесь:
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Используя ресурс: [Link] -
постройте дерево DOM из HTML-кода предложенного документа.
<!DOCTYPE HTML>
42
<html lang="ru">
<head>
<meta charset="utf-8">
<title>Программирование в среде JavaScript</title>
<link href="[Link]" rel="stylesheet">
</head>
<body>
<h1>Веб-программирование и дизайн</h1>
<ul>
<li>все о веб-технологиях</li>
<li>примеры кодов</li>
<li>работы студентов</li>
<li>обширная практика применения</li>
</ul>
<!-- и многое другое -->
</body>
</html>
ЗАДАНИЕ 2
Вам предложен файл изображения:
ЗАДАНИЕ 3
Вам предложен неработающий скрипт. Сам код скрипта ошибок не
содержит. Добейтесь работоспособности приведённого скрипта.
<!DOCTYPE HTML>
<html lang="ru">
43
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<script>
// создаем переменную, содержащую текст приветствия
let msg = prompt("Введите текст приветствия")
// выводим текст в документ
[Link]("[Link]").innerText = msg;
</script>
</head>
<body>
<header>
<h1 align="center">Введение в JavaScript</h1>
</header>
<h1 class="msg"></h1>
</body>
</html>
Отчет по практической работе
Продемонстрировать работы преподавателю.
44
Практическая работа 7
ДОСТУП К DOM
Содержание
Стань
1. Методы выбора DOM элемента
профессионалом! 2. Свойства
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Дети
childNodes содержит все дочерние узлы, в т. ч. текстовые
children содержит все дочерние узлы-элементы
firstChild первый дочерний узел
firstElementChild первый дочерний узел-элемент
lastChild последний дочерний узел
lastElementChild последний дочерний узел-элемент
Родитель
parentNode родительский узел
parentElement родительский узел-элемент
45
Братья (сестринские)
previousSibling предыдущий сестринский узел
previousElementSibling предыдущий сестринский узел-элемент
nextSibling следующий сестринский узел
nextElementSibling следующий сестринский узел-элемент
Методы для работы с DOM содержатся в глобальном объекте docu-
ment. Document содержит все узлы DOM и функции для работы с ним:
[Link] - ссылка на узел html;
[Link] - ссылка на узел body;
[Link] - ссылка на узел head.
ПРИМЕР 1
<body> <script>
<h2>Цитаты Венедикта Ерофеева</h2> // ссылка на узел body
<!-- блок цитат Венедикта Ерофеева --> let body = [Link];
<div> // получили доступ к элементу header
<p>Надо привыкнуть смело, в глаза let header = [Link];
людям, говорить о своих достоинствах. // далее спускаемся вниз по дереву узлов
Кому же, как не нам самим, знать, до какой let h = [Link];
степени мы хороши?</p> // используя цепочку получаем ссылку на
<p>Потому что с тех пор, как помню узел комментария
себя, я только и делаю, что симулирую let comment = [Link];
душевное здоровье, каждый миг, и на это let div = [Link];
расходую все (все без остатка) и let p = [Link];
умственные, и физические, и какие угодно // получаем ссылку на текстовый узел
силы.</p> первого элемента p
</div> let txt = [Link];
// выводим значение узла комментария
<script>……</script> [Link]([Link]);
// выводим значение текстового узла
</body> [Link]([Link]);
</script>
46
ПРИМЕР 2
<body>
<div>
<p>Хорошо идти, когда зовут. Ужасно —
когда не зовут. Однако лучше всего, когда
зовут, а ты не идёшь (С.Довлатов).</p>
</div>
<script>
// ссылка на узел body
let body = [Link];
[Link](body);
// первый дочерний узел для body это
#text
let text = [Link];
// [Link](text);
// последний дочерний узел для body
это script
let script = [Link];
[Link](script);
</script>
<p>А как же я??? :(</p>
<!-- скрипт тебя не видит... -->
</body>
ПРИМЕР 3
<body>
<header> <h1 align="center">Доступ к
элементам DOM</h1> </header>
<div>
<p>Хорошо идти, когда зовут. Ужасно —
когда не зовут. Однако лучше всего, когда
зовут, а ты не идёшь (С.Довлатов).</p>
</div>
<script>
// ссылка на узел body
let body = [Link];
[Link](body);
// первый дочерний html-узел для body
это header
let header = [Link];
// [Link]("--> ", header);
// последний дочерний html-узел для
body это script
let script = [Link];
// [Link]("--> ", script);
</script>
<p>А как же я??? :(</p>
<!-- скрипт тебя не видит... -->
</body>
47
Свойства nextSibling, previousSibling
Свойства, позволяющие получить следующий и предыдущий узел (в
том числе, текст и комментарии).
ПРИМЕР 4
<body>
<header> <h1 align="center">Доступ к
элементам DOM</h1> </header>
<div>
<p>Хорошо идти, когда зовут. Ужасно —
когда не зовут. Однако лучше всего, когда
зовут, а ты не идёшь (С.Довлатов).</p>
</div>
<script>
// ссылка на узел body
let body = [Link];
[Link](body);
// первый дочерний html-узел для body
это header
let header = [Link];
// [Link]("--> ", header);
// следующий узел за header это пустой
#text
let txt1 = [Link];
// [Link]("--> ", txt1);
// следующий узел за txt1 это div#citate
let div1 = [Link];
// [Link]("--> ", div1);
// следующий узел за div#citate это
пустой #text
let txt2 = [Link];
// [Link]("--> ", txt2);
// вернемся обратно к div#citate
let div2 = [Link];
// [Link]("--> ", div2);
</script>
</body>
48
ПРИМЕР 5
<body>
<header> <h1 align="center">Доступ к
элементам DOM</h1> </header>
<div id="citate">
<p>Хорошо идти, когда зовут. Ужасно —
когда не зовут. Однако лучше всего, когда
зовут, а ты не идёшь (С.Довлатов).</p>
</div>
<h3>Ваш отзыв о статье</h3>
<form id="myform">
Имя <input name="name" type="text"
value="Каин" /><br /><br/>
Логин <input name="login" type="text"
value="master" /><br /><br/>
Пароль <input name="pwd"
type="password" value="12345" /><br
/><br/>
</form>
<script>
// ссылка на узел body
let body = [Link];
[Link](body);
// первый дочерний html-узел для body
это header
let header = [Link];
// [Link]("--> ", header);
// следующий html-узел за header это
div#citate
let div = [Link];
// [Link]("--> ", div);
// следующий html-узел за div это h3
let h3 = [Link];
// [Link]("--> ", h3);
// следующий html-узел за h3 это form
let form = [Link];
// [Link]("--> ", form);
</script>
</body>
49
ПРИМЕР 6
<script>
// ссылка на узел body
let body = [Link];
[Link](body);
// первый дочерний html-узел для body
это header
let header = [Link];
// [Link]("--> ", header);
// следующий html-узел за header это
div
let div = [Link];
// [Link]("--> ", div);
// дочерние узлы для узла div
let nodes = [Link];
// [Link]("--> ", nodes);
// дочерние html-узлы для узла div
let html_nodes = [Link];
// [Link]("--> ", html_nodes);
</script>
До сих пор мы создавали переменные и присваивали каждой
переменной свой узел. Количество переменных можно сократить, объединив
ссылки на дерево узлов в цепочки вызовов.
Например строки:
let body = [Link];
let header = [Link];
let div = [Link];
ПРИМЕР 7
<script>
// последовательное получение доступа к нужному узлу
let body = [Link];
let header = [Link];
let div = [Link];
let h3 = [Link];
let form = [Link];[Link](form);
// последовательный доступ можно объединить в цепочкувызовов
// вряд ли это сделает код более читабельным
form = [Link]
[Link];
[Link](form);
</script>
50
Свойства parentNode, parentElement
Свойства, позволяющие получить непосредственного родителя:
parentNode - непосредственный родитель;
parentElement - непосредственный родитель (html-элемент).
ПРИМЕР 8
<script>
// последовательное получение доступа к
нужному узлу
let body = [Link];
let header = [Link];
let div = [Link];
let h3 = [Link];
let form = [Link];
[Link](form);
// последовательный доступ можно объединить
в цепочку вызовов
// вряд ли это сделает код более читабельным
form =
[Link]
[Link];
[Link](form);
</script>
Метод item
item() - возвращает узел с указанным индексом в DOM. Существует два
способа получить доступ к узлу по указанному индексу.
Синтаксис:
[Link](index); или nodes[index];
index - индекс узла в списке, узлы нумеруются по мере их появления в
документе. Индекс начинается с 0.
Возвращаемое значение - узел с указанным индексом. Null если
индекс находится вне диапазона. Самый простой и распространенный способ
– указание индекса в квадратных скобках [index].
ПРИМЕР 9
<script>
// ссылка на узел body
let body = [Link];
// получаем доступ к узлу div#citate
let div = [Link];
// получаем набор дочерних узлов-элементов (теги <p>)
let nodes = [Link];
// вывод в консоль дочерних узлов
[Link]("0 --> ", [Link](0));
[Link]("1 --> ", [Link](1));
[Link]("2 --> ", [Link](2));
</script>
51
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №7 - Задание 1»
предложен файл [Link]. Получите доступ к элементам списка первого
уровня. Выведите в консоль текстовые узлы списка в следующем
порядке:
1. Криминальное чтиво.
2. Зеленая миля.
3. Побег из Шоушенка.
4. Бойцовский клуб.
5. Форрест Гамп.
ЗАДАНИЕ 2
Вам предложен следующий список:
<h1>Яркие цитаты Владимира Ильича Ленина*</h1>
<div id="citate">
<h3>Учиться, учиться и ещё раз учиться.</h3>
<h3>Из всех искусств для нас важнейшим является кино.</h3>
<h3>Богатые и жулики - это две стороны одной медали.</h3>
<h3>Не так опасно поражение, как опасна боязнь признать своё
поражение.</h3>
<h3>Нас помнят, пока мы мешаем другим.</h3>
<h3>Равнодушие есть молчаливая поддержка того, кто силён, того, кто
господствует.</h3>
</div>
<p>* - В.И.Ленин - вождь мирового пролетариата
Напишите скрипт, вызывающий метод prompt() и сохраняющий
значение введенного пользователем индекса. Получите доступ к коллекции
52
узлов h3 блока div#citate. По введенному пользователем индексу получите
доступ к текстовому узлу соответствующего элемента h3. Выведите
текстовый узел в консоль.
53
Практическая работа 8
СВОЙСТВО УЗЛОВ
Содержание
Стань
1. Классы DOM узлов
профессионалом! 2. Встроенные свойства узлов
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
ПРИМЕР 1
// выбираем узлы документа
let header = [Link];
let div = [Link];
let p = [Link];
let span = [Link];
54
let txt = [Link];
let comment = [Link];
let script = [Link];
55
ПРИМЕР 2
<body> <script>
<header><h1 align="center">Свойства //ссылка на узел body
узлов</h1></header> let body=[Link];
<h2>Оскар Уайльд – цитаты</h2> // получили доступ к элементу header
<!-- блок цитат --> let header=[Link];
<div id="citate"> // далее спускаемся вниз по дереву узлов
<p>У меня очень let div = head-
непритязательный вкус — достаточно [Link];
самого лучшего.</p> let p = [Link]; // выводим
<p>Все сочувствуют несчастьям значение html-узла p
своих друзей, и лишь немногие — [Link]([Link]);
радуются их успехам.</p> // изменим значение узла
<p>Я слышал столько клеветы в [Link] = "Очень опасно встретить
Ваш адрес, что у меня нет сомнений: женщину, которая полностью тебя понимает.
Вы — прекрасный человек!</p> Это обычно кончается женитьбой.";
</div> </script>
</body>
outerText
Свойство outerText устанавливает или возвращает текстовое
содержимое указанного узла. Это свойство похоже на внутреннее свойство
innerText. Есть важное отличие при установке внешнего текста элемента,
потому что сам выбранный элемент удаляется.
Синтаксис:
[Link];// получить текстовое содержимое узла
[Link] = "newtext";//установить текстовое содержимое
(заменить весь узел)
ПРИМЕР 3
<body>
…как и в примере 2…
<script>
//ссылка на узел body
let body=[Link];
// получили доступ к элементу header
let header = [Link];
// далее спускаемся внизпо дереву узлов
let div = [Link];
let p = [Link];
// выводим значение html-узла p
[Link]([Link]);
// изменим значение узла используя innerText
[Link] = "<b> Очень опасно встретить женщину, которая полностью
тебя понимает. Это обычно кончается женитьбой.</b>";
// изменим значение узла используя outerText
[Link] = "<b>Очень опасно встретить женщину, которая полностью
тебя понимает. Это обычно кончается женитьбой.</b>";
</script>
56
textContent
Свойство textContent содержит только текст внутри этого текстового
узла и его потомков, за вычетом всех тегов.
Синтаксис:
[Link];// получить текстовое содержимое узлаи всех его
потомков
[Link] = "text";//установить текстовое содержимое узла
При установке нового текстового содержимого, все дочерние узлы
удаляются и заменяются одним текстовым узлом, содержащем указанную
строку.
ПРИМЕР 4
<body>
…как и в примере 2…
<script>
// ссылка на элемент div
let div = [Link]
ling;
// выведем textContent элемента
[Link]([Link]);
// пока отличий от innerText невидно
[Link]([Link]);
// определим новое текстовое содержимое узла div
// h1 - не сработает ;)
[Link] = "<h1>Упс..., содержимое блока div удалено</h1>";
// на замене innerText работает аналогично
// [Link] = "<h1>Упс..., содержимое блока div удалено</h1>";
</script>
</body>
innerHTML
Свойство innerHTML позволяет получить или установить содержимое
узла элемента.
Синтаксис:
[Link];// получить содержимое узла
[Link]="element";//установить содержимое узла
Значение, возвращаемое innerHTML – всегда валидный HTML-код.
При записи можно попробовать записать что угодно, но браузер исправит
ошибки.
ПРИМЕР 5
<body> <script>
<header><h1 align="center">Свойства // ссылка на узел body
57
узлов</h1></header> let body = [Link];
<h2>Великие цитаты Льва // получили доступ к элементу header
Толстого</h2> let header = [Link];
<!-- блок цитат --> // далее спускаемся вниз по дереву
<div id="citate"> узлов
<p><i>Если нет сил гореть и разливать let h = [Link];
свет, то хоть не засти его.</i></p> let div = [Link];
<p><i>Знание только тогда знание, let p =
когда оно приобретено усилиями своей [Link];
мысли, а не памятью.</i></p> // выводим значение html-узла p
<p><i>Ученый — тот, кто много знает [Link]([Link]);
из книг; образованный — тот, кто // изменим значение узла
усвоил себе все самые [Link] = "<b> Думай хорошо
распространенные в его время знания и и мысли созреют в добрые
приемы; просвещенный — тот, кто поступки.<b>";
понимает смысл своей жизни.</i></p> // а вот здесь теги в строке уже имеют
</div> значение
</script>
</body>
outerHTML
Свойство outerHTML позволяет получить или установить элемент
целиком.
Синтаксис:
[Link];// получить элемент
[Link]="element";//установить элемент
ПРИМЕР 6
<script>
//ссылка на узел body
let body=[Link];
// получили доступ к элементу headerlet
header=[Link];
// далее спускаемся вниз по дереву узлов
let h = [Link];
let div = [Link];
let p = [Link];
// выводим html-узел, соответсвующий первому элементу p
[Link]([Link]);
// заменим узел целиком
[Link] = "<h2>Есть три вещи, которых боится большинство людей:
доверять, говорить правду и быть собой.</h2>";
</script>
58
Синтаксис:
[Link]; // получить значение узла
[Link] = "new node";// установить значение узла
ПРИМЕР 7
<script>
//ссылка на узел body
let body=[Link];
// получили доступ к элементу header
let header=[Link];
// далее спускаемся вниз по дереву узлов
let h = [Link];
let div = [Link];
let p = [Link];
// получаем ссылку на текстовый узел первого элемента p
let txt = [Link];
// выводим содержимое текстового узла
[Link]([Link]);
// изменим узел
[Link] = "Почему я такой большой дядя, а веду себя, как маленькая тетя?";
</script>
nodeName
Свойство nodeName возвращает имя указанного узла.
Синтаксис:
[Link];
Возможныезначения
возвращает тэг для узлов элементов, в верхнем регистре;
возвращает имя атрибута для узлов атрибутов;
возвращает "#text" для текстовых узлов;
возвращает "#comment" для узлов комментариев;
возвращает "#document" для узлов документа.
ПРИМЕР 8
<script>
//ссылка на узел body
let body=[Link];
// элемент header
let header = [Link];
[Link]([Link]);//HEADER
// элемент h2
let h = [Link];
[Link]([Link]);// h2
// пустой текстовый узел
let txt = [Link];
[Link]([Link]);// #text
// комментарий
let comment = [Link];
59
[Link]([Link]);// #comment
</script>
nodeType
Свойство nodeType возвращает тип узла.
Синтаксис:
[Link];
Возвращаемое значение: число, представляющее тип узла.
Всего существует 12 типов, в таблице представлены некоторые из
узлов:
Значение Описание
1 Узел элемента (возвращает корневой элемент документа, для HTML-
документов это элемент HTML)
2 Узел атрибута (возвращает атрибут элемента XML – или HTML документа)
3 Текстовый узел (#text)
8 Узел комментария
ПРИМЕР 9
<script>
//ссылка на узел body
let body=[Link];
// элемент header
let header = [Link];
[Link]([Link]);// 1
// элемент h2
let h = [Link];
[Link]([Link]);// 1
// пустой текстовый узел
let txt = [Link];
[Link]([Link]);// 3
// комментарий
let comment = [Link];
[Link]([Link]);// 8
</script>
nodeValue
Свойство nodeValue возвращает или устанавливает значение узла.
Эквивалентно свойству data. На практике чаще используют data, так как оно
короче в записи.
Синтаксис:
[Link];// получить значение узла
[Link] = "value";// установить значение узла
Возвращаемое значение: строка, представляющая значение узла.
Возможные значения:
60
возвращает пустое значение для узлов элементов и узлов документа;
возвращает значение атрибута для узлов атрибутов;
возвращает содержимое текстовых узлов;
возвращает содержимое для комментариев узлов.
ПРИМЕР 10
<script>
//ссылка на узел body
let body=[Link];
// получили доступ к элементу h2
let h = [Link];
// ссылка на узел комментарий
let comment = [Link];
// ссылка на текстовый узел
let txt = [Link];
// выводим в консоль значение узлов
[Link]([Link]);
[Link]([Link]);
// устанавливаем новое значение узлов
[Link]="Кто хочет удержать – тот теряет. Кто готов с улыбкой
отпустить – того стараются удержать.";
[Link] = "Эрих Мария Ремарк блок цитат";
</script>
tagName
Свойство tagName возвращает имя тега указанного элемента.
Синтаксис:
[Link];
Возвращаемое значение: строка, представляющая имя тега элемента в
верхнем регистре.
ПРИМЕР 11
<script>
//ссылка на узел body
let body=[Link];
// элемент header
let header = [Link];
[Link]([Link]); // header
// элемент h2
let h = [Link];// H2
[Link]([Link]); // текстовый узел
let txt = [Link];
[Link]([Link]);// undefined
// комментарий
let comment = [Link];
[Link]([Link]); // undefined
// элемент div
let div = [Link];
[Link]([Link]);//DIV
</script>
61
hidden
Атрибут и DOM-свойство hidden указывает на то, видим ли мы
элемент или нет. Свойство может быть использовано в HTML или назначено
при помощи JavaScript.
ПРИМЕР 12
<script>
// ссылка на элемент div
let div = [Link];
// набор элементов p
let set = [Link]; // скрываем второй абзац (18+)
[Link](set[1].hidden = true);
// set[1] = [Link](1)
</script>
ПРИМЕР 13
<script>
let form = [Link];
// вывод свойств узла form
[Link]([Link], [Link]);
let input = [Link];
// вывод свойств узла input
[Link]([Link], [Link]);
let a = [Link];
// вывод свойств узла a
[Link]([Link], [Link]);
</script>
Пользовательские свойства
Узлы DOM – это обычные JavaScript объекты. А у объектов есть
свойства. Поэтому любому узлу можно назначить свойство, используя
обычный синтаксис.
Значением свойства объекта может быть любой JS тип.
62
ПРИМЕР 14
<div id="content"> <script>
<pre> // ссылка на элемент div
«Мой дядя самых честных let div =
правил, [Link]
Когда не в шутку занемог, ling;
Он уважать себя заставил // добавим набор пользовательских
И лучше выдумать не мог. свойств
Его пример другим наука; div._id = 1105;
Но, боже мой, какая скука div._title = "Евгений Онегин";
С больным сидеть и день и div._author = {name : "Александр",
ночь, patronymic : "Сергеевич", surname : "Пушкин"};
Не отходя ни шагу прочь! div._characters = ["Евгений Онегин",
Какое низкое коварство "Татьяна Ларина", "Ольга Ларина", "Владимир
Полуживого забавлять, Ленский"];
Ему подушки поправлять, // выводим свойства элемента div
Печально подносить лекарство, // стандартные свойства узла-элемента
Вздыхать и думать про себя: [Link]("Cтандартные свойства:");
Когда же черт возьмет тебя!» [Link]([Link]);
</pre> [Link]([Link]);
</div> // пользовательскте свойства узла-
элемента
[Link]("Пользовательские свойства:");
[Link](div._id);
[Link](div._title);
[Link](div._author.surname);
[Link](div._characters[1]);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №8 - Задание 1»
вам предложен файл [Link]. Ознакомьтесь со структурой документа.
Напишите скрипт, создайте JS-объект со следующими свойствами:
text, тип текстовый;
author, тип JS-объект, со свойствами: name, surname, patronymic;
title, тип текстовый;
date, тип текстовый;
characters, тип массив.
Имя свойств объекта соответствуют идентификаторам (id) блоков div.
Поместите в свойства объекта текстовый контент соответствующих
блоков. Используя [Link] выведите объект в консоль.
Вид объекта в консоле представлен на рисунке.
63
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №8 - Задание 2»
вам предложен файл [Link] и внешний скрипт [Link]. Скрипт собирает
текстовые данные HTML-документа и упаковывает их в объект. В качестве
скрипта можете использовать скрипт, созданный вами в предыдущем
задании.
Подключите внешний скрипт. При подключении учтите, скрипт
работает с DOM документа, а поэтому должен быть подключен, когда
документ полностью сформирован.
Напишите скрипт, выводящий данные объекта в браузер.
64
Практическая работа 9
АТРИБУТЫ И СТИЛИ
Содержание
Стань
1. Свойства для работы с атрибутами
профессионалом! 2. Свойство attributes
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
DOM свойства
Когда браузер загружает страницу, он парсит HTML-код и генерирует
из него DOM-объекты. Все элементы страницы станут DOM-объектами со
своими встроенными свойствами, которые учитываются браузером при
построении дерева визуализации. Узел, соответствующий тегу p имеет один
набор свойств, узел div – другой набор, узел #text: – третий.
DOM-узлы – это обычные объекты JavaScript. Объекты обладают
свойствами, которые можно изменять, технически нас никто не
ограничивает, разработчик может добавить своё собственное свойство к
объекту.
ПРИМЕР 1
<div>
<p>Любовь к ближнему не котируется на бирже современных отношений.</p>
<p>О, дайте мне хоть разок посентиментальничать. Я так устал быть
циником!</p>
</div>
<script>
// ссылка на элемент div
let div = [Link];
// назначили собственное свойство элементу
[Link] = "Блок цитат Владимира Набокова"
// встроенное свойство
[Link]([Link]);
// встроенное свойство
[Link]([Link]);
// пользовательское свойство
[Link]("--> ", [Link]);
</script>
HTML-атрибуты
У HTML тегов могут быть атрибуты. Когда браузер парсит HTML,
чтобы создать DOM-объекты для тегов, он распознаёт стандартные атрибуты
65
и создаёт для них DOM-свойства. Большинство стандартных HTML-
атрибутов становятся свойствами соответствующих объектов.
ПРИМЕР 2
<script>
// ссылка на элемент div
let div = [Link];
[Link] = "Блок цитат Владимира Набокова"
// встроенное свойство
[Link]([Link]);
// пользовательское свойство
[Link]([Link]);
// свойство из стандартного атрибута id тега div
[Link]([Link]);
</script>
Таким образом, когда у элемента есть id или другой стандартный
атрибут, для него создаётся соответствующее свойство, но, преобразование
атрибута в свойство не происходит, если атрибут нестандартный.
ПРИМЕР 3
<div id="citate" myattr="non- <script>
standard-attribute"> // ссылка на элемент div
<p>Любовь к ближнему let div =
не котируется на бирже [Link].
современных nextElementSibling;
отношений.</p> [Link] = "Блок цитат Владимира Набокова"
<p>О, дайте мне хоть // встроенное свойство
разок [Link]([Link]);
посентиментальничать. Я // пользовательское свойство
так устал быть [Link]([Link]);
циником!</p> // стандартный атрибут
</div> [Link]([Link]);
// нестандартный атрибут
[Link]([Link]);
</script>
Стандартный атрибут для одного тега может быть нестандартным для
другого. Например, атрибут type является стандартным для элемента input
(HTMLInputElement), но не является стандартным для body
(HTMLBodyElement).
Стандартные атрибуты описаны в спецификации для
соответствующего класса элемента.
66
Однако, это справедливо не для всех атрибутов.
Например: атрибуту class соответствует свойство className, атрибуту
data - свойство dataset.
ПРИМЕР 4
<div id="citate" class="card"> <script>
<p>Любовь к ближнему не // ссылка на элемент div
котируется на бирже современных let div =
отношений.</p> [Link]
<p>О, дайте мне хоть разок [Link];
посентиментальничать. Я так устал // имя атрибута = имя свойства
быть циником!</p> [Link]([Link]);
<p>Он продолжал молчать, и // имя атрибута class, имя свойства
она замолчала тоже, и стала className
рыться в сумке, мучительно ища в [Link]([Link]); // undefined
ней тему для разговора.</p> [Link]([Link]); // card
</div> </script>
Многие элементы HTML имеют только базовый набор атрибутов: id,
class, style и title, а также языковые атрибуты lang и dir.
ПРИМЕР 5
<div id='citate'> <script>
Эх, тройка! Птица тройка, // ссылка на узел div
кто тебя выдумал? Знать, у let div =
бойкого народа ты могла только [Link]
родиться, в той земле, что не Sibling;
любит шутить, а ровнем-гладнем // скроем элемент
разметнулась на полсвета, да и [Link] = true;
ступай считать версты, пока не </script>
зарябит тебе в очи...
</div>
id
Свойство id позволяет установить или возвратить идентификатор
элемента (значение атрибута id элемента).
67
Синтаксис:
[Link]; // возвращает значение
[Link] ="id" // установить значение
где: id - идентификатор элемента.
Возвращаемое значение: строка, содержащая идентификатор
элемента.
ПРИМЕР 6
<div id='citate'> <script>
…как и в примере 5… // ссылка на узел body
</div> let body = [Link];
let header = [Link];
let div = [Link];
// поменяем атрибут id
[Link] = "plus";
// к узлу применились настройки из <style>
// для идентификатора id
[Link]("Текущий идентификатор элемента: id =",
[Link]);
</script>
className
Свойство className устанавливает или возвращает значение атрибута
class.
Синтаксис:
[Link]; // возвращает значение
[Link] = "name"; // устанавливает значение
где: name - задает имя класса элемента. Чтобы применить несколько
классов, необходимо разделить их пробелами.
Например: [Link] = "test demo";
Возвращаемое значение: строка, представляющая класс, или
разделенный пробелами список классов, элемента.
ПРИМЕР 7
<div id="citate"> <script>
…как и в примере 5…. // ссылка на узел div
</div> let div =
[Link];
// добавим в свойство className два класса
[Link] = "go plus";
// выведем значение свойства
[Link]([Link]); // go plus
</script>
classList
Свойство classList содержит список (псевдомассив) классов элемента.
68
Синтаксис:
[Link]; // возвращает список классов
Для работы с этим массивом можно воспользоваться циклом или
встроенными методами:
Метод Описание
[Link](class1, Добавляет один или несколько имен классов элемента.
class2,...) Если указанный класс уже существует, не будет добавлен
[Link]
Удаляет один или несколько имен классов из элемента.
(class1, class2,...)
[Link]
Проверяет, имеется ли класс (true) или нет (false)
(class)
Добавляет класс, если его нет, или удаляет его, если он
[Link](class)
уже есть
ПРИМЕР 8
Добавление и удаление <script>
классов: // ссылка на узел div
let div =
<div id="citate" class="go"> [Link];
…как и в примере 5…. // добавим узлу class="border"
</div> [Link]("border");
// добавим узлу class="font"
[Link]("font");
// удалим class="go"
[Link]("go");
// проверим наличие классса с именем "go"
if ([Link]("go"))
[Link]("go class detected");
else [Link]("go class not found");
</script
style
Свойство style возвращает объект, который дает доступ к стилю
элемента на чтение и запись.
ПРИМЕР 9
<div id="citate" class="go"> <script>
…как и в примере 5…. // ссылка на узел div
</div> let div =
[Link];
// выведем объект style
[Link]([Link]);
// изменим некоторые CSS-свойства узла
[Link] = "darkgrey";
[Link] = "#fff";
[Link] = "2px dotted red";
[Link] = "20px";
</script>
69
cssText
Свойство cssText позволяет задать CSS стили массово одной строкой.
При этом все содержимое атрибута style перезаписывается.
Синтаксис:
[Link]; // возвращает значение
[Link] = "свойство 1: значение; свойство 2:
значение..."; // устанавливает одно или несколько значений
ПРИМЕР 10
<div id="citate" class="go"> <script>
…как и в примере 5…. // ссылка на узел body
</div> let div =
[Link];
// перезапишем настройки класса go
[Link] = "background: #fff; border: 1px
solid green; color: #000; font-family: Verdana; font-size:
0.9em";
</script>
Свойство attributes
У любого элемента есть свойство attributes, с помощью которого
можно получить коллекцию его атрибутов, в виде объекта NamedNodeMap.
Доступ к атрибуту в этой коллекции осуществляется по его индексу или с
помощью метода item. Отсчёт атрибутов в коллекции начинается с 0.
Синтаксис:
[Link]; // возвращает объект NamedNodeMap
[Link][index]; // возвращает атрибут по индексу
У любого атрибута есть свойства name и value, с помощью которых
можно получить имя атрибута и его значение:
[Link][index].name; // возвращает имя атрибута
[Link][index].value; // возвращает значение атрибута
[Link][index].value = "value"; // устанавливает значение атрибута
ПРИМЕР 11
<div id="citate" class="go" <script>
title="Н.В. Гоголь" // ссылка на узел body
style="margin:20px; let body = [Link];
border:1px solid #c0c0c0; let div =
padding:10px; background: [Link];
#f5f5f5;"> [Link]("Объект NamedNodeMap: ",
…как в примере 5... [Link]);
</div> // первый атрибут
[Link]("Первый атрибут: ", [Link][0]);
// второй атрибут
[Link]("Второй атрибут: ", [Link][1]);
[Link]("Имя второго атрибута: ",
[Link][1].name);
70
[Link]("Значение второго атрибута: ",
[Link][1].value);
</script>
item
Метод item () возвращает узел атрибута по указанному индексу.
Синтаксис:
[Link](index); // возвращает атрибут по индексу
[Link][index]; // альтернативная форма записи
index - индекс узла атрибута в NamedNodeMap.
ПРИМЕР 12
<div id="citate" title="Н.В. <script>
Гоголь" class="go" // ссылка на узел div
style="border:1px solid let div =
#c0c0c0; background: [Link];
#f5f5f5; padding:10px;"> [Link]("Коллекция атрибутов узла: ",
…как в примере 5... [Link]);
</div> // доступ к первому атрибуту
[Link]([Link](1));
// или так...
[Link]([Link][1]);
[Link]("Имя третьего атрибута: ",
[Link](2).name);
[Link]("Значение третьего атрибута: ",
[Link](2).value);
</script>
length
Свойство length возвращает количество узлов-атрибутов в
NamedNodeMap.
Синтаксис:
[Link]; // возвращает количество атрибутов в
коллекции
ПРИМЕР 13
<div id="citate" class="go" <script>
name="txt" title="Мертвые // ссылка на узел div
души"> let div =
…как в примере 5... [Link];
</div> // вывод свойства length
[Link] ([Link]); // 4
</script>
ПРИМЕР 14
<div id="citate" <script>
title="Мертвые души" // ссылка на узел div
onclick="alert('Мертвые души let div =
(Н.В. Гоголь)')" [Link];
style="margin:20px; // набор -> NamedNodemap
border:1px solid #c0c0c0; // [Link]([Link]);
padding:10px; background: // получим узел атрибута c именем id
#f5f5f5;"> [Link]([Link]("id"));
…как в примере 5... [Link]([Link][0]); // тот же узел, но
</div> через индекс
// получим узел атрибута c именем title
[Link]([Link]("title"));
// [Link]([Link][1]); // тот же узел, но
через индекс
// получим узел атрибута с именем onclick
[Link] ([Link]("onclick"));
// [Link]([Link][2]); // тот же узел, но
через индекс
// получим узел атрибута c именем style
[Link]([Link]("style"));
// [Link]([Link][3]); // тот же узел, но
через индекс
</script>
removeNamedItem
Метод removeNamedItem() удаляет узел с указанным именем в
объекте NamedNodeMap.
Синтаксис:
[Link](nameName); // удаляет
атрибут по индексу
nodeName – имя узла в NamedNodeMap который необходимо удалить.
72
Возвращаемое значение: объект узел, представляющий удаленный
узел атрибута.
ПРИМЕР 15
<div id='citate' <script>
title="Мертвые души" // ссылка на узел div
onclick="alert('Мертвые let div =
души (Н.В. Гоголь)')" [Link];
style="margin:20px; // удалим узел-атрибут
border:1px solid #c0c0c0; var attr = [Link]("id");
padding:10px; background: // удаленный узел-атрибут
#f5f5f5;"> [Link](attr); // id='citate'
…как в примере 5... // получим атрибут id
</div> [Link]([Link]("id")); //
null
</script>
setNamedItem
Метод setNamedItem() добавляет указанный узел к объекту
NamedNodeMap.
Синтаксис:
[Link](node);// удаляет атрибут к коллекции
Параметр:
node - узел для добавления или замены в NamedNodeMap.
Если узел уже существует, то он будет заменен. Замененный узел
будет возвращаемое значением, в противном случае возвращаемое значение
будет нулевым.
createAttribute
Метод createAttribute() создает новый узел атрибута и возвращает его.
Синтаксис:
[Link](name); // создает атрибут
name - строка, содержащая имя атрибута.
ПРИМЕР 16
<style> <script>
#citate { // ссылка на узел div
background-color: lightgrey; let div =
border-color: darkgrey; [Link];
padding: 20px;} // создаем атрибут
</style> var attr = [Link]("id");
<div> …как в примере 5... // назначим атрибуту значение
</div> [Link] = "citate";
[Link](attr);
// или так [Link] = "citate";
</script>
73
Методы для работы с атрибутами
Помимо свойства attributes, которое возвращает атрибуты в виде
NameNodeMap, у каждого элемента есть методы, которые позволяют
работать с его атрибутами более просто. Кроме того, методы позволяют
получить доступ к нестандартным атрибутам, для которых не будет
соответствующих DOM-свойств. Эти методы работают именно с HTML-
атрибутами как они есть в документе.
Фактически, они изменяют код страницы:
значения атрибутов - это всегда строки.
имя атрибута можно указывать в любом регистре, так как HTML не
предъявляет требований к регистру символов в коде.
getAttribute
Метод getAttribute() возвращает значение атрибута, указанного в
качестве параметра. Если данного атрибута у элемента нет, то данный метод
возвращает пустую строку или null.
Синтаксис:
[Link] (nameAttr); // получить атрибут
nameAttr - имя атрибута.
В следующем примере получаем значения стандартных атрибутов
узла, соответствующего HTML-тегу div.
ПРИМЕР 17
<div id="citate" class="go"> <script>
"... женщины, это такой предмет... let header =
просто и говорить нечего! Поди-ка [Link];
попробуй рассказать или передать let div = [Link];
все то, что бегает на их лицах, все те // методы доступа к атрибутам
излучинки, намеки, – а вот просто [Link]("id = ", [Link] ("id"));
ничего не передашь. Одни глаза их [Link]("class = ", [Link]
такое бесконечное государство, в ("class"));
которое заехал человек – и поминай </script>
как звали! ..."
</div>
С помощью свойства attributes или специальных методов Attribute()
можно получить доступ к атрибутам вне зависимости от того, стандартный
он для выбранного элемента или нет.
ПРИМЕР 18
<div id="citate" class="go" name="text" title="Н.В.Гоголь `Мертвые души`">
"... как в примере 17..."
</div>
<script>
let header = [Link];
let div = [Link];
74
// свойства из атрибутов
[Link]("id = ", [Link]);
[Link]("class = ", [Link]);
[Link]("title = ", [Link]);
// свойство из нестандартного атрибут
[Link]("name = ", [Link]); // undefined
[Link]("----------");
// свойства и методы доступа к атрибутам
[Link]("id = ", [Link] ("id"));
[Link]("class = ", [Link](1).value);
[Link]("title = ", [Link] ("title"));
// доступ к нестандартному атрибуту
[Link]("name = ", [Link] ("name"));
</script>
setAttribute
Метод setAttribute() добавляет указанный атрибут к элементу и
присваивает ему указанное значение. Если указанный атрибут у элемента
уже есть, то данный метод изменяет только его значение.
Синтаксис:
[Link] (nameAttr, value); // установить атрибут
nameAttr - имя атрибута;
value – значение атрибута.
ПРИМЕР 19
<style> <script>
#citate { // ссылка на узел div
background-color: lightgrey; let div =
border-color: darkgrey; [Link];
padding: 20px; } // установим атрибут id
</style> // к узлу применились настройки из <style>
<div> [Link] ("id", "citate");
"... как в примере 17 ..." [Link]("Текущий идентификатор элемента: id
</div> =", [Link]("id"));
</script>
removeAttribute
Метод removeAttribute() удаляет указанный атрибут у элемента.
Данный метод имеет один обязательный параметр - это строка, содержащая
имя атрибута, который вы хотите удалить у элемента. Данный метод в
качестве результата ничего не возвращает.
Синтаксис:
[Link] (nameAttr); // удалить атрибут
nameAttr - имя атрибута.
ПРИМЕР 20
<style> <script>
75
#citate { // ссылка на узел div
background-color: lightgrey; let div =
border-color: darkgrey; [Link];
padding: 20px; } // вывод списка узлов атрибутов
</style> [Link] ([Link]);
<div id="citate" // удаляем атрибуты
book="Мертвые души" [Link] ("book");
author="Н.В.Гоголь" [Link] ("author");
>"... как в примере 17 ..." // вывод списка узлов атрибутов
</div> [Link] ([Link]);
</script>
hasAttribute
Метод hasAtrribute() возвращает true, если указанный атрибут
существует у элемента. В противном случае данный метод возвращает false.
Данный метод имеет один обязательный параметр - это строка, содержащая
имя атрибута, который вы хотите проверить на существование у элемента.
Синтаксис:
[Link](nameAttr); // проверить наличие атрибута
nameAttr - имя атрибута.
ПРИМЕР 21
<header> <script>
<h1 align="center">Атрибуты // ссылка на узел body
и стили, часть 2</h1> let body = [Link];
</header> let header = [Link];
<div id="citate"> let div = [Link];
"...как в примере 17..." // true - если атрибут присутствует
</div> [Link] ([Link] ("id"));
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Вам предложены два текстовых блока в тегах div. Напишите скрипт, в
котором все атрибуты блока div#one будут назначены второму блоку div.
<div id="one" class="go" title="Н.В. Гоголь" style="border:1px solid #c0c0c0;
background: #f5f5f5; padding:10px; margin:10px">
Эх, тройка! Птица тройка, кто тебя выдумал? Знать, у бойкого народа ты могла
только родиться, в той земле, что не любит шутить, а ровнем-гладнем
разметнулась на полсвета, да и ступай считать версты, пока не зарябит тебе в
очи...
</div>
<!-- блок к которому применить атрибуты -->
<div>
Не так ли и ты, Русь, что бойкая необгонимая тройка несешься? Дымом
дымится под тобою дорога, гремят мосты, все отстает и остается позади.
76
Остановился пораженный божьим чудом созерцатель: не молния ли это,
сброшенная с неба?...
</div>
<script>
let body = [Link];
// ...
</script>
ЗАДАНИЕ 2
Вам предложены два текстовых блока в тегах div.
<div id='one' class="go" onclick="alert('Никола́
й Васи́
льевич Го́
голь (1809-1852)')">
…Текст как и в задании 1…
</div>
<div id="two" class="go">
…Текст как и в задании 1…
</div>
<script>
let div1 = [Link];
let div2 = [Link];
// ...
</script>
Напишите скрипт, в котором блоку div#two будет назначен узел-
атрибут onclick из блока div#one.
При получении узла-атрибута onclick из блока div#one использовать
метод getNamedItem().
Для создания узла-атрибута onclick в блоке div#two использовать
методы: createAttribute(), setNamedItem().
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №9 - Задание 3»
вам предложен файл [Link], в котором необходимо создать скрипт.
В скрипте с использованием цепочки вызовов получите доступ к
элементу h3 блока footer. Используя метод setAttribute() измените атрибут
align элемента h3 на "right". Выведите текущее свойство align элемента h3 в
браузер.
ЗАДАНИЕ 4
В папке «Раздаточный материал - Практическая работа №9 - Задание 4»
вам предложен файл [Link]. Получите доступ к таблице с
использованием цепочки вызовов.
Примените стилевые настройки для таблицы.
color = '#ff0000';
background = "lightgrey";
font-size = '16px';
font-family = 'arial';
font-style = 'italic';
77
font-weight = "bold";
font-stretch = "condensed";
78
Практическая работа 10
Содержание
Стань 1. Выбор элементов по CSS селектору
2. Методы getElement*
профессионалом! 3. Дополнительные способы
подключения коллекций
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Найти несколько DOM - элементов и получить к ним доступ из
JavaScript можно разными способами: querySelectorAll,
getElementsByTagName, children и так далее.
В итоге в каждом случае будет возвращена коллекция — сущность,
которая похожа на массив объектов, но при этом им не является, на самом
деле это набор DOM-элементов. Стоит учесть, что фактически разные
методы возвращают разные коллекции:
HTMLCollection — коллекция непосредственно HTML- элементов.
Доступ к элементам можно получить по их имени, идентификатору или
номеру индекса.
NodeList — это набор узлов документа (узлов элементов, узлов
атрибутов и текстовых узлов). Доступ к элементам возможен только по их
порядковому номеру.
NodeList и коллекция HTML — это одно и то же (почти). Оба
представляют собой массивоподобные коллекции (списки) узлов
(элементов), извлеченных из документа. Доступ к узлам можно получить по
порядковым номерам. Индекс начинается с 0.
79
ПРИМЕР 1
<h2>Лучшие цитаты от гения
сарказма Станислава Ежи Леца</h2>
<pre>Мастерство подать свою мысль
в лаконичной и хлесткой форме — <script>
это настоящий талант. Самые яркие // выберем все элементы p внутри
цитаты, высказывания и div#citate
советы Леца, которые, как var p =
ободряющий душ, действуют на наш [Link]('div#citate
мозг.</pre> p');
// коллекция NodeList узлов p
<div id="citate"> [Link](p);
<p>Граница между светом и тенью — // узнаем количество найденных
ты.</p> элементов
<p>Тот, кто не разбирается ни в чем, var length = [Link];
может взяться за что угодно.</p> [Link]("Количество элементов в
<p>Безвыходным мы называем коллекции: ", length);
положение, выход из которого нам не </script>
нравится.</p>
<p>Я думал, что опустился на самое
дно, как вдруг снизу постучали…</p>
</div>
ПРИМЕР 2
Доступ к элементам коллекции: HTMLCollection и NodeList:
<script> <script>
// выбор всех элементов tr в документе // выберем элемент div#citate
var set_tr = [Link]('tr'); var div =
// выбор четвертой строки [Link]('div#citat
var tr = set_tr[3]; e')[0];
// выбор всех элементов td внутри nodes = [Link]("p");
выбранной строки tr // коллекция NodeList
var set_td = [Link]('td'); [Link](nodes);
// выбор второй ячейки elements = [Link];
var td = set_td.item(1);
// коллекция HTMLCollection
// выведем информацию по выбранному
[Link](elements);
узлу
</script>
[Link]("Узел: ", td);
[Link]("Тип узла: " + [Link]);
[Link]("Имя узла: " + [Link]);
[Link]("Значение узла: ", [Link]);
</script>
80
querySelector
querySelector – метод, который также как querySelectorAll
осуществляет поиск по CSS селектору, но в отличие от него возвращает не
все найденные элементы, а только первый из них.
Синтаксис:
element = [Link]('selector');
element = [Link]('selector');
Результат метода querySelector аналогичен querySelectorAll
('selector')[0], но в отличие от него он выполняет это намного быстрее.
ПРИМЕР 3
<script>
// поиск по имени тега, тег - p
let el1 = [Link]('p');
[Link](el1); // найден первый элемент p
</script>
Методы getElement*
getElementById
Метод getElementById() возвращает элемент (тег) страницы по его
атрибуту id. В качестве результата метод getElementById возвращает ссылку
на объект или значение null, если элемент с указанным идентификатором не
найден.
Синтаксис:
[Link]('tagID');
tagID - аргумент, который представляет атрибут id тега.
ПРИМЕР 3
<h2>Лучшие цитаты от гения
сарказма Станислава Ежи Леца</h2> <script>
<pre>Мастерство подать свою мысль // получение элемента через
в лаконичной и хлесткой форме — getElementById
это настоящий талант. Самые яркие var el =
цитаты, высказывания и [Link]('citate');
советы Леца, которые, как [Link](el);
ободряющий душ, действуют на наш // получение коллекции дочерних
мозг.</pre> элементов
<div id="citate"> var elements = [Link];
<p>Граница между светом и тенью — [Link](elements);
ты.</p> [Link]("Всего выбрано элементов: ",
<p>Тот, кто не разбирается ни в чем, [Link]);
может взяться за что угодно.</p> </script>
<p>Безвыходным мы называем
положение, выход из которого нам не
нравится.</p> </div>
81
getElementsByClassName
Метод getElementsByClassName() возвращает коллекцию
(HTMLCollection) элементов с определенным классом. Находит элемент и в
том случае, если у него несколько классов, а искомый – один из них. Этот
метод позволяет найти все элементы с указанными классами во всём
документе или в некотором элементе.
Синтаксис:
elements = [Link]('names');
elements = [Link]('names');
names - строка, состоящая из одного или нескольких классов
разделённых между собой с помощью пробела.
Действие метода getElementsByClassName можно очень просто
выполнить с помощью querySelector.
ПРИМЕР 4
getElementsByName: querySelector:
<script> // получение элемента через
// получение коллекции через getElementsByClassName
getElementsByClassName var elem =
var elements = [Link]('sec
[Link]('selec ond');
ted'); // получение элемента через
[Link]("Количество элементов: ", querySelector
[Link]); var elem =
[Link]("1 элемент коллекции: ", [Link]('.second');
elements[0].innerText);
[Link]("2 элемент коллекции: ",
elements[1].innerText);
[Link]("3 элемент коллекции: ",
elements[2].innerText);
</script>
getElementsByTagName
Метод getElementsByTagName() предназначен для получения
коллекции элементов по имени тега.
Синтаксис:
elements = [Link]('tagName');
elements = [Link]('tagName');
tagName - строка с названием тега, который нужно найти. Регистр тега
не имеет значения. Чтобы выбрать все элементы можно использовать *.
Действие метода getElementsByTagName можно очень просто
выполнить с помощью querySelector.
82
ПРИМЕР 5
getElementsByName: querySelector:
<script> // получение элемента через
// получение коллекции по имени getElementsByTagName
тега - h2 var elem =
var h2 = [Link]('li');
[Link]('h2'); // получение элемента через
[Link](h2); querySelector
// получение коллекции по имени тега - var elem = [Link]('li');
table
var table =
[Link]('table');
// выбор тегов tr внутри таблицы
var set =
[Link](0).getElementsByTagName('tr');
[Link](set);
</script>
getElementsByName
Метод getElementsByName() может применяться, когда вам нужно
выбрать коллекцию элементов, имеющих атрибут name с указанным
значением.
Синтаксис:
element = [Link]('value');
value - строка со значением атрибута name в соответствии с которым
нужно найти элементы.
Действие метода getElementsByName можно выполнить с помощью
querySelector.
ПРИМЕР 6
getElementsByName: querySelector:
<script> // получение элемента через
// выбрать элементы с name="prog" getElementsByName
var elems = var elem =
[Link]('prog'); [Link]('login');
// коллекция элементов // получение элемента через
// к коллекции обращаться необходимо querySelector
по индексу var elem =
[Link](elems); [Link]("[name='login']");
// вывод значения второго чекбокса
[Link](elems[1].value);
// выбор элемента с нестандартным
атрибутом
var elems =
[Link]('test');
[Link](elems[0].id); // citate
[Link](elems[0].name); // undefined
</script>
83
Дополнительные способы получения коллекций
forms
Свойство forms возвращает коллекцию всех элементов form в
документе.
Синтаксис:
[Link]; // возвращает коллекцию всех элементов form в документе
[Link]; // возвращает количество элементов в коллекции
[Link][index];// возвращает элемент с указанным индексом или
пустое значение, если индекс находится вне диапазона
[Link](index);// возвращает элемент с указанным индексом или
пустое значение, если индекс находится вне диапазона
ПРИМЕР 7
<script>
alert("Количество форм на странице: " + [Link]);
[Link]("Первая форма: ", [Link][0]);
[Link]("Вторая форма: ", [Link](1));
// получение коллекции форм
let frms = [Link];
// вывод коллекции
[Link](frms);
// коллекция элементов второй формы
let set = frms[1].children;
[Link](set);
</script>
images
Свойство images возвращает коллекцию всех элементов img в
документе.
Синтаксис:
[Link];// возвращает коллекцию всех элементов img в документе
[Link];// возвращает количество элементов в коллекции
[Link][index];// возвращает элемент с указанным индексом или
пустое значение, если индекс находится вне диапазона
[Link](index);// возвращает элемент с указанным индексом
ПРИМЕР 8
<script>
[Link]("Количество ссылок на странице: ", document. [Link]);
// изменим размер изображений
[Link](0).[Link] = "250px";
[Link](1).[Link] = "250px";
[Link](2).[Link] = "250px";
// выберем блок-контейнер изображений
let div = [Link]("#img-container");
// применим к блоку flex-позиционирование
[Link] = "display:flex; flex-direction:row; justify-content:center;";
</script>
84
links
Свойство links возвращает коллекцию всех a и area элементов в
документе, которые имеют атрибут HREF.
Синтаксис:
href [Link];// возвращает коллекцию элементов, имеющие атрибут
[Link];// возвращает количество элементов в коллекции
[Link][index];// возвращает элемент с указанным индексом или пустое
значение, если индекс находится вне диапазона
[Link](index);// возвращает элемент с указанным индексом или
пустое значение, если индекс находится вне диапазона
ПРИМЕР 9
<script>
[Link]("Количество ссылок на странице: ", [Link]);
// изменим свойства ссылок
[Link](0).[Link] = "red";
[Link](1).[Link] = "none";
[Link](2).[Link] = "alias";
[Link](3).[Link] = "Arial";
// получим в переменную коллекцию ссылок
let set = [Link];
// скроем вторую ссылку
// set[1].hidden = true;
</script>
closest
Метод closest ищет ближайший родительский элемент, подходящий
под указанный CSS селектор (сам элемент тоже включается в поиск).
Синтаксис:
let parent = [Link]('selector');
ПРИМЕР 10
<form id="auth">
Имя <input name="name" type="text" value="Фауст" /><br /><br/>
Логин <input name="login" type="text" value="master" /><br /><br/>
Пароль <input name="pwd" type="password" value="12345" /><br /><br/>
Сообщение <textarea name="message"></textarea>
</form>
<script>
// выбираем элемент
let login = [Link]('[name="login"]');
// определяем родителя, получаем его id
let id = [Link]("form").getAttribute("id");
// выводим id родителя
[Link](id);
</script>
85
contains
Метод contains позволяет проверить, содержит ли один элемент внутри
себя другой.
Синтаксис:
let bool = [Link](element);
Возвращаемое значение: возвращает true, если узел является
потомком узла, в противном случае false.
ПРИМЕР 11
<ol id="picture"> <script>
<li> // выбираем первый элемент
<ul>Звёздная ночь let pict =
<li>художник - Винсент ван Гог</li> [Link]('#picture');
<li>год создания - 1889 г.</li> // выбираем второй элемент
<li>расположение - Нью-Йоркский let sel =
музей современного искусства</li> [Link]('.selected');
</ul> // определяем, является ли второй
</li> элемент потомком первого
<li class="selected">
[Link]([Link](sel));
<ul>Девушка с жемчужной серёжкой
</script>
<li>художник - Ян Вермеер</li>
<li>год создания - 1665 г.</li>
<li>расположение - Маурицхёйс</li>
</ul>
</li>
</ol>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №10 - Задание
1» вам предложен файл [Link] со вложенным списком, содержащим
HTML-элемент li с классом selected.
Получите доступ к элементу с использованием свойств узла. Выведите
элемент в консоль.
Получите доступ к элементу с использованием метода querySelector.
Выведите элемент в консоль.
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №10 - Задание
2» вам предложен файл [Link]. В файле находится таблица авиарейсов с
выбранной с помощью радиокнопки строкой. Напишите скрипт, создающий
объект с данными выбранной строки.
Структура объекта может иметь следующий вид.
86
// создадим объект, содержащий данные выбранной строки
obj = {
id:,
from:,
dateFrom:,
to:,
dateTo:,
price:
}
Выведите в браузер данные объекта. Примерный формат вывода
может быть следующим:
<h3>Выбранный элемент</h3>
Код: __ <br/>
Откуда: __ <br/>
Дата и время вылета: __ <br/>
Куда: __ <br/>
Дата и время прилета: __ <br/>
Цена: __ <br/>
Выведите в консоль сам объект.
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №10 - Задание
3» вам предложена HTML-разметка и стили файла [Link]. Стили
определены тремя классами. Напишите скрипт, запрашивающий у
пользователя, какой класс он хотел бы установить для блока #citate.
Взаимодействие с пользователем выполните с помощью диалогового окна
prompt. Выберите блок #citate, установите, заданный пользователем класс
87
Практическая работа 1 1
Содержание
Стань 1. Создание текстовых узлов
профессионалом! 2. Вставка узлов
3. Замена и клонирование узлов
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Создание узлов-элементов
Создание узла-элемента в JavaScript выполняется с помощью метода
createElement.
Синтаксис:
node = [Link]('tag');
Вместо tag необходимо указать тег элемента, который нужно создать.
ПРИМЕР 1
<script>
var div = [Link]('div');
[Link] = 'myclass';
[Link] = 'myid';
[Link] = '<h1>Партия - ум, честь и совесть нашей эпохи!</h1>';
// ищем div в документе
[Link] ([Link]); // нет его... :(
</script>
88
Вставка узлов
Чтобы DOM-узел был показан на странице, его необходимо вставить в
целевой узел документа. В JavaScript методы вставки узлов условно
разделяют следующим образом:
1. Современные методы
[Link] – для добавления узлов или строк в конец node;
[Link] – для вставки узлов или строк в начало node;
[Link] – для вставки узлов или строк до node;
[Link] – для вставки узлов или строк после node.
2. Набор методов InsertAdjacent
[Link]();
[Link]();
[Link]().
Набор современных методов
ПРИМЕР 2
Вставка текстового узла: Вставка узла-элемента:
<script> <script>
let txt = var div = [Link]('div');
[Link]('Догоним [Link] = 'myclass';
и перегоним Америку!'); [Link] = 'myid';
// вставляем текстовый узел в [Link] = '<h1>Даёшь стране
конец документа угля!</h1>';
[Link](txt); // выбираем целевой элемент
// проверим наличие текстового let target =
узла [Link]("header")[0];
[Link] ([Link]); // // вставляем узел-элемент в документ
есть такой ;) [Link](div);
</script> // ищем div в документе
[Link] ([Link]); // находим ;)
</script>
Обратите внимание, методы могут вставлять не только объекты-теги,
но и текстовые элементы как строки.
Рассмотрим вставку узла-элемента и текстового узла на примере
метода append вставки объекта на HTML-страницу.
ПРИМЕР 3
<script>
// создаем узел-элемент тега <p>
let node_p = [Link]("p");
// создаем текстовый узел
let node_txt = [Link]('Жизнь прекрасна, невзирая на
недочеты.');
// в узел node_p вставляем текстовый узел node_txt
node_p.append(node_txt);
89
// выбираем элемент <div id="citate">
let div = [Link]("div#citate");
// в узел-элемент div вставляем узел-элемент node_p
[Link](node_p);
</script>
Протестируем методы before и after.
ПРИМЕР 4
<h2>Топ лучших фильмов (по <script>
версии // выбор целевого элемента (нумерованного
[Link])</h2> списка)
<ol> let target = [Link]("ol");
<li>Зеленая миля</li> // создаем первый узел h2
<li>Криминальное чтиво</li> let h1 = [Link]("h2");
<li>Форрест Гамп</li> let txt1 =
</ol> [Link]("Джентльмены удачи");
[Link] = "red";
[Link](txt1);
[Link](h1)
// создаем второй узел h2
let h2 = [Link]("h2");
[Link] = "blue";
[Link]("Гараж");
[Link](h2);
// вставим первый узел перед списком
[Link](h1);
// вставим второй узел после списка
[Link](h2);
</script>
90
Пример использования метода insertAdjacentElement:
ПРИМЕР 5
<!-- beforebegin --> <script>
<ul> // выберем целевой элемент
<!-- afterbegin --> let ul = [Link]("ul");
<li>PHP</li> // создадим 1-й элемент
<li>MySQL</li> let elem1 = [Link]("h2");
<!-- beforeend --> [Link]("Технологии для Backend-разработчика");
</ul> [Link](elem1);
<!-- afterend --> // создадим 2-й элемент
let elem2 = [Link]("li");
[Link]("<b>Laravel</b>"); // append не понимает
теги
// создадим 3-й элемент
let elem3 = [Link]("li");
[Link] = "<b>Python</b>"; // innerText не
понимает теги
// создадим 4-й элемент
let elem4 = [Link]("div");
[Link] = "<h3>Терпения и сил =)</h3>";
// выполняем вставку
[Link]('beforebegin', elem1);
[Link]('afterbegin', elem2);
[Link]('beforeend', elem3);
[Link]('afterend', elem4);
</script>
Пример использования метода insertAdjacentHTML:
ПРИМЕР 6
<!-- beforebegin --> <script>
<ul> // выберем целевой элемент
<!-- afterbegin --> let ul = [Link]("ul");
<li>PHP</li> // выполняем вставку
<li>MySQL</li> [Link]('beforebegin', "<h2>Технологии
<!-- beforeend --> для Frontend-разработчика</h2>");
</ul> [Link]('afterbegin', "<li>JavaScript</li>");
<!-- afterend --> [Link]('beforeend', "<li>Bootstrap</li>");
[Link]('afterend', "<h3>Терпения и сил
=)</h3>");
// посмотрите консоль разработчика вкладку
Элементы обязательно
</script>
91
Пример использования метода insertAdjacentText:
ПРИМЕР 7
<!-- beforebegin --> <script>
<ul> // выберем целевой элемент
<!-- afterbegin --> let ul = [Link]("ul");
<li>Xara Designer [Link]('beforebegin', "Инструментарий
Pro+</li> графического дизайнера");
<li>Canva</li> [Link]('afterbegin', "Adobe Photoshop");
<!-- beforeend --> // обратите внимание теги в текстовом формате
</ul> [Link]('beforeend', "<li>CorelDRAW
<!-- afterend --> Graphics Suite</li>");
[Link]('afterend', "<h3>Удачи =)");
</script>
ПРИМЕР 8
<h2>Топ лучших <script>
фильмов</h2> // выберем второй элемент исходного списка
<ol> let old_li = [Link]("ol li:nth-child(2)");
<li>Криминальное // создадим первый элемент списка с текстом
чтиво</li> let new_li1 = [Link]("li");
<li>Форрест new_li1.innerText = "Белое солнце пустыни";
Гамп</li> // создадим второй элемент списка с текстом
<li>Зеленая let new_li2 = [Link]("li");
миля</li> new_li2.innerText = "Берегись автомобиля";
</ol>
// заменим элемент исходного списка на новые элементы
old_li.replaceWith(new_li1, new_li2);
</script>
Клонирование узлов
Для создания копии узла предназначен метод cloneNode.
Синтаксис:
copy = [Link](deep);
node – узел, который нужно клонировать;
copy – переменная, в которую нужно поместить новый узел, который
будет копией node;
92
deep – глубина клонирования (по умолчанию false, т.е. выполняется
клонирование только самого элемента node без детей); если установить true,
то node будет скопирован со всеми его детьми.
ПРИМЕР 9
<ol> <script>
<li>Зеленая миля: // сделаем клон элемента <ol> и сохраним в
<ul> <li>режиссёр: Фрэнк переменную
Дарабонт</li> let ol = [Link]("ol").cloneNode(true);
<li>год: 1999</li> // выведем в консоль
</ul> </li> [Link](ol);
<li>Криминальное чтиво: // проведем ограничитель
<ul> <li>режиссёр: Квентин [Link]("<hr>");
Тарантино</li> // выведем в браузер клон списка <ol>
<li>год: 1994</li> </ul> [Link](ol);
</li> </ol> </script>
Удаление узлов
Удалить узел из DOM можно в JavaScript с помощью методов:
removeChild (считается устаревшим);
remove.
Синтаксис:
[Link]();
ПРИМЕР 10
<ol> <script>
<li>Зеленая миля: // выбор второго элемента нумерованного списка
<ul><li>режиссёр: Фрэнк let li = [Link]("ol > li:nth-child(2)");
Дарабонт</li> // удаление выбранного элемента
<li>год: 1999</li> [Link]();
</ul></li> // удаленный элемент вывели в консоль
<li>Криминальное чтиво: [Link](li);
<ul><li>режиссёр: Квентин [Link]("<hr>");
Тарантино</li> // вставка в документ удаленного элемента
<li>год: 1994</li></ul></li> [Link](li);
</ol> </script>
93
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №11 - Задание
1» вам предложен файл [Link]. В файле находится блок цитат.
Напишите скрипт, добавляющий две предложенные цитаты на
позицию первой и последней цитат в блоке. При выполнении задания
разрешается использовать следующие методы:
.createElement()
.createTextNode()
.append()
.prepend()
Выделите вставленные цитаты цветом.
ЗАДАНИЕ 2
Напишите скрипт, создающий список, состоящий из ссылок на картины
известных русских художников.
РЕПИН Илья – Бурлаки на Волге ([Link]
Russian/pic/glrx-671453857) ;
АЙВАЗОВСКИЙ Иван – Девятый вал ([Link]
Russian/pic/glrx-668405151) ;
ШИШКИН Иван – Утро в сосновом лесу ([Link]
Russian/pic/glrx-608117675) ;
АВИЛОВ Михаил – Поединок Пересвета с Челубеем на Куликовом
поле ([Link]
ПЕРОВ Василий – Охотники на привале ([Link]
Russian/pic/glrx-147680664) .
Важно. Первая ссылка создается с помощью метода .createElement().
Последующие ссылки создаются клонированием, с использованием метода
.cloneNode(). Проверьте работоспособность ссылок.
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №11 - Задание
3» вам предложены исходные файлы для выполнения практической работы.
Ваша задача - динамическое создание блоков, содержащих данные о
городах галереи «Самые красивые города мира».
Откройте файл [Link], выполните следующий набор действий:
создайте и подключите файл стилей ([Link]);
подключите файл с данными ([Link]);
94
используя представленную в комментарии структуру (шаблон),
создайте первый блок города;
последующие блоки городов получите клонированием от первого;
используя данные объекта из файла [Link] вставьте контент для
каждого созданного блока;
вставьте в целевой блок <div class=row> созданный контент.
Результат выполнения задания продемонстрирован на рисунке.
95
Практическая работа 12
ОПЕРАЦИИ JAVASCRIPT.
ОПЕРАТОРЫ
Содержание
Стань
1. Арифметические операторы
профессионалом! 2. Операторы присваивания
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Арифметические операторы
Арифметические (математические) операторы используют в качестве
своих операндов числа (или литералы или переменные) и в качестве
результата возвращают одно числовое значение.
ПРИМЕР 1
<script>
// пример 1
let res1 = 8 / 2 + 5 - -18 / 6 * 2;
// (8 / 2) + 5 - (-18 / 6 * 2);
[Link](res1); // 15
// пример 2
var x = 2;
let res2 = 8 / 2 + 6 - -9 * x;
96
[Link](res2); // 28
// пример 3
var x = 5;
var y = 8;
let res3 = x** (3 + 4) / (y + 2) % 2;
[Link](res3); // 0.5
</script>
Операторы присваивания
Операторы присваивания присваивают значения переменным
JavaScript.
В результате операции присваивания операнду слева от оператора
присваивания (знак «=») устанавливается значение, которое берётся из
правого операнда. Таким образом, выражение a= b означает, что a
присваивается значение b.
Существуют также комбинированные (составные) операторы
присваивания, которые используются для сокращённого представления
операций, описанных в следующей таблице:
Оператор Альтернатива Описание
Присваивание. Используется для присваивания значения
= a=b
переменной.
+= a =a + b
Комбинированный оператор. Выполняет присваивание с
-= a =a – b
операцией. Между первыми вторым операндом
*= a =a * b
выполняется соответствующая операция, затем результат
/= a =a / b
присваивается первому операнду.
%= a =a % b
ПРИМЕР 2
<script>
var x = 32;
x /= 4; // аналогично: х = х / 4, x = 8
x %= 3; // аналогично: х = х % 3, x = 2
x *= 7; // аналогично: х = х * 7, x = 14
x -= 9; // аналогично: х = х - 9, x = 5
x += 6; // аналогично: х = х + 6, x = 11
[Link](x); // 11
</script>
97
3. Префиксный декремент (--х) – уменьшает на единицу операнд,
возвращая уменьшенное значение.
4. Постфиксный декремент (х--) – уменьшает на единицу операнд,
возвращая первоначальное значение.
Постфиксные операторы:
1. сначала возвращают значение переменной,
2. затем увеличивают или уменьшают значение этой переменной.
ПРИМЕР3
<script>
var a = 10;
var b = a++;
[Link] (`a=${a}; b=${b}`); // выводит а=11; b=10
</script>
Префиксные операторы:
1. увеличивают или уменьшают значение переменной,
2. возвращают значение этой переменной.
ПРИМЕР4
<script>
var a = 10;
var b = --a;
[Link] (`a=${a}; b=${b}`); // выводит а=9; b=9
</script>
Операции инкремента и декремента на практике применяются очень
часто. Например, они встречаются практически в любом цикле for.
ПРИМЕР 5
<script>
let x=6;
let y=19;
let result=x/2+5--(--y)/x++; // 3 + 5 - -(18) / 6; при этом x = 7, y = 18
[Link]("x=",x);
[Link]("y=",y); //8-(-3)
[Link](result); //11
</script>
Операторы сравнения
Операторы сравнения используются для сопоставления операндов,
результатом выражения может быть одно из двух значений — true или false.
Операндами могут быть не только числа, но и строки, логические значения
и объекты.
98
Чаще всего операции сравнения используются при организации в
программах ветвлений.
Оператор Описание
Равенство. Проверяет две величины на совпадение, допуская
== преобразование типов. Возвращает true, если операнды совпадают, и
false, если они различны.
!= Неравенство. Возвращает true, если операнды неравны
Идентичность. Проверяет два операнда на «идентичность»,
=== руководствуясь строгим определением совпадения. Возвращает true,
если операнды равны без преобразования типов.
Неидентичность. Выполняет проверку идентичности. Возвращает
!==
true, если операнды не равны без преобразования типов.
Больше. Возвращает true, если первый операнд больше второго, в
>
противном случае возвращает false.
Больше или равно. Возвращает true, если первый операнд не меньше
>=
второго, в противном случае возвращает false.
Меньше. Возвращает true, если первый операнд меньше второго, в
<
противном случае возвращает false.
Меньше или равно. Возвращает true, если первый операнд не больше
<=
второго, в противном случае возвращает false.
ПРИМЕР 6
<script>
[Link](5 == "5"); // true
[Link](5 === "5"); // false
[Link](5 == 5.0); // true
[Link](false === 0); // false
[Link](1 !== true); // true
[Link](1 != true); // вернет false, так как true преобразуется в 1
[Link](3 > -3); // true
[Link](3 >= "2"); // true
</script>
Строковые операторы
Оператор сложения (+) может использоваться для объединения строк.
При использовании со строками, оператор сложения (+) часто называют
оператором конкатенации.
1. Контенация (+) – оператор работает слева направо, выполняя
объединение стрток. Если первый операнд является строкой, последующие
операнды будут преобразованы в строки и далее выполнится их объединение.
2. Конкатенация с присваиванием (+=) – выполняется объединение двух
строк и результат присваивается переменной.
3. Сравнение (>,<,>=,<=,==) – строки сравниваются по алфавиту, буквы в
верхнем регистре всегда меньше букв в нижнем регистре.
ПРИМЕР 7
<script>
[Link]("1"+"10"); // 110
99
[Link]("1" + 10); // 110
[Link]("1">"10"); //false
[Link]("10" == 10); // true
[Link](7+3+"негритят"); //10 негритят
[Link]("Карты,деньги,"+1+1+"ствола"); // Карты, деньги, 11 ствола
[Link]("JAVASCRIPT"=="javascript"); //false
x="Стив";
[Link](x+="Джобс"); //Стив Джобс
</script>
Логические операторы
Логические операторы позволяют комбинировать условия,
возвращающие логические величины. Чаще всего используются в условных
выражениях if.
1. Логическое И (&&) – возвращает true, только если оба операнда
истинны. При выполнении операции сначала проверяется значение первого
операнда. Если оно имеет значение false, то значение второго операнда не
учитывается и результату выражения присваивается false.
2. Логическое ИЛИ (II) – возвращает true, если хотя бы один операнд
истинен, т.е. проверяет истинность как минимум одного условия.
3. Логическое НЕ (!) – изменяет значение оператора на обратное – с true на
false и наоборот.
ПРИМЕР8
<script>
let a=3;
let b=5;
let c;
let count=((c=a++--b)+1)&&(a/c); //0.5
//выражение в первых скобках не false, идем дальше (операция - &&)
//результат по выражению(a/c)
//анализ переменных
[Link]("a="+a,"b="+b,"c="+c,"count="+count);
let result=count&&b||-7; //5
//count не false, идем дальше (операция-&&)
//b не false-стоп (операция-||)
//результат по переменной - b
[Link](result);
</script>
Операторы типов
typeof - возвращает типо переменной, может быть записан в двух
формах – в скобках () и без скобок;
instanceof – возвращает true, если объект является экземляром
определенного объектного типа.
ПРИМЕР9
<script>
[Link](typeof undefined); // undefined
100
[Link](typeof true); // boolean
[Link](typeof (false)); // boolean
[Link](typeof 5); // number
[Link](typeof ("")); // string
[Link](typeof null); // object
[Link](typeof {name: ""}); // object
[Link](typeoffunction(){});//function
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Напишите программу, которая вычислит и выведет в консоль
результат выражения:
1+2-3+4
где:
1.«5 в степени 3»
2.«12 разделить на 3»
3. остаток от деления «30 на 4»
4. «минус 7 умножить на 2»
Результат каждого действия сохраните в отдельной переменной.
ЗАДАНИЕ 2
Вам предложен фрагмент кода. Рассчитайте вывод каждой
инструкции [Link] без использования калькулятора и прочих подручных
средств. Напишите программу, сверьте выводы программы с расчетными
значениями.
<script> r = ${r}
let x = 5; x = ${x}
let y = 2; y = ${y}
let r = --x / y; `);
[Link](` let s = (x - --y) / t++ + r;
r = ${r} [Link](`
x = ${x} s = ${s}
y = ${y} t = ${t}
`); r = ${r}
let t = (r++ / y) / x--; x = ${x}
[Link](` y = ${y}
t = ${t} `);
</script>
101
Практическая работа 13
ОПЕРАЦИИ JAVASCRIPT.
РАБОТА СО СТРОКАМИ
Содержание
Стань 1. Объект String
профессионалом! 2. Определение строк
3. Преобразование строк
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Объект String
Объект String используется, чтобы представить и конструировать
последовательность символов.
String — это обёртка над примитивным строковым типом, которая
содержит дополнительные методы работы со строками:
поиска по строке;
строковых преобразований;
получения отдельных символов.
ПРИМЕР 1
<script>
// инициализация примитивной строки
const primitiveString = "Привет, Мир ;)";
// инициализация String Object
const objectString = new String("Привет, Мир ;)");
// выведем типы строк в консоль
[Link](typeof primitiveString); // string
[Link](typeof objectString); // object
</script>
Определение строк
В JavaScript любые текстовые данные являются строками. Строка —
это ноль или больше символов, заключенных в кавычки. Строки
используются для хранения и манипулирования текстовыми данными.
Есть несколько способов создать строку:
одинарными кавычками;
102
двойными кавычками;
обратными кавычками (шаблонная строка).
Записи в одинарных и двойных кавычках, по сути, идентичны.
Шаблонные строки позволяют подставлять в строку значения переменных.
В местах, где нужно вставить значение из переменной используется
синтаксис ${имя_переменной}.
ПРИМЕР 2
<h2>Японская поэзия</h2>
<script>
// выберем целевой элемент
let h2 = [Link]("h2");
// инициируем переменные
let interpreter = "В. Санович";
let scheme = "6-7-7-9-9";
let genre = "Танка";
let collection = "Хякунин иссю (Сто стихотворений ста поэтов)";
// инициируем строку,
// выполняем вставку переменных
let txt = `
<b><p>Я жалею людей <br />
Я жалею людей. <br />
Я презираю людей. <br />
Я отчаялся думать <br />
О печалях этого мира <br />
И в свою печаль погрузился. </b><p>
<hr>
Переводчик: <i>${interpreter}</i> <br />
Схема: <i>${scheme}</i> <br />
Жанр: <i>${genre}</i> <br />
Изборник: <i>${collection}</i>
`;
// вставляем фрагмент в документ
[Link]('afterend', txt);
</script>
Специальные символы
Кавычки, используемые внутри строки, должны отличаться от
кавычек, определяющих строку.
Экранирующий символ (\) преобразует специальные символы в
символы строки:
\" – двойная кавычка;
\n – перенос строки;
\t – знак табуляции.
При использовании символа переноса строки вы должны четко
представлять результат вставки строки в браузер. Символ \n это не <br/>.
ПРИМЕР 3
<h2>Японская поэзия</h2>
103
<p></p>
<script>
let pre=[Link]("p")[0];
//формируем строку,
//в качестве разделителя – символ переноса строки
let hokku = "Осенняя луна\nСосну рисует тушью\nНа синих небесах."
// браузер переносов не видит, ему нужны теги
[Link] =hokku;
[Link](hokku);
</script>
Поиск подстроки
Существует несколько способов поиска подстроки:
indexOf
lastIndexOf
search
includes
startsWith, endsWith
indexOf
Синтаксис:
[Link](substr[, pos]);
Метод indexOf() ищет подстроку substr в строке str, начиная с позиции
pos, и возвращает позицию (индекс), на которой располагается совпадение,
либо -1 при отсутствии совпадений.
Параметры:
substr – строка, представляющая искомое значение.
pos – необязательный параметр. Местоположение внутри строки,
откуда начинать поиск. Может быть любым целым числом.
Метод indexOf() является регистрозависимым.
ПРИМЕР 4
<script>
let str =
"Англичанин мне друг" +
"Но пришлось утопить..." +
"Пакетик чая"
// проверяем вхождение подстрок
[Link] ([Link]("друг")); // 15
[Link] ([Link]("враг")); // -1
[Link] ([Link]("хуже татарина")); // -1
</script>
lastIndexOf
Синтаксис:
[Link](substr[, pos]);
104
Метод lastIndexOf() возвращает позицию (индекс) последнего
вхождения заданного текста в строке, или -1, если ничего не было найдено.
Поиск по строке ведётся от конца к началу, начиная с индекса pos.
Параметры:
substr – строка, представляющая искомое значение.
pos – необязательный параметр. Местоположение внутри строки,
откуда начинать поиск, нумерация индексов идёт слева направо. Может быть
любым целым числом.
Метод lastIndexOf() является регистрозависимым.
ПРИМЕР 5
<script>
// поиск индекса заглавной 'О', ближайшей к концу строки
// такая буква в слове - 'VOLGOGRAD'
// отсчет начинается слева, с позиции - 0
[Link]("Welcome VOLGOGRAD" . lastIndexOf("O")); // 12
search
Синтаксис:
[Link](regexp);
Метод search() возвращает индекс первого сопоставления с
регулярным выражением внутри строки. В противном случае метод вернёт -
1.
Параметр:
regexp – объект регулярного выражения. Если будет передан не объект
регулярного выражения, а простая строка, то она будет неявно
преобразована.
ПРИМЕР 6
<script>
<h2>Японская поэзия</h2> // определяем строку
<pre> str = `И той порою,
<h3> Когда непринуждённо
И той порою, Дождь смывал следы,
Когда непринуждённо Убогими казались мысли
Дождь смывал следы, О проходящем...`;
Убогими казались мысли [Link]([Link]("дождь")); // -1
105
О проходящем... // 'Дождь' <> 'дождь'
</h3> </script>
</pre>
Различия методов search() и indexOf():
метод search() не может принимать второй аргумент начального
положения.
метод indexOf() не может принимать в качестве аргумента регулярные
выражения.
В настоящее время метод indexOf() считается устаревшим и может
встретиться только в старом коде, в новом он просто не нужен: ему на смену
пришел более современный метод includes().
includes
Синтаксис:
[Link](substr[, pos]);
Метод includes() возвращает true, если в строке str есть подстрока
substr, либо false, если нет.
Параметры:
substr – подстрока для поиска в данной строке.
pos – необязательный параметр. Позиция в строке, с которой начинать
поиск строки substr, по умолчанию 0.
Метод используется, если необходимо проверить, есть ли совпадение,
но позиция не нужна. Необязательный второй аргумент includes() позволяет
начать поиск с определённой позиции.
ПРИМЕР 7
<script>
<h2>Японская поэзия</h2> // определяем строку
str = [Link]("h3")[0].
<h3> innerText;
На чумазых котят <br/> // ищем вхождение
Так похожи сережки ивы, [Link]([Link]("сережки")); // true
<br/> // а так?
А ведь тоже цветы! [Link]([Link]("серёжки")); // ???
</h3> </script>
startsWith, endsWith
Синтаксис:
[Link](substr[, pos]);
Метод startsWith() проверяет, начинается ли строка с символов
указанных в скобках, возвращая, соответственно, true или false.
Параметры:
substr – символы, искомые в начале данной строки.
106
pos – необязательный параметр. Позиция в строке, с которой начинать
поиск substr, по умолчанию 0.
Синтаксис:
[Link](substr[, length]);
Метод endsWith() проверяет, заканчивается ли строка символами
указанными в скобках, возвращая, соответственно, true или false.
Параметры:
substr – символы, искомые в конце строки.
length – необязательный параметр. Позволяет искать внутри строки,
обрезая её по диапазону, по умолчанию равен длине строки.
ПРИМЕР 8
<script>
// определяем строку
var str = "Welcome Volgograd";
// тестируем методы
[Link]([Link]("Welcome")); // true
[Link]([Link]("welcome")); // false
[Link]([Link]("VolgograD")); // false
[Link]([Link]("Volgograd", 25)); // true
</script>
ПРИМЕР 9
var str = "Welcome Volgograd";
[Link]([Link](7, 17)); // Volgograd
Если параметр имеет отрицательное значение, позиция учитывается от
конца строки.
107
var str = "Welcome Volgograd";
[Link]([Link](-20,-10)); // Welcome
substring
Синтаксис:
[Link](start [, end]);
Метод substring() аналогичен методу slice(). Возвращает подстроку
строки между двумя индексами, или от одного индекса и до конца строки.
Разница заключается в том, что substring() не может принимать
отрицательные индексы. Если опустить второй параметр, substring() будет
разрезать оставшуюся часть строки.
ПРИМЕР 10
<script>
// полный сотовый номер
let phone = "8(912)552-92-25";
// страна
let country = [Link](0,1);
// оператор
let operator = [Link](2,4);
// регион (может не соответствовать реальному)
let region = [Link](4,5);
// абонент
let abonent = [Link](6);
// формируем строку для вывода
let out = `
<h3>Информация о владельце номера</h3>
Номер: <b>${phone}</b> <br/>
Международный код страны: ${country} <br/>
Оператор сотовой связи: ${operator} <br/>
Регион: ${region} <br/>
Абонент: ${abonent}
`;
// получаем доступ к элементу h2
var el = [Link]("h2");
// вставляем строку в документ
[Link]("afterend", out);
</script>
substr
Синтаксис:
[Link](start [, length]);
Метод substr() похож на slice(). Разница в том, что второй параметр
указывает длину извлеченной подстроки.
Параметры:
start – позиция, с которой начинать извлекать символы;
length – необязательный параметр. Количество извлекаемых символов.
108
ПРИМЕР 11
<script>
// статьи для вывода, в виде массива объектов, каждый объект фрагмент
информации о статье
let article = [
{ teazer: "Художественный дар — это одновременно и талант, и огромный
труд. Так как искусство во многом близко ремеслу, в нем сочетается безусловное
природное дарование и простые технические навыки, без которых настоящего
художника никогда не будет.",
href: [Link] },
{ teazer: "Наверное, в мире нет более известного полотна, чем «Мона Лиза».
Она популярна во всех странах, широко растиражирована как узнаваемый и
броский образ.",
href: [Link]
[Link] },
{teazer: "Художники-передвижники внесли огромную лепту в развитие
русского и мирового искусства, создав совершенно новую эстетическую шкалу и
расширив сюжетный круг станковой живописи.",
href: [Link]
[Link] }
];
// формируем из массива строки-ссылки для вывода
let p1 = `<a href='${article[0].href}' target='blank'>${article[0].[Link](0,31)}
...</a>`;
let p2 = `<a href='${article[1].href}' target='blank'>${article[1].[Link](0,31)}
...</a>`;
let p3 = `<a href='${article[2].href}' target='blank'>${article[2].[Link](0,31)}
...</a>`;
// формируем список из ссылок
let out = `
<ul>
<li>${p1}</li>
<li>${p2}</li>
<li>${p3}</li>
</ul>
`;
// вставляем список в документ
[Link]("h2").insertAdjacentHTML("afterend", out);
</script>
ПРИМЕР 12
<div>
{{img}}
</div>
<script>
// забираем из документа содержимое блока div
var str = [Link]("div").innerHTML;
// выполняем замену
var newstr = [Link](/{{img}}/, "<img src='[Link]' width='350px'>");
// это самое простое применение метода .replace
// возможности метода безграничны (почти;)
// замещаем блок новым содержимым
[Link]("div").innerHTML = newstr;
</script>
Преобразование строк
Преобразование в верхний и нижний регистр
toUpperCase
Синтаксис:
[Link]();
Метод toUpperCase() возвращает значение строки, преобразованное в
верхний регистр. Метод toUpperCase() не изменяет значение самой строки.
ПРИМЕР 13
var str="Welcome Volgograd!";
var upstr = [Link]();
alert(upstr); // WELCOME VOLGOGRAD!
alert(str);//Welcome Volgograd!
toLowerCase
Синтаксис:
[Link]();
Метод toLowerCase() возвращает значение строки, преобразованное в
нижний регистр. Метод toLowerCase() не изменяет значение самой строки.
ПРИМЕР 14
var str="Welcome Volgograd!";
var lowstr = [Link]();
alert(lowstr); // welcome volgograd!
alert(str);//Welcome Volgograd!
110
Преобразование в массив
split
Синтаксис:
[Link]([separator[, limit]);
Метод split() разбивает объект String на массив строк путём
разделения строки указанной подстрокой.
Параметры:
separator – необязательный параметр. Указывает символы,
используемые в качестве разделителя внутри строки.
limit – необязательный параметр. Целое число, определяющее
ограничение на количество найденных подстрок.
ПРИМЕР 15
<pre>
<h2>
Смотрю на футон, созерцаю
Пусть немотствуют уста мои,
Перелетные птицы собрались в стаи
</h2>
</pre>
<script>
// забираем содержимое тега h2,
// вместе со всеми переводами строк и табуляциями
let str = [Link]("pre h2").innerText;
// разделитель - перенос строки: \n
let arr = [Link]("\n");
// вывод массива
[Link](arr);
// разделитель - запятая: ,
arr = [Link](",");
// вывод массива
[Link](arr);
// разделитель - знак табуляции: \t
arr = [Link]("\t");
// вывод массива
[Link](arr);
</script>
111
Метод charAt() возвращает символ по указанному индексу (позиции) в
строке.
Параметр:
index – целое число от 0 до длины строки минус 1.
Символы в строке идут слева направо. Индекс первого символа равен
0, а последнего символа в строке stringName равен [Link] - 1.
Еслипредоставленный вами параметр index выходит за пределы этого
диапазона, JavaScript вернёт пустую строку.
var str = "Hello, User!";
var ch = [Link](0);
alert(ch);//H
charCodeAt
Синтаксис:
[Link](index);
Метод charCodeAt() возвращает код символа по указанному индексу в
строке.
Параметр:
index – целое число больше, либо равное 0 и меньше длины строки;
если параметр не является числом, он устанавливается в 0.
Метод charCodeAt() возвращает NaN, если указанный индекс меньше
нуля или больше длины строки.
var str = "Hello, User!";
var code = [Link](0);
alert(code); // 72
trim
Синтаксис:
[Link]();
Метод trim() возвращает строку с вырезанными пробельными
символами с её концов. Метод trim() не изменяет значение самой строки.
Пробельными символами считаются все собственно пробельные
символы (пробел, табуляция, неразрывный пробел и прочие).
var str = " Hello, User! ";
alert([Link]()); // "Hello, User!"
length
Синтаксис:
[Link];
Свойство length возвращает длину строки.
var str = "ABCDEFGH";
alert([Link]); // 8
112
ПРИМЕР 16
<script>
// определение строк
var en_message = 'Volgograd';
var ru_message = "Привет, мы из Волгограда!";
var empty = '';
// вывод строк в браузер
[Link]('Строка "' + en_message + '" имеет длину ' + en_message.length + '
символов <p>');
[Link]('Строка "' + ru_message + '" имеет длину ' + ru_message.length + '
символ <p>');
[Link]('Пустая строка имеет длину, равную ' + [Link]);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Напишите программу, которая вычислит и выведет в консоль
результат выражения:
Вам предложен фрагмент из произведения М.А. Булгакова «Мастер и
Маргарита», состоящий из десяти (10) абзацев:
Мастер и маргарита (Разговор на Патриарших)
(1) Попав в тень чуть зеленеющих лип, писатели первым долгом
бросились к пестро раскрашенной будочке с надписью "Пиво и воды".
(2) Да, следует отметить первую странность этого страшного майского
вечера. Не только у будочки, но и во всей аллее, параллельной Малой
Бронной улице, не оказалось ни одного человека. В тот час, когда уж,
кажется, и сил не было дышать, когда солнце, раскалив Москву, в сухом
тумане валилось куда-то за Садовое кольцо, - никто не пришел под липы,
никто не сел на скамейку, пуста была аллея.
(3) - "Дайте нарзану", - попросил Берлиоз.
(4) - "Нарзану нету", - ответила женщина в будочке и почему-то
обиделась.
(5) - "Пиво есть?" - сиплым голосом осведомился Бездомный.
(6) - "Пиво привезут к вечеру", - ответила женщина.
(7) - "А что есть?" - спросил Берлиоз.
(8) - "Абрикосовая, только теплая", - сказала женщина.
(9) - "Ну, давайте, давайте, давайте!.. "
(10) Абрикосовая дала обильную желтую пену, и в воздухе запахло
парикмахерской. Напившись, литераторы немедленно начали икать,
расплатились и уселись на скамейке лицом к пруду и спиной к Бронной.
Напишите скрипт, используя конкатенацию строк (операция
соединения нескольких текстовых строк в одну) в двойных кавычках
запишите все абзацы в одну переменную.
113
let str = "абзац 1" +
"абзац 2" +
"абзац 3" + ...
Используя метод [Link], выведите переменную в браузер.
Примерный формат вывода:
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №13 - Задание
2» вам предложен скрипт вывода условного заказа.
Перепишите фрагмент кода формирования строки вывода.
Пусть строка для вывода формируется с помощью конкатенации
строк, оформленных либо в двойные, либо в одинарные кавычки.
114
Практическая работа 14
ОПЕРАЦИИ JAVASCRIPT.
РАБОТА С ЧИСЛАМИ
Содержание
Стань
1. Арифметические операторы
профессионалом! 2. Операторы присваивания
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
В отличие от многих других языков программирования JavaScript не
определяет множество различных числовых типов вроде целочисленные без
знака, с плавающей точкой, короткие, длинные и т.п.
В современном JavaScript существует два типа чисел:
Тип данных number использует числа с плавающей точкой двойной
точности (double precision floating point numbers), а также специальные
значения Infinity, -Infinity и NaN.
Тип BigInt позволяет работать с целыми числами произвольной длины.
BigInt числа нужны достаточно редко.
Форма записи чисел
Для записи чисел используются цифры, для разделения целой и
десятичной части используется точка:
let a = 50; // 50
let b = 4.7; // 4.7
let с = .7; // 0.7
Можно использовать экспоненциальную запись.
let d = 2e3;// 2000 (2*10^3)
let e = 5.8e-2;// 0,058 (5.8*10^-2)
Числа так же могут быть представлены в двоичном (0b),
восьмеричном (0o) или шестнадцатеричном (0x) виде, при выводе на экран
такие числа будут автоматически преобразованы в десятичную систему
счисления.
ПРИМЕР 1
<script>
// двоичная система счисления
const binary = 0b11;
[Link](binary);// 3
// восьмеричная система счисления
const octal = 0o77;
115
[Link](octal);// 63
// шестнадцатеричная система счисления
const hexadecimal = 0xFF;
[Link](hexadecimal);// 255
</script>
Числовые строки
Строки JavaScript могут содержать числовой контент:
var x = 100; // x - число
var y = "100"; // y - строка
JavaScript будет стараться конвертировать строки в числа во всех
арифметических операциях. Это сработает:
var x = "100";
var y = "10";
[Link](x / y); // 10
И это сработает:
var x = "100";
var y = "10";
[Link](x - y); // 90
А вот это не сработает. JavaScript использует оператор «+» для
конкатенации строк.
var x = "100";
var y = "10";
[Link](x + y); // "10010"
116
В качестве первого демонстрационного примера выполним расчет
выражения, состоящего из числовых примитивов разных систем счисления.
(--x ** 0112 + 678) / 2D16 % 10002 + 3316 * 168 / ++x
где: x = 6
ПРИМЕР 2
<script>
// определение числовой переменной
let x = 6;
// составление выражения с числами разных систем счисления
let num = (--x ** 0b011 + 0o67) / 0x2D % 0b1000 + 0x33 * 0o16 / ++x;
// вывод результата
[Link](num);// 123
</script>
Объект Number
Number — это обёртка над примитивным числовым типом, которая
содержит встроенные свойства и методы, предоставляющие дополнительные
возможности работы с числами.
Например, Number позволяет использовать методы на числовых
примитивах:
проверка на специальные значения [Link]();
конвертирование в строку [Link]();
и др.
ПРИМЕР 3
<script>
var primitive = 123;
var num = new Number(123);
[Link](typeof primitive); // number
[Link](typeof num); // object
</script>
Если необходимо использовать методы на числе, то его нужно
обернуть в круглые скобки или поставить точку дважды:
// скобки
[Link]((5).toFixed(2));// 5.00
// двойная точка
[Link](5..toFixed(2));// 5.00
117
Параметр:
radix – необязательный параметр. Целое число, определяющее
основание системы счисления, используемой для представления числового
значения.
ПРИМЕР 4
<script>
// определим числовой примитив
const number = 42;
// преобразуем примитив методом toString()
[Link]([Link]()); // '42'
[Link]([Link](2)); // '101010'
[Link]([Link](8)); // '52'
[Link]([Link](16)); // '2a'
</script>
toFixed
Синтаксис:
[Link]([digits]);
Метод [Link]() форматирует число, используя запись с
фиксированной запятой.
Параметр:
digits – необязательный параметр. Количество цифр после десятичной
запятой, если аргумент опущен, он считается равным 0.
ПРИМЕР 5
<script>
// определим числовой примитив
var num = 123.456;
// преобразуем примитив методом toFixed()
[Link]([Link]()); // '123'
[Link]([Link](1)); // '123.5'
[Link]([Link](5)); // '123.45600'
[Link]((1.23e+3).toFixed(2)); // '1230.00'
[Link]([Link](2)); // '2.34'
</script>
toPrecision
Метод toPrecision() возвращает строку, представляющую объект
Number с указанной точностью.
Синтаксис:
[Link]([precision]);
Параметр:
precision – необязательный параметр. Целое число, определяющее
количество значащих цифр.
Возвращаемое значение:
118
Строка, представляющая объект Number в записи с фиксированной
запятой или в экспоненциальной записи, округлённое до precision значащих
цифр.
Если аргумент precision опущен, поведение аналогично методу
toString().
ПРИМЕР 6
<script>
// определим числовой примитив
var val = 5.123456;
// преобразуем примитив методом toPrecision()
[Link]([Link]()); // '5.123456'
[Link]([Link](5)); // '5.1235'
[Link]([Link](2)); // '5.1'
[Link]([Link](1)); // '5'
</script>
119
Если значение входного параметра string начинается с «0», за
основание системы счисления принимается либо 8, либо 10, в
зависимости от браузера.
[Link]([Link]('0011')); // 11
ПРИМЕР 7
<script>
// только эксперименты расставят все на свои места
[Link]([Link]('0011')); // 11 (10-тичное)
[Link]([Link]('0011', 2)); // 3 (2-ичное)
// 16-ричная система счисления распознается
[Link]([Link]('0x011')); // 17 (16-ричное)
// 8-, 2-ичные системы счисления не распознаются
[Link]([Link]('0o0011')); // 0
[Link]([Link]('0b0011')); // 0
// указание основания для системы счисления не поможет
[Link]([Link]('0o0011', 8)); // 0
[Link]([Link]('0b0011', 2)); // 0
// вот так можно
[Link]([Link]('0011', 8)); // 8 (8-ричное)
[Link]([Link]('0011', 2)); // 3 (2-ичное)
</script>
parseFloat
Синтаксис:
[Link](string)
Метод parseFloat() принимает строку в качестве аргумента и
возвращает десятичное число (число с плавающей точкой).
Параметр:
string – cтрока, представляющая значение, которое вы хотите
разобрать.
Возвращает число, полученное из разобранной строки или NaN, если
первый символ не удалось преобразовать в число. Пробелы игнорируются.
[Link]([Link]('12.12')); // 12.12
[Link]([Link]('12')); // 12
[Link]([Link](' 12.42')); // 12.42
[Link]([Link](' 1.15 ')); // 1.15
[Link]([Link]('pechora')); // NaN
120
Если строка начинается с чисел, а заканчивается текстовыми
символами, то парсинг прервётся на первом символе, который не удастся
конвертировать в число.
parseFloat('123.12hello'); // 123.12
Если встречается вторая точка, то остаток строки так же отбрасывается.
[Link]([Link]('12.34.567')); // 12.34
ПРИМЕР 8
<script>
// получим ссылку на элемент
let div = [Link]('div');
// прочитаем значения в переменные
let width = [Link];
let height = [Link];
// всегда анализируем, что происходит
[Link]([Link](width));
[Link]([Link](height));
// установимновыезначения
[Link] = [Link](width) + 500 + "px";
[Link] = [Link](height) + 20 + "px";
// сравниваем размеры блока до и после приращения
[Link]([Link]);
[Link]([Link]);
</script>
isFinite
Синтаксис:
[Link](testValue);
Метод isFinite() определяет, является ли переданное значение
конечным числом.
Параметр:
testValue – значение, проверяемое на конечность.
Если аргумент является NaN, положительной или отрицательной
бесконечностью, а также не является числом функция вернёт false. Иначе
возвращается true.
ПРИМЕР 9
<script>
[Link]([Link](Infinity)); // false
[Link]([Link](NaN)); // false
[Link]([Link](-Infinity)); // false
[Link]([Link](0)); // true
[Link]([Link](2e6)); // true
[Link]([Link]('0')); // false
[Link]([Link]('hello')); // false
</script>
121
isNaN
В JavaScript невозможно полагаться на «==» и «===» для определения,
является ли переменная или литерал нечисловым значением NaN или нет, так
как проверки NaN == NaN и NaN === NaN в качестве значения вернут false.
Для таких целей используется метод isNaN().
Синтаксис:
[Link](value);
Метод isNaN() определяет является ли литерал или переменная
нечисловым значением NaN или нет.
Параметр:
value – литерал или переменная которые будут проверяться на
нечисловое значение – NaN.
Метод возвращает true только для числовых значений, имеющих
значение NaN. Напомню, что значения Infinity, -Infinity и NaN являются
специальными значениями числового типа.
ПРИМЕР 10
<script>
// true
[Link]([Link](NaN));
[Link]([Link]('then' / 2));
[Link]([Link](100 / 'two'));
[Link]([Link](NaN * 5));
// можно проверить
// [Link]('then' / 2); // NaN
// [Link](NaN * 5); // NaN
// false
[Link]([Link](0));
[Link]([Link](37));
[Link]([Link]('37'));
[Link]([Link]('37.37'));
// можно проверить
// [Link](37);
// [Link]('37.37');
</script>
Преобразования чисел
Преобразование строки в число
Явно привести строку в число можно несколькими способами:
Использовать унарный оператор «+», который необходимо
расположить перед значением.
[Link](+'7.35'); // 7.35
[Link](+'string'); // NaN
// оператор пренебрегает пробелами в начале и конце строки, а также
переводом строки
[Link](+' 7.35 '); // 7.35
[Link](+'7.35 \n '); // 7.35
122
С помощью глобальной функции parseInt() или метода
[Link](). Они предназначены для преобразования значения,
переданного им на вход, в целое число. В отличие от использования унарного
оператора «+», эти методы позволяют преобразовать строку в число, в
которой не все символы являются цифровыми.
[Link](parseInt('18px')); // 18
[Link]([Link]('18.5px')); // 18
[Link](parseInt('33.3%')); // 33
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Напишите скрипт, вычисляющий результат выражений,
представленных ниже. Операнды выражений представлены в виде чисел,
записанных в различных системах счисления.
Результат каждого выражения выведите в консоль.
Выражение 1:
(2068 / 10000112 + 10002 − (−13В16 )/ 318
Выражение 2:
(20016 − 4816 )/ 508 % 1112
Выражение 3:
− − х % 1002 + 1278 − −(− − у)/ х + +,
где: х = 110002 ; у = 28516
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №14 - Задание
2» вам предложен документ с выводом геометрической фигуры
треугольник. Текстовые поля в свойстве value содержат значения для
основания и высоты треугольника.
Напишите скрипт расчета площади фигуры:
123
𝑎∗ℎ
𝑆=
2
Запишите результат в текстовое поле.
Важно. Результат расчета выводить в виде числа с точностью - два
символа после плавающей точки. Например: 56.00
Поэкспериментируйте со значениями основания и высоты фигуры
124
Практическая работа 15
ОПЕРАЦИИ JAVASCRIPT.
ОБЪЕКТ MATH
Содержание
Стань 1. Объект Math
профессионалом! 2. Свойства объекта Math
3. Методв объекта Math
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Объект Math
Объект Math является встроенным объектом, хранящим в своих
свойствах и методах различные математические константы и функции.
Объект Math не является функциональным объектом.
В отличие от других глобальных объектов, объект Math не является
конструктором. Все свойства и методы объекта Math являются
статическими, поэтому не нужно пытаться вызывать метод на созданном
экземпляре объекта Math.
ПРИМЕР 1
<script>
// --- строка (объект String) ---
// инициализация строки через создание объекта String, str - экземпляр
объекта String
let str = new String("Welcome Bun ...");
// вызов метода includes на экземпляре объекта String
[Link]([Link]("Bun")); // true
// --- число (объект Number) ---
// инициализация числа через создание объекта Number, num - экземпляр
объекта Number
let num = new Number(2.333);
// вызов метода toString на экземпляре объекта Number
[Link]([Link]()); // '2.333'
// вызов статического метода parseInt на объекте Number, без создания
экземпляра Number
[Link]([Link]()); // 2
// --- объект Math ---
// вызов статического метода sqrt на объекте Math, без создания экземпляра
Math
[Link]([Link](25)); // 5
// к статическим методам объекта необходимо обращаться без создания
экземпляра этого объекта
</script>
125
Методы объекта Math
[Link]
Метод [Link]() - округление вниз. Округляет аргумент до
ближайшего меньшего целого.
Синтаксис:
[Link](x);
Параметр:
x – число. Метод floor() является статическим методом объекта Math.
[Link]
Метод [Link]() - округление вверх. Округляет аргумент до
ближайшего большего целого.
Синтаксис:
[Link](x);
Параметр:
x – число. Метод ceil() является статическим методом объекта Mat.
ПРИМЕР 2
<script>
// инициализация переменной
let a = 11 / 3;
// вывод исходного числа
[Link]("11 / 3 = ", a);
// вывод округленных значений
[Link](".ceil() - ", [Link](a));
[Link](".floor() - ", [Link](a));
</script>
[Link]
Метод [Link]() возвращает число, округлённое к ближайшему
целому.
Синтаксис:
[Link](x);
Если дробная часть числа больше, либо равна 0,5, аргумент будет
округлён до ближайшего большего целого. Если дробная часть числа меньше
0,5, аргумент будет округлён до ближайшего меньшего целого.
Метод round() является статическим методом объекта Math.
[Link]
Функция [Link]() возвращает целую часть числа путём удаления
всех дробных знаков.
Синтаксис:
[Link](x);
126
В отличие от других трёх методов объекта Math — [Link](),
[Link]() и [Link]() — метод [Link]() работает очень просто.
Отбрасывается запятая и все цифры после неё, не обращая внимания на знак
аргумента.
Аргумент, переданный в этот метод, будет неявно преобразован в
число. Метод trunc() является статическим методом объекта Math.
ПРИМЕР 3
<script>
// инициализация переменной
a = 19 / 7;
// вывод исходного числа
[Link]("19 / 7 = ", a);
// вывод округленных значений
[Link](".ceil() - ", [Link](a));
[Link](".floor() - ", [Link](a));
[Link](".round() - ", [Link](a));
[Link](".trunc() - ", [Link](a));
</script>
[Link]
Метод [Link]() возводит число в заданную степень. Первым
параметром передается число, вторым - в какую степень его возвести.
Синтаксис:
[Link](base, exponent);
Параметры:
base – основание степени.
exponent – показатель степени, в которую возводится основание base.
Метод pow() является статическим методом объекта Math.
ПРИМЕР 4
<script>
// расчет площади круга
let r = 5;
let S = [Link] * [Link](r, 2);
// расчет дискриминанта квадратного уравнения
letb = 8;
let a = 2;
let c = 1;
let D = [Link](b,2) - 4 * a * c;
[Link]("Площадь круга: ", S);
[Link]("Дискриминант: ", D);
</script>
[Link]
Метод [Link]() возвращает квадратный корень числа.
127
Синтаксис:
[Link](x);
Метод sqrt() является статическим методом объекта Math.
Возвращаемое значение: квадратный корень заданного числа. Если
число отрицательное, то вернётся NaN.
ПРИМЕР 5
<script>
// расчет корней квадратного уравнения
// инициализация коэффициентов
let a = 1;
let b = 6;
let c = 4;
// расчет дискриминанта
let D = [Link](b,2) - 4 * a * c;
// расчет корней уравнения
let x1 = (-b + [Link](D)) / 2 * a;
let x2 = (-b - [Link](D)) / 2 * a;
// вывод расчетных значений
[Link]("Дискриминант: ", D);
[Link]("x1: ", x1);
[Link]("x2: ", x2);
</script>
[Link]
Метод [Link]() возвращает псевдослучайное число с
плавающей запятой из диапазона [0, 1), то есть, от 0 (включительно) до 1 (но
не включая 1), которое затем можно отмасштабировать до нужного
диапазона.
Синтаксис:
[Link]();
Получение случайного числа от 0 (включительно) до 1 (не
включая):
[Link]();
Получение случайного числа в заданном интервале:
[Link]() * (max - min) + min;
Возвращаемое значение не менее (и может быть равно) min и не более
(и не равно) max.
ПРИМЕР 6
<img id="happy-bear" src="[Link]" style="width:200px">
<script>
// выбираем изображение
let bear = [Link]("#happy-bear");
// ширину изображения для тестирования в консоль
// [Link] ([Link]);
// диапазон размеров для атрибута width
128
let min = 150;
let max = 600;
// получаем ширину из указанного диапазона
let width = [Link]() * (max - min) + min;
// новую ширину изображения для тестирования в консоль
[Link](width);
// устанавливаем новую ширину для изображения
[Link] = width + "px";
</script>
Получение случайного целого числа в заданном интервале
Этот пример возвращает случайное целое число в заданном интервале.
Возвращаемое значение не менее min (или следующее целое число, которое
больше min, если min не целое) и не более (но не равно) max.
min = [Link](min);
max = [Link](max);
// максимум не включается, минимум включается
[Link]([Link]() * (max - min)) + min;
Получение случайного целого числа в заданном интервале,
включительно
Если вам нужно, чтобы включалось и минимальное, и максимальное
значение, можно использовать следующее решение:
min = [Link](min);
max = [Link](max);
// максимум и минимум включаются
[Link]([Link]() * (max - min + 1)) + min;
[Link] / [Link]
Метод [Link]() возвращает наибольшее из нуля или более чисел.
Метод [Link]() возвращает наименьшее из нуля или более чисел.
Синтаксис:
[Link]([value1[, value2[, ...]]]); [Link]([value1[, value2[, ...]]]);
Методы max() / min() являются статическими методами объекта Math.
ПРИМЕР 7
<script>
// диапазон для генератора случайных чисел
let rangeMin = 0;
let rangeMax = 50;
// генерируем пять случайных чисел
let num1 = [Link]([Link]() * (rangeMax - rangeMin)) + rangeMin;
let num2 = [Link]([Link]() * (rangeMax - rangeMin)) + rangeMin;
let num3 = [Link]([Link]() * (rangeMax - rangeMin)) + rangeMin;
let num4 = [Link]([Link]() * (rangeMax - rangeMin)) + rangeMin;
let num5 = [Link]([Link]() * (rangeMax - rangeMin)) + rangeMin;
// вывод в консоль
[Link](num1, num2, num3, num4, num5);
// из диапазона чисел выбираем
// ->минимальное
129
let min = [Link](num1, num2, num3, num4, num5);
// ->максимальное
let max = [Link](num1, num2, num3, num4, num5);
// выводим найденные значения в консоль
[Link]("Min = ", min);
[Link]("Max = ", max);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №15 - Задание
1» представлен JS-массив объектов, каждый из которых представляет тизер
фильма. Подключите файл массива к файлу [Link]. Напишите скрипт
вывода случайного тизера.
Для определения интервала поиска случайного числа используйте
диалоговое окно метода prompt(). По умолчанию интервал находится в
диапазоне индексов массива data (0-9).
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №15 - Задание
2» представлен материал. Напишите скрипт, имитирующий бросок игровых
кубиков двумя игроками. Данные об игроках сохранить в объекте. В
качестве данных сохраняем имя игрока и количество набранных баллов
от броска трех кубиков.
Загрузка изображения кубика определяется случайным числом, в
диапазоне 1 – 6. Имена игроков запросить с помощью диалогового окна
метода prompt().
Результат броска вывести в соответствующие текстовые поля.
Примерный результат работы скрипта представлен на рисунке.
130
131
Практическая работа 16
ОПЕРАЦИИ JAVASCRIPT.
ОБЪЕКТ DATE
Содержание
Стань 1. Методы-аксессоры объекта Date
профессионалом! 2. Отображение даты
3. Автоматическая корретировка дат
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Объект Math
Объект Date создается при помощи конструктора new Date().
Существует четыре способа создания нового объекта даты:
1. new Date()
2. new Date(milliSecond)
3. new Date(dateString)
4. new Date(year, month[, day[, hour[, minute[, second[, milliSecond]]]]])
new Date()
Конструктор new Date() создает новый объект даты с текущими датой
и временем.
ПРИМЕР 1
<script>
// создаем специальный объект Date
var d = new Date();
// Thu Dec 15 2022 10:29:45 GMT+0300 (Москва, стандартное время)
[Link](d);
</script>
new Date(milliSecond)
Параметр:
milliSecond – целое значение, представляющее количество
миллисекунд, прошедших с 1 января 1970 00:00:00 по UTC (эпоха Unix).
ПРИМЕР 2
<script>
// метка timestamp
[Link]("Thu Jan 01 1970 00:00:00 GMT+0300 (Москва, стандартное время)");
// на вход функции Date подадим количество миллисекунд,
// прошедших с начала эпохи Unix
// 24*60*60*1000 = 1 сутки
132
var d = new Date(24*60*60*1000);
// метка timestamp + 1 сутки
[Link](d);
</script>
new Date(dateString)
Параметр:
dateString – строковое значение, представляющее дату. Строка должна
быть в одном из форматов, распознаваемых методом [Link]()
(совместимые со стандартами временные метки).
ПРИМЕР 3
<script>
// корректная строка 1
varstrDate1 = "Tue Nov 29 2022 11:52:30 GMT+0300";
// корректная строка 2
var strDate2 = "10-23-2011";
// корректная строка 3
var strDate3 = "March 08, 1997";
// корректная строка 4 ??
varstrDate4 = "Сент 10, 2021";
// вывод значения объекта Date
[Link](new Date(strDate1));
[Link](new Date(strDate2));
[Link](new Date(strDate3));
[Link](new Date(strDate4));
</script>
ПРИМЕР 4
<script>
// 2 числовых параметра определяют: -год, -месяц
var d2 = new Date(2022, 11);
[Link](d2);
// 3 числовых параметра определяют: -год, -месяц, -день
var d3 = new Date(2022, 11, 12);
[Link](d3);
// 4 числовых параметров определяют: -год, -месяц, -день, -часы
var d4 = new Date(2022, 11, 22, 10);
[Link](d4);
// 5 числовых параметров определяют: -год, -месяц, -день, -часы, -минуты
var d5 = new Date(2022, 11, 2, 10, 33);
[Link](d5);
// 6 числовых параметров определяют: -год, -месяц, -день, -часы, -минуты, -
секунды
var d6 = new Date(2022, 11, 4, 10, 33, 30);
[Link](d6);
// 7 числовых параметров определяют: -год, -месяц, -день, -часы, -минуты, -
секунды, -миллисекунды
var d7 = new Date(2022, 11, 21, 10, 33, 30, 55);
[Link](d7);
</script>
134
var d = new Date();
getMonth() получить номер месяца (0-11)
[Link]([Link]());
var d = new Date();
getDate() получить число месяца (1-31)
[Link]([Link]());
var d = new Date();
getDay() получить номер дня недели (0-6)
[Link]([Link]());
var d = new Date();
getHours() получить час (0-23)
[Link]([Link]());
var d = new Date();
getMinutes() получить минуты (0-59)
[Link]([Link]());
var d = new Date();
getSeconds() получить секунды (0-59)
[Link]([Link]());
var d = new Date();
getMilliseconds() получить миллисекунды (0-999)
[Link]([Link]());
ПРИМЕР 5
<script>
// текстовое название месяцев
var months = ["Январь", "Февраль", "Март", "Апрель", "Май", "Июнь", "Июль",
"Август", "Сентябрь", "Октябрь", "Ноябрь", "Декабрь"];
// текстовое название дней недели
var days = ["Воскресенье", "Понедельник", "Вторник", "Среда", "Четверг",
"Пятница", "Суббота"];
// получение строки текущего времени
let d = new Date();
// получение отдельных компонентов текущего времени
let time = [Link]();
let fullYear = [Link]();
let month = months[[Link]()];
let date = [Link]();
let day = days[[Link]()];
// вывод в консоль компонентов
[Link](time);
[Link](fullYear);
[Link](month);
[Link](date);
[Link](day);
// подготовка форматированной строки для вывода в браузер
let strDate = `
Микросекунд: ${time} <p>
Год: ${fullYear} <p>
Месяц: ${month} <p>
Число: ${date} <p>
День недели: ${day}
`;
// вставка в браузер строки с компонентами времени
[Link]("demo").innerHTML = strDate;
</script>
Методы сеттеры
Помимо получения данных в объекте Date также есть методы,
которые позволяют изменить значения даты и времени (год, месяц, день,
час, минуты, секунды, миллисекунды).
135
Метод Описание Пример
ПРИМЕР 6
<script>
// новый объект Date с текущими датой и временем
vard = new Date();
// текущий объект Date, но 22 часа
[Link](22);
[Link](d);
// текущий объект Date, но 30 минут
[Link](30);
[Link](d);
// текущий объект Date, но 45 секунд
[Link](45);
[Link](d);
</script>
Отображение даты
По умолчанию, JavaScript будет отображать дату в формате полной
текстовой строки: Wed Mar 25 2015 03:00:00 GMT+0300. Когда вы выводите
136
объект даты в HTML, он автоматически преобразуется в строку при помощи
метода toString().
Метод toUTCString() преобразует дату в строку UTC (стандарт
отображения даты).
Метод toDateString() преобразует дату в более читабельный формат.
ПРИМЕР 7
<script>
// создание объекта текущей даты
d = new Date();
// формируем строку для вывода
let date = `
Текущая дата<b>new Date()</b>: ${d} </d><p>
Метод<b>toString()</b>: ${[Link]()} <p>
Метод<b>toUTCString()</b>: ${[Link]()} <p>
Метод<b>toDateString()</b>: ${[Link]()} <p>
`;
// вывод строки в браузер
[Link](date);
</script>
ПРИМЕР 8
<script>
// ММ/ДД/ГГГГ
var d = new Date("12/25/2021"); // текущая дата
[Link](d);
// ДД/ММ/ГГГГ
var d = new Date("25/12/2021"); // NaN
[Link](d);
// ГГГГ/ММ/ДД
var d = new Date("2021/12/25"); // текущая дата
[Link](d);
</script>
ПРИМЕР 9
<script>
var d1 = new Date("January 25 2015");
var d2 = new Date("Jan 25 2015");
// запятые игнорируются
// имена регистронезависимы
var d3 = new Date("JANUARY, 25, 2015");
// так не работает
137
var d4 = new Date("Январь, 25, 2015");
[Link](d1);
[Link](d2);
[Link](d3);
[Link](d4);
</script>
Парсинг даты
Корректно составленную строку даты можно при помощи метода
[Link]() преобразовать в миллисекунды. Метод [Link]() возвращает
количество миллисекунд, прошедших с 1 января 1970 до заданной даты.
ПРИМЕР 10
<script>
// парсим корректную строку времени в миллисекунды
var msec = [Link]("March 12 2021");
[Link](msec);
// миллисекунды преобразуем в дату
[Link](d = new Date(msec));
// дату преобразуем в миллисекунды
[Link]([Link]());
</script>
ПРИМЕР 11
<script>
// первая метка времени
var a = new Date(2023, 0);
// вторая метка времени
var b = new Date(2022, 0);
// вычисляем разность в миллисекундах
var dif = [Link]() - [Link]();
[Link]("Расчетное время в миллисекундах: ", dif);
// разность меток можно вычислить и так
// var dif = a - b;
// [Link](dif);
// всего дней
[Link]("Всего дней: ", dif / (1000 * 60 * 60 * 24));
// всего часов
[Link]("Всего часов: ", dif / (1000 * 60 * 60));
// всего минут
[Link]("Всего минут: ", dif / (1000 * 60));
// всего секунд
[Link]("Всего секунд: ", dif / (1000));
</script>
138
Автоматическая корректировка дат
JavaScript имеет очень интересную и полезную особенность: если при
создании объекта Date был указан некорректный момент времени - он
автоматически будет пересчитан в корректный.
ПРИМЕР 12
<script>
// зададим дату - 32 мая
let date = new Date(2018, 4, 32);
// браузер исправил на первое июня
// Fri Jun 01 2018 00:00:00 GMT+0300 (Москва, стандартное время)
[Link](date);
</script>
JavaScript просто прибавил лишний день к следующему месяцу.
Можно указывать не только лишние дни, но и месяцы. При этом
следует помнить, что месяцы начинаются с нуля, а значит последний
корректный месяц - 11-тый. Если указать 12-тый месяц, то получится январь
следующего года.
Минимальный месяц имеет номер 0. Это значит, что минус первый
день попадает во 2 день с конца предыдущего месяца, а минус первый месяц
попадает просто в последний месяц предыдущего года.
ПРИМЕР 13
<script>
// определим дату с отрицательным числом
var dat = new Date(2022, 12, -5);
// браузер додумывает за пользователя,
// что тот имел в виду
// часто успешно
[Link](dat);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Напишите скрипт, который при загрузке HTML-страницы, выводит в
браузер текущий день недели, число, месяц и год. Для вывода дня недели
предусмотреть текстовый массив.
Примерный формат вывода:
Сегодня: 14-12-2023 (Четверг)
ЗАДАНИЕ 2
Напишите скрипт, который при загрузке HTML-страницы
запрашивает дату вашего рождения и выводит на страницу день недели,
число, месяц и год этой даты.
139
Для вывода месяца и дня недели организовать текстовые массивы.
ЗАДАНИЕ 3
Напишите скрипт, подсчитывающий, сколько дней осталось до
ближайшего Нового года. Выведите расчетное значение в предназначенный
блок HTML-страницы.
140
Практическая работа 17
Содержание
Стань 1. Структура формата JSON
профессионалом! 2. Объект JSON
3. Вложенность в строках JSON
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
JSON (JavaScript Object Notation, объектная нотация JavaScript) — это
стандартный текстовый формат для представления структурированных
данных на основе синтаксиса объектов JavaScript. По сути, формат JSON
представляет собою обычную строку.
JSON существует в виде строки — это удобно, когда вы хотите
передавать данные по сети. Обычно используется для обмена данными в
веб-приложениях. Обмен заключается в отправке некоторых данных с
сервера клиенту, чтобы их можно было отобразить на веб-странице, и
наоборот, от клиента на сервер, для обеспечения обратной связи между
клиентом и приложением.
При помощи простых правил формирования JSON-конструкций,
разработчик может обеспечить простой и надежный способ хранения
любого вида информации, будь то обычное число, целые строки или
огромное количество различных объектов, выраженных в простом тексте.
Строка JSON может храниться в собственном файле, который в
основном представляет собой просто текстовый файл с расширением .json.
Где используется JSON
После того как файл создан, содержащиеся в нем JSON-данные
довольно легко перенаправить в другое приложение сети через любые пути
передачи данных. Это связано с тем, что JSON-строка представляет собой
обычный текст.
Как выглядит этот процесс? Его можно представить в виде двух шагов:
На первом шаге, сервер, по запросу, пришедшему ему от клиента,
формирует некоторый набор данных, который затем упаковывает в строку
формата JSON. Завершается работа на сервере отправкой JSON данных в
качестве результата клиенту.
На втором шаге, клиент получает в качестве ответа от сервера
строку JSON и распаковывает её, т.е. переводит в JavaScript объект.
141
После этого на клиенте выполняются дальнейшие с ними действия,
например, выводятся на страницу.
Структура формата JSON
Типы данных JSON
В JSON типы данных можно разделить на две категории: простые и
сложные.
К категории простых типов (примитивов) относятся:
string – строки;
number – числа;
boolean – логические (булевы) значения;
null.
К сложным типам относятся:
object – объекты;
array – массивы.
Синтаксис JSON заимствован из JavaScript, поэтому для представления
значений простых и сложных типов используется тот же синтаксис, что и в
JavaScript.
Простые значения
Простейший пример JSON-кода – любое значение простого типа.
Обратите внимание на определение строк. Строки должны быть только в
двойных кавычках.
ПРИМЕР 1
<script>
// определение в JS
var num = 25;
var str = "string";
var bool = true;
var nul = null;
// определение в JSON
var numJSON = 25;
var strJSON = "\"string\"";
var boolJSON = true;
var nullJSON = null;
</script>
Объекты
Структура объекта JSON практически ничем не отличается от записи
JS объекта.
Объект JSON представляет собой заключённый в фигурные скобки
список из нуля или более пар «ключ»: значение. В этой паре ключ
отделяется от значения с помощью знака двоеточия (:), а одна пара от
другой - с помощью запятой (,).
142
Имена ключей (свойств объектов) обязательно должны быть
заключены в двойные кавычки.
Это важное отличие JSON от JS объекта. В JS объекте ключ (имя
свойства) заключать в двойные кавычки не обязательно.
Свойства объекта могут содержать значения любого типа (простого
или сложного). Это позволяет разработчику строить иерархию данных.
ПРИМЕР 2
<script>
// определение JS-объекта
let personJS = {
surname : "Бородина",
name : "Ксения",
patronymic : "Алексеевна",
post : "Преподаватель"
};
// определение JSON-объекта
// для записи в несколько строк используем обратные кавычки
let personJSON = `
{
"surname": "Бородина",
"name": "Ксения",
"patronymic": "Алексеевна",
"post": "Преподаватель"
}`;
</script>
Массивы
Массив JSON представляет собой заключённый в квадратные скобки
список из нуля или более значений, разделённых запятыми. Массив может
содержать значения любого типа (простого или сложного).
ПРИМЕР 3
<script>
// определение JS-массива
let coursesJS = [
"Профессия веб-разработчик",
"Fullstack разработчик на Python",
"Серверное программирование на PHP"
];
// определение JSON-массива
// для записи в несколько строк используем обратные кавычки
let coursesJSON = `[
"Профессия веб-разработчик",
"Fullstack разработчик на Python",
"Серверное программирование на PHP"
]`;
</script>
143
Иерархия данных в формате JSON
Пример более сложного JSON формата, хранящего в качестве значения
ключа другие сложные типы данных (объект и массив) приведен ниже.
ПРИМЕР 4
<script>
// определение сложного JS-объекта
let personJS = {
surname : "Бородина",
name : "Ксения",
patronymic : "Алексеевна",
post : "Преподаватель",
category : "Соответствие занимаемой должности",
experience : {"total" : 21.3, "college" : 14.5},
courses : ["Профессия веб-разработчик", "Fullstack разработчик на Python"]
};
// определение сложного формата JSON-строки
let personJSON = `{
"surname" : "Бородина",
"name" : "Ксения",
"patronymic" : "Алексеевна",
"post" : "Преподаватель",
"category" : "Соответствие занимаемой должности",
"experience" : {"total" : 21.3, "college" : 14.5},
"courses" : ["Профессия веб-разработчик", "Fullstack разработчик на Python"]
}`;
</script>
Каждый из типов данных, которые передаются в JSON как значения,
будут поддерживать свой собственный синтаксис. При этом:
вложенные объекты берутся в фигурные скобки;
массивы берутся в прямоугольные скобки.
Пример JSON строки, с которыми, скорее всего, вы будете иметь дело
в реальных приложениях представлен в следующем примере.
ПРИМЕР 5
<script>
// определение сложного формата JSON-строки
let personJSON = `{
"surname" : "Бородина",
"name" : "Ксения",
"patronymic" : "Алексеевна",
"post" : "Преподаватель",
"category" : "Соответствие занимаемой должности",
"experience" : {"total" : 21.3, "college" : 14.5},
"courses" : ["Профессия веб-разработчик", "Fullstack разработчик на Python"],
"education" : [
{
"institution" : "Санкт-Петербургский государственный университет
(СПбГУ)",
"qualification" : "Информационные системы и технологии",
144
"specialty" : "Безопасность киберфизических систем",
"year_receipts" : 1993,
"year_release" : 1998
},
{
"institution" : "Московский государственный университет имени
М.В.Ломоносова",
"qualification" : "Факультет вычислительной математики и кибернетики",
"specialty" : "Прикладная математика и информатика",
"year_receipts" : 1990,
"year_release" : 2001
}
]
}`;
// вывод строки в браузер
[Link](personJSON);
</script>
Объект JSON
Для работы с форматом JSON в JavaScript есть глобальный объект
JSON. У объекта JSON есть два метода: stringify() и parse(). Кроме этих двух
методов он не содержит больше никакой дополнительной
функциональности:
[Link] для преобразования JS-объектов в JSON.
[Link] для преобразования JSON обратно в JS-объект.
Метод [Link]()
Функция [Link]() преобразует объект JS в строку JSON.
Синтаксис:
let json = [Link](value, [replacer, space]);
Параметры:
value – значение для кодирования.
replacer – массив свойств для кодирования или функция соответствия,
которая будет вызываться для каждой пары key, value.
space – дополнительное пространство (отступы), используемое для
форматирования.
В большинстве случаев [Link] используется только с
первым аргументом. Но если нужно настроить процесс преобразования, то
можно использовать второй аргумент [Link].
ПРИМЕР 6
<script>
// -- пользователь выбрал товар на сайте одежды
// заказ сформирован в виде JS-объекта
// в объекте допускаются строки в одинарных кавычках
let order = {
id : 1,
title : 'Утепленная стеганая куртка',
145
brand : 'MARCO DI RADI',
colour : 'Синий',
country : 'Китай',
hood : 'Есть',
size : 52,
price : 25.590,
image : '[Link]'
};
// преобразуем объект в JSON
let orderJSON = [Link](order);
// вывод в консоль объекта заказа
[Link](order);
// вывод в консоль заказа в виде строки JSON
[Link](orderJSON);
// заказ упакован в JSON, можно отправлять для обработки на сервер
// дальнейшие действия зависят от логики работы приложения
</script>
Полученная строка JSON называется JSON-форматированным или
сериализованным объектом. Строки имеют малый вес и поэтому очень
полезны при обмене данными между клиентом и сервером или для
размещения в хранилище данных.
Обратите внимание, что объект в формате JSON имеет несколько
важных отличий от объектного литерала JS:
Строки используют двойные кавычки. Никаких одинарных кавычек
или обратных кавычек в JSON. Так 'Утепленная стеганая куртка' становится
"Утепленная стеганая куртка".
Имена свойств объекта также заключаются в двойные кавычки. Это
обязательно. Так size:52 становится "size":52.
Конечные запятые запрещены.
Ведущие нули запрещены, перед десятичной запятой обязательно
должна быть хотя бы одна цифра.
[Link] поддерживает все типы данных JSON.
ПРИМЕР 7
<script>
// число в JSON остаётся числом
[Link] ([Link](25)); // 25
// строка в JSON по-прежнему остаётся строкой, но в двойных кавычках
[Link] ([Link]('test')) // "test"
[Link] ([Link](true)); // true
[Link] ([Link](null)); // null
[Link] ([Link]([1, 2, 3])); // [1,2,3]
[Link] ([Link]({a:1, b:'2', c:'три'})); // {"a":1,"b":"2","c":"три"}
</script>
JSON является независимой от языка спецификацией для данных,
поэтому [Link] не обрабатывает некоторые специфические свойства
объектов JavaScript.
А именно:
146
свойства-функции (методы);
свойства, содержащие undefined;
символьные ключи и значения.
ПРИМЕР 8
<script>
// определение JS-объекта
let person = {
surname : "Бородина",
name : "Ксения",
post : "Преподаватель",
note : undefined,
fnMsg () {return "Добрый день, " + [Link]}
};
// сериализуем объект
[Link]([Link](person));
</script>
Метод [Link]()
Чтобы декодировать JSON-строку нужен метод [Link](). Метод
преобразует строку JSON в соответствующее значение JavaScript.
Особенности преобразования:
Если во время преобразования в строке JSON встретится значение
undefined, то оно будет опущено (не будет включено в результат).
Синтаксис:
let value = [Link](str, [reviver]);
Параметры:
str - JSON для преобразования в объект;
reviver - необязательная функция, которая будет вызываться для
каждой пары (ключ, значение) и может преобразовывать значение.
ПРИМЕР 9
<script>
// -- пользователь запросил информацию о товаре на сайте одежды
// информация о товаре поступила в виде строки JSON
let orderJSON = '{ "id" : 1, "title" : "Утепленная стеганая куртка", "brand" : "MARCO
DI RADI", "colour" : "Синий", "country" : "Китай", "hood" : "Есть", "size" : "52", "price" :
25.590, "image" : "[Link]" }';
// вывод в консоль
[Link](orderJSON);
// для доступа к данным преобразуем JSON в JS-объект
let order = [Link](orderJSON);
// вывод в консоль звказа в виде JS-объекта
[Link](order);
// тестируем доступ
[Link]([Link]);
</script>
147
Вложенность в строках JSON
Методы объекта JSON позволяют конвертировать сложные структуры.
JSON может быть настолько сложным, насколько это необходимо, объекты
и массивы могут включать другие объекты и массивы. Но они должны
быть в том же JSON-формате.
ПРИМЕР 10
<script>
// -- пользователь выбрал два товара на сайте одежды
// заказ сформирован в виде JS-массива
let order = [
{
id : 1,
title : "Утепленная стеганая куртка",
brand : "MARCO DI RADI",
colour : "Синий",
country : "Китай",
hood : "Есть",
size : 52,
price : 25.590,
image : "[Link]"
},
{
id : 2,
title : "Пальто",
brand : "Allsaints",
colour : "Коричневый",
country : "Китай",
hood : "Отсутствует",
size : 50,
price : 53.990,
image : "[Link]"
}
];
// преобразуем JS-массив в JSON
let orderJSON = [Link](order);
// вывод в консоль массива заказа
[Link](order);
// вывод в консоль заказа в виде JSON
[Link](orderJSON);
// заказ упакован в JSON, можно отправлять для обработки на сервер
// дальнейшие действия зависят от логики работы приложения
</script>
Парсинг строки JSON в массив JS.
ПРИМЕР 11
<script>
// -- пользователь запросил информацию о двух товарах на сайте одежды
// информация о товаре поступила в виде JSON-массива
let orderJSON = `[
{
"id" : 1,
148
"title" : "Утепленная стеганая куртка",
"brand" : "MARCO DI RADI",
"colour" : "Синий",
"country" : "Китай",
"hood" : "Есть",
"size" : 52,
"price" : 25.590,
"image" : "[Link]"
},
{
"id" : 2,
"title" : "Пальто",
"brand" : "Allsaints",
"colour" : "Коричневый",
"country" : "Китай",
"hood" : "Отсутствует",
"size" : 50,
"price" : 53.990,
"image" : "[Link]"
}
]`;
// вывод в консоль
[Link](orderJSON);
// для доступа к данным преобразуем JSON в JS-массив
let order = [Link](orderJSON);
// вывод в консоль звказа в виде JS-массива
[Link](order);
// тестируем доступ
[Link](order[0].title);
[Link](order[1].title);
</script>
Так, если на сайте возможно заказать телевизор, свитер худи и
спортивную добавку, то формат JSON может состоять из объекта,
содержащего три ключа (например: tv, hoody, sportpit), значением которых
будут массивы, описывающие однотипные товары. И даже если каждый из
товаров заказан в единственном экземпляре, хранить его удобно в массиве.
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В файле [Link] (в папке «Раздаточный материал - Практическая
работа №17 - Задание 1») вам предложена строка формата JSON. Вручную
преобразуйте JSON строку в JavaScript объект. Выведите данные объекта в
браузер.
Примерный формат вывода представлен на рисунке.
149
ЗАДАНИЕ 2
В файле [Link] (в папке «Раздаточный материал - Практическая работа
№17 - Задание 2») вам представлены массивы.
Создайте строку JSON формата. Строка должна содержать объект с
тремя ключами (свойствами):
toyota;
mitsubishi;
bmw.
Значениями каждого ключа являются массивы, содержащие объекты,
описывающие представленные автомобили.
Используя метод [Link] преобразуйте строку в JS-объект. Если
строка JSON собрана правильно, преобразование в объект пройдет без
ошибок. Выведите автомобили марки Toyota в браузер.
150
Практическая работа 18
Содержание
Стань 1. Создание объекта регулярного
выражения
профессионалом! 2. Методы регулярных выражений
3. Методы объекта String
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Регулярные выражения, обычно известные как regex или RegExp —
это способ описания шаблонов в строковых данных.
Регулярные выражения, например, можно использовать для проверки
правильности формата данных, введенных пользователем:
имени;
пароля;
адреса электронной почты;
номера телефона;
поиска или замены соответствующей строки в текстовом содержимом;
и т. д.
В JavaScript регулярные выражения также являются объектами.
Создание объекта регулярного выражения
Регулярное выражение JavaScript (или RegExp) — это
последовательность символов, которую мы можем использовать для
эффективной работы со строками. Используя этот синтаксис, мы можем:
искать текст в строке;
заменить подстроки в строке;
извлекать информацию из строки.
В JavaScript регулярное выражение это объект (RegExp), который
может быть определён двумя способами.
Литеральным синтаксисом.
Конструктором объекта регулярного выражения.
Литеральный синтаксис регулярного выражения
Синтаксис литерала использует косую черту /pattern/ для
обертывания шаблона (паттерна) регулярного выражения.
Синтаксис:
let reg = /pattern/;
151
ПРИМЕР 1
<script>
// определение строки для поиска
let str = "Языки PHP и JavaScript монстры Fullstack разработки";
// синтаксис литерала при определении шаблона поиска
let reg = /JavaScript/;
// вывод результата поиска
// позиция вхождения шаблона в строку
[Link]([Link](reg));
</script>
ПРИМЕР 2
<script>
// определение строки поиска
// строка содержит непечатные символы перевода строки и табуляции
let str = `
Изучаем frontend на JavaScript и
немножко backend на PHP
`;
// синтаксис конструктора при определении шаблона поиска
let reg = new RegExp("PHP");
// вывод результата поиска
// позиция вхождения шаблона в строку
[Link]([Link](reg));
</script>
152
Синтаксис литерала: let reg = /pattern/flags;
Синтаксис конструктора: var rexp = new RegExp('pattern', 'flags');
ПРИМЕР 3
<script>
// определение строки поиска
let str = 'Frontend разработка на JavaScript с нуля до гуру';
// шаблона поиска
let reg1 = new RegExp("javascript");
// вывод результата поиска
// вхождение не найдено
[Link]([Link](reg1)); // -1
// шаблона поиска с флагом
let reg2 = new RegExp("javascript", "i");
// вывод результата поиска c учетом флага -i
// вхождение найдено в позиции 23
[Link]([Link](reg2)); // 23
</script>
153
При успехе метод возвращает индекс первого сопоставления с
регулярным выражением внутри строки. В противном случае метод вернёт -
1.
ПРИМЕР 4
Метод search() с неявным преобразование аргумента в RegExp:
<h2>Человек человеку волк (Плавт) (лат.: Homo homĭni lupus est. [Гхо́
мо гхо́
мини
лю́
пус эст])</h2>
<script>
// строка в которой будем искать совпадение с шаблоном
str = [Link]("h2").innerText;
// передаем не объект RegExp, а обычную строку - Homo
// строка будет неявно преобразована автоматически
// поиск
let pos = [Link]("Homo");
// вывод позиции вхождения
[Link](pos); // 37
</script>
ПРИМЕР 5
Метод search() с аргументом типа RegExp:
<pre> <script>
<h3> // строка в которой будем искать совпадение с
Ослу образованье дали. шаблоном
Он стал умней? Едва ли. let str =
Но раньше, как осел, [Link]("pre").textContent;
Он просто чушь порол, // полученная строка
А нынче – ах злодей – [Link](str);
Он, с важностью педанта, // шаблон поиска в литеральной нотации
При каждой глупости своей let reg = /Кант/;
Ссылается на Канта. // поиск вхождения
(Саша Черный) let pos = [Link](reg);
</h3> // вывод позиции вхождения
</pre> [Link](pos); // 213
</script>
match
Метод match() возвращает получившиеся совпадения при
сопоставлении строки str с регулярным выражением regexp.
Синтаксис:
[Link](regexp);
Параметр:
regexp - объект регулярного выражения. Если будет передан объект
obj, не являющийся регулярным выражением, он будет неявно
преобразован в объект RegExp через вызов конструктора new RegExp (obj).
Возвращаемое значение: объект Array, содержащий результаты
сопоставления, или null, если ничего не было сопоставлено.
154
ПРИМЕР 6
<pre> <script>
<h2>Владимир Маяковский — // строка в которой будем искать
Левый марш</h2> совпадение с шаблоном
<h3> let str =
Глаз ли померкнет орлий? [Link]("pre").innerText;
В старое станем ли пялиться? // шаблон в конструкторе
Крепи let reg = new RegExp("левой", "i");
у мира на горле // поиск вхождения
пролетариата пальцы! let info = [Link](reg);
Грудью вперед бравой! // вывод информации о результате поиска
Флагами небо оклеивай! // возвращается массив, но JS
Кто там шагает правой? идентифицирует его как объект
Левой! [Link](typeof info); // object
Левой! [Link](info);
Левой! [Link]("----------");
</h3> [Link](info[0]);
</pre> [Link](info['index']);
[Link](info['input']);
</script>
ПРИМЕР 7
Метод match() с флагом g:
<pre> <script>
<h2>Yellow Submarine (The // строка в которой будем искать
Beatles)</h2> совпадение с шаблоном
<h3> let str =
We all live in a yellow submarine [Link]("h3")[0].inner
Yellow submarine, yellow Text;
submarine // шаблон в литеральной нотации
We all live in a yellow submarine // let reg = /submarine/;
Yellow submarine, yellow // флаг -g позволяет найти все совпадения
submarine let reg = /submarine/g;
</h3> // поиск вхождений
</pre> let arr = [Link](reg);
// вывод массива совпадений
[Link](arr);
</script>
matchAll
Метод matchAll() возвращает итератор по всем результатам при
сопоставлении строки str с регулярным выражением regexp.
Синтаксис:
[Link](regexp);
Параметр:
regexp – объект регулярного выражения. Если передано значение, не
являющееся объектом регулярного выражения, оно неявно преобразуется в
RegExp используя new RegExp(obj).
155
Возвращается iterator. Итератор можно использовать с циклическими
конструкциями for...of, [Link]() и т.д.
ПРИМЕР 8
<pre> <script>
<h2>Ночь, улица, фонарь, // строка в которой будем искать
аптека... (А.А. Блок)</h2> совпадение с шаблоном
<h3> let text =
Ночь, улица, фонарь, аптека, [Link]("pre").innerText;
Бессмысленный и тусклый // глобальный шаблон поиска
свет. let reg = new RegExp("аптека", "ig");
Живи еще хоть четверть века - // возвращает специальный итератор
Все будет так. Исхода нет. let arr = [Link](reg);
Умрешь - начнешь опять // с помощью цикла выводим
сначала возвращаемый объект
И повторится все, как встарь: for (el of arr) {
Ночь, ледяная рябь канала, // протестируйте вывод, там много
Аптека, улица, фонарь. интересного
</h3> // [Link](el);
</pre> // в консоль
[Link](el[0]);
// в браузер
[Link](el[0], "<br/>");
}
// RegExpStringIterator
[Link](arr);
</script>
split
Метод split() разбивает строку str на массив строк путём разделения
строки указанной подстрокой separator.
Синтаксис:
[Link]([separator[, limit]]);
Параметр:
separator – необязательный параметр. Указывает символы,
используемые в качестве разделителя внутри строки. Параметр separator
может быть как строкой, так и регулярным выражением.
Если разделитель separator найден, он удаляется из строки, а
подстроки возвращаются в массиве.
Если параметр опущен, возвращёный массив будет содержать один
элемент со всей строкой.
Если параметр равен пустой строке, строка str будет преобразована в
массив символов.
limit – необязательный параметр. Целое число, определяющее
ограничение на количество найденных подстрок. Метод split() всё равно
разделяет строку на каждом сопоставлении с разделителем separator, но
обрезает возвращаемый массив так, чтобы он содержал не более limit
элементов.
156
Возвращаемое значение: возвращается новый массив.
ПРИМЕР 9
<h2>Изучаем Веб- <script>
технологии</h2> // строка в которой будем искать совпадение с
<ul> шаблоном
<li>Python</li> let str = [Link]("ul").innerText;
<li>OpenServer</li> // вывод строки в консоль
<li>Figma</li> [Link](str);
<li>JavaScript</li> // шаблон для разделения
<li>MySQL</li> let reg = new RegExp("\n");
</ul> // разбиваем строку по шаблону в массив
let arr = [Link](reg);
// вывод массива
[Link](arr); // Array
// тестируем доступ к массиву
[Link](arr[3]);
</script>
В следующем примере рассмотрим строки формата CSV. Формат
может использоваться при асинхронном взаимодействии клиент-сервер. На
протяжении всего курса JSON и CSV будут встречаться многократно.
ПРИМЕР 10
<script>
// строка в которой будем искать совпадение с шаблоном
let text =
`1;'Aerosmith';'aerosmith';'США';'1970';'хард-рок';'assets/teams/[Link]'
2;'Pink Floyd';'pink-floyd';'Великобритания';'1965';'психоделический-
рок';'assets/teams/[Link]'
3;'The Beatles';'the-beatles';'Великобритания';'1960';'рок-н-
ролл';'assets/teams/[Link]'
4;'AC/DC';'ac-dc';'Австралия';'1973';'хард-блюз-рок';'assets/teams/[Link]'
5;'Scorpions';'scorpions';'ФРГ';'1965';'хард-рок';'assets/teams/scorpions_.jpg'
6;'Ленинград';'ленинград';'Россия';'1997';'ска, фолк,
панк';'assets/teams/[Link]'`;
// шаблон, разбивающий текст в массив построчно
let reg = new RegExp("\n");
// разбиваем строку по шаблону в массив
let arr = [Link](reg);
// вывод массива
[Link](arr);
// вывод третьего элемента массива
[Link](arr[2]);
</script>
replace
Метод replace() возвращает новую строку с некоторыми или всеми
сопоставлениями шаблона, заменёнными на заменитель.
Синтаксис:
[Link](substr|regexp, newSubStr|function);
157
Шаблон может быть:
строкой;
регулярным выражением.
Заменитель может быть:
строкой;
функцией, вызываемой при каждом сопоставлении.
Параметры:
substr – строка, заменяемая на newSubStr. Обратите внимание, будет
заменено только первое вхождение искомой строки.
regexp – объект регулярного выражения RegExp. Сопоставление
заменяется возвращаемым значением второго параметра.
newSubStr – строка, заменяющая подстроку из первого параметра.
function – функция, вызываемая для создания новой подстроки.
Возвращаемое значение: новая строка с некоторыми или всеми
сопоставлениями шаблона, заменёнными на заменитель.
ПРИМЕР 11
<h2>Было</h2> <script>
<h3>Изучаем Веб- // строка в которой будем искать совпадение с
технологии </h3> шаблоном
<p>#Python #OpenServer let tags = [Link]("p").innerText;
#Figma #JavaScript // шаблон поиска всех вхождений символа - "#"
#MySQL</p> let reg = new RegExp("#", "g");
// замена всех "#" на "<li>"
<h2>Стало</h2> let list = [Link](reg, "<li>");
<div></div> // формируем строку представляющую список
list = `
<h3>Изучаем Веб-технологии с pechora-PRO</h3>
<ul>${list}</ul>
`;
// вывод списка в документ
[Link]("div").innerHTML = list;
</script>
test
Метод test() выполняет поиск сопоставления регулярного выражения
reg указанной строке str.
158
Синтаксис:
[Link](str);
Параметр:
str – cтрока, с которой сопоставляется регулярное выражение.
Возвращает логическое значение: true или false.
ПРИМЕР 12
<script> country : "Китай",
// массив заказа hood : "Отсутствует",
let order = [ size : "50",
{ price : 53.990,
id : 1, image : "images/palto-
title : "Утепленная стеганая [Link]"
куртка", },
brand : "MARCO DI RADI", ];
colour : "Синий", // преобразуем массив заказов в
country : "Китай", строку
hood : "Есть", let orderJSON = [Link](order);
size : 52, // вывод в консоль строки
price : 25.590, // [Link](orderJSON);
image : "images/steganaya- // создание RegExp
[Link]" let reg = new RegExp("Парка", "g");
}, // поиск в заказе товара - Парка
{ let res = [Link](orderJSON);
id : 2, // вывод результата поиска
title : "Пальто", [Link](res);
brand : "Allsaints", </script>
colour : "Коричневый",
exec
Метод exec() ищет совпадение регулярного выражения reg в строке str.
Синтаксис:
[Link](str);
Параметр:
str – строка, с которой производится сопоставление регулярного
выражения.
Если сопоставление успешно выполнилось, метод exec() возвращает
массив. Возвращаемый массив в первом элементе содержит
сопоставленный текст, а в последующих элементах — текст, захваченный
при сопоставлении круглыми скобками (рассмотрим в следующем уроке).
Если сопоставление не удалось, метод exec() возвращает null.
ПРИМЕР 13
<pre> <script>
<h2>Путь (А. Белый)</h2> // строка в которой будем искать
<h3> совпадение с шаблоном
Чтоб бранью сухой не let text = [Link]("pre
159
встречали, h3").innerText;
Жилье огибаю, как трус, – // шаблон поиска
И дале – и дале – и дале – let reg = new RegExp("дале", "i");
Вдоль пыльной дороги // возвращаемый массив
влекусь. let arr1 = [Link](text);
</h3> // вывод массива arr1
</pre> [Link](arr1);
// сравним поиск методом -match
arr2 = [Link](reg);
// вывод массива arr2
[Link](arr2);
// массивы одинаковы
</script>
Метод exec() ведёт себя по-разному в зависимости от того, имеет ли
регулярное выражение флаг g.
Если флага нет, то exec() возвращает первое совпадение в точности как
match().
Если флаг есть, то:
Вызов exec() возвращает первое совпадение и запоминает позицию
после него в свойстве lastIndex.
Следующий вызов начинает поиск с позиции lastIndex, возвращает
следующее совпадение и запоминает позицию после него в lastIndex.
…И так далее.
Если совпадений больше нет, то exec возвращает null, а для lastIndex
устанавливается значение 0.
Таким образом, повторные вызовы возвращают одно за другим все
совпадения, используя свойство lastIndex для отслеживания текущей
позиции поиска.
ПРИМЕР 14
<pre> <script>
<h2>Путь (А. Белый)</h2> // строка в которой будем искать совпадение с
<h3> шаблоном
Чтоб бранью сухой не let text = [Link]("pre
встречали, h3").innerText;
Жилье огибаю, как трус, – // шаблон поиска, используем флаг -g
И дале – и дале – и дале – let reg = new RegExp("дале", "ig");
Вдоль пыльной дороги // 1-ый поиск
влекусь. let arr = [Link](text);
</h3> [Link]("\n\n1-ый поиск");
</pre> [Link](arr);
[Link]("Сопоставление найдено в позиции ",
arr["index"]);
[Link]("Следующий поиск с позиции ",
[Link]);
// 2-ой поиск
arr = [Link](text);
[Link]("\n\n2-ой поиск");
[Link](arr);
160
[Link]("Сопоставление найдено в позиции ",
arr["index"]);
[Link]("Следующий поиск с позиции ",
[Link]);
// 3-ий поиск
arr = [Link](text);
[Link]("\n\n3-ий поиск");
[Link](arr); // null
[Link]("Сопоставление найдено в позиции ",
arr["index"]); // ошибка
[Link]("Следующий поиск с позиции ",
[Link]);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В файле [Link] (в папке «Раздаточный материал - Практическая
работа №18 - Задание 1») содержится информация о темпераментах.
Информация структурирована в виде массива объектов, сохраненного в
формате JSON.
Подключите файл темпераментов к файлу скрипта [Link].
Напишите скрипт, используя возможности регулярных выражений
выполните следующие действия:
замените строковые обозначения изображений на изображения из
директории pict;
распарсите JSON формат в JS объект;
выведите полученный контент в браузер.
161
Практическая работа 19
Содержание
Стань 1. Метасимволы поиска совпадений
2. Захват переменных
профессионалом! 3. Количественные метасимволы
4. Метасимволы позиционирования
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Метасимволы задают тип символов искомой строки, способ
окружения искомой строки в тексте, а также количество символов
отдельного типа в просматриваемом тексте.
Метасимволы — это символы, которые интерпретируются особым
образом механизмом RegEx. Вот список метасимволов:
. | []() \ * + ? {} ^ $
Метасимволы можно разделить на три группы:
Метасимволы поиска совпадений.
Количественные метасимволы.
Метасимволы позиционирования.
Метасимволы поиска совпадений
Метасимволы, определяющие совпадения, начнем с самого
универсального. Точка «.» соответствует любому одиночному символу
(кроме новой строки '\n').
Шаблон Строка Количество совпадений
a [Link]("a".match(/../g)); // null
.. ab [Link]("ab".match(/../g)); // 1
abc [Link]("abc".match(/../g)); // 1
abcd [Link]("abcd".match(/../g)); // 2
162
Шаблон Строка Количество совпадений
abcde [Link]("abcde".match(/a|b/g)); // 2
cde [Link]("cde".match(/a|b/g)); // null
a|b
acde [Link]("acde".match(/a|b/g)); // 1
abcdea [Link]("abcdea".match(/a|b/g)); // 3
163
ПРИМЕР 1
<h2>Чeм бeзупрeчнee чeловeк снаружи, тeм большe дeмонов у нeго внутри
(З.Фрeйд)</h2>
<script>
// строка в которой будем искать совпадение с шаблоном
str = [Link]("h2")[0].innerText;
// шаблон - поиск английских букв
let reg = /[a-z]/ig;
// поиск
let arr = [Link](reg);
// вывод позиции вхождения
[Link](arr); // 12 - совпадений (каких?)
</script>
Захват переменных
Например, шаблон:
/{([a-z-]{5,15})}/i
сопоставляется с подстроками:
1. <a href="#" target="blank">{image-bear}</a>
2. <a href="#" target="blank">{image-21}</a>
и в случае нахождения совпадения запоминает совпавшее значение
в переменной. В первой подстроке запомненное значение – image-bear. Во
второй подстроке совпадения не найдено (цифр в шаблоне нет).
В дальнейшем запомненное значение скобочной группы можно
повторно использовать в объекте регулярного выражения. Очень часто
используется, например, при поиске и замене.
Сопоставленную подстроку можно достать из предопределённых
пременных $1, $2, ..., $9 объекта RegExp.
ПРИМЕР 2
<div>
{{1}}
{{2}}
{{3}}
</div>
<script>
// забираем из документа содержимое блока div
var str = [Link]("div").innerHTML;
// выполняем замену с использованием захватывающих скобок
// ([1-9]) - захват числа
// $1 - захватываемое число
var newstr = [Link](/{{([1-9])}}/g, `<img src='$[Link]' width='350px'>`);
// замещаем блок новым содержимым
[Link]("div").innerHTML = newstr;
</script>
164
Количественные метасимволы
Ниже представлены варианты указания количественных
метасимволов, их еще называют квантификаторами:
* - ноль и большее количество раз.
+ - один и большее количество раз.
? - ноль или один раз
{n} - точно n раз.
{n,} - n или большее количество раз.
{n,m} - по крайней мере, n раз, но не более чем m раз.
* - Звездочка
Символ звездочки «*» соответствует предыдущему символу
повторенному 0 или более раз. Эквивалентно {0,} (кванторы будут
рассмотрены далее).
Шаблон Строка Количество совпадений
mn [Link]("mn".match(/ma*n/g)); // 1
man [Link]("man".match(/ma*n/g)); // 1
ma*n mann [Link]("mann".match(/ma*n/g)); // 1
main [Link]("main".match(/ma*n/g)); // null
woman [Link]("woman".match(/ma*n/g)); // 1
165
mann [Link]("mann".match(/ma?n/g)); // 1
main [Link]("main".match(/ma?n/g)); // null
woman [Link]("woman".match(/ma?n/g)); // 1
ПРИМЕР 3
<div> <script>
<h2>1. Я спокоен</h2> {{img1}} // забираем из документа содержимое
<br/> блока div
<h2>2. Я открыт к позитивным var str =
изменениям</h2> {{img2}} <br/> [Link]("div").innerHTML;
<h2>3. Из тела уходит // выполняем замену
напряжение</h2> {{img3}} <br/> var newstr = [Link](/{{img([1-5])}}/g,
<h2>4. Я хорошо справляюсь с `<img src='pict$[Link]' width='350px'>`);
любыми трудностями</h2> // замещаем блок новым содержимым
{{img4}} <br/> [Link]("div").innerHTM
<h2>5. Мне хорошо и L = newstr;
уютно</h2> {{img5}} </script>
</div>
Метасимволы позиционирования
К метасимволам позиционирования относят символы:
^ - начало строки.
$ - конец строки.
^ - Каретка
166
Символ каретки «^» используется для проверки того, начинается ли
строка с определенного символа (символ начала строки).
Шаблон Строка Количество совпадений
abcd [Link]("abcd".match(/^ab/g)); // 1
^ab _ab [Link](" ab".match(/^ab/g)); // null
ac [Link]("ac".match(/^ab/g)); // null
$ - Доллар
Символ доллара «$» используется для проверки того, заканчивается
ли строка определенным символом (символ конца строки).
Шаблон Строка Количество совпадений
a [Link]("a".match(/a$/g)); // 1
cora [Link]("cora".match(/a$/g)); // 1
a$
form [Link]("form".match(/a$/g)); // null
mam a [Link]("mam a".match(/a$/g)); // 1
167
alert( "/".match(/\//) );
ПРИМЕР 4
<h2>Проверка данных, введенных пользователем</h2>
<script>
// Фамилию, Имя, Логин, Пароль храним в переменных
// зададим шаблоны соответствия для пользовательских данных
// используем символы начала и конца строки
let pattern_surname = /^[a-zа-яё\s]{3,20}$/ig;
let pattern_name = /^[a-zа-яё]{3,10}$/ig;
let pattern_login = /^[a-zA-Z\d]{5,10}$/g;
let pattern_pwd = /^[\w\d@%&\[\]]{5,15}$/g;
// строковые данные пользователя в переменных
let surname = "Гарсиа Фернандес";
let name = "123Denis";
let login = "master123й";
let pwd = "Denis123@qw[";
// сопоставление шаблона со строковыми данными
// вывод результата в консоль браузера
[Link]("Фамилия: ", pattern_surname.test(surname));
[Link]("Имя: ", pattern_name.test(name));
[Link]("Логин: ", pattern_login.test(login));
[Link]("Пароль: ", pattern_pwd.test(pwd));
</script>
ПРИМЕР 5
<div id="full"> <script>
<!-- буквы -a и -b для var text =
идентификации строк --> [Link]("#full").innerHTML;
Fullstack-developer-a // выбрать только ту строку, где в конце
Fullstack-developer-b<br> - \n
</div> var pattern = /[a-z-]{1,25}(?=\n)/ig;
<hr> // выбрать только ту строку, где в конце
<div id="frame"> - \br
<!-- буквы -a и -b для // var pattern = /[a-z-]{1,25}(?=<br>)/ig;
идентификации строк --> [Link]([Link](pattern));
<span>Framework-devel-a // --------------------
Framework-devel-b var text =
</div> [Link]("#frame").innerHTML;
<hr> // выбрать только ту строку, где в начале
<div id="web"> - <span>
Web-разработчик - 120.000 <br> var pattern = /(?<=<span>)[a-z-]{1,25}/ig;
Web-devel - 70.000 <br> [Link]([Link](pattern));
Веб-дизайнер - 65.000 <br> // --------------------
Веб-программист - 105.000 var text =
</div> [Link]("#web").innerHTML;
// выбрать только ту строку, где
168
разрядов числа 7 и больше
// т.е. больше число
var pattern = /[a-zа-я-]{3,25}(?=.*[0-
9.]{7})/ig;
[Link]([Link](pattern));
// --------------------
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Используя возможности регулярных выражений (метасимволы,
захват) напишите скрипт для поиска и замены шаблонов подстрок на
соответствующие изображения. Для выполнения задания воспользуйтесь
файлами в папке «Раздаточный материал - Практическая работа №19 -
Задание 1.
ЗАДАНИЕ 2
Используя возможности регулярных выражений напишите скрипт для
поиска и замены шаблонов подстрок на соответствующие изображения.
Будьте внимательны, файлы изображений и заменяемые подстроки носят
уникальный характер (в отличии от предыдущего задания). Для выполнения
задания воспользуйтесь файлами в папке «Раздаточный материал -
Практическая работа №19 - Задание 2.
ЗАДАНИЕ 3
В файле [Link] (в папке «Раздаточный материал - Практическая
работа №19 - Задание 3) вам предложен фрагмент статьи «Что такое frontend-
разработка? Frontend vs Backend». Используя возможности регулярных
выражений, напишите скрипт, выполняющий выделение жирным
шрифтом всех английских символов статьи.
169
Практическая работа 20
УСЛОВНЫЕ ИНСТРУКЦИИ
Содержание
Стань 1. Условный оператор if
профессионалом! 2. Оператор switch
3. Правила приведения условия
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Условные операторы - это операторы языка JavaScript, которые в
зависимости от некоторого условия позволяют выполнить одно или
несколько определённых инструкций.
Формы условных операторов в JavaScript:
условный оператор if (с одной ветвью);
условный оператор if...else (с двумя ветвями);
условный оператор else if... (с несколькими ветвями);
тернарный оператор (?:);
оператор выбора switch.
Условный оператор if
Условный оператор выполняет тот или иной блок кода в зависимости
от того, верно ли условие.
Синтаксис без фигурных скбок:
if (condition) statement
Параметры:
сondition - выражение, являющееся условием для проверки. Должно
равняться true или false (или быть приведено к одному из этих значений);
statement - инструкция, которая выполняется, если условие является
true или приведено к нему.
Если необходимо выполнить несколько инструкций, то их необходимо
поместить в фигурные скобки.
Синтаксис с фигурными скобками
if (condition) {
statement 1
...
statement n
}
170
Рекомендуется, использовать фигурные скобки даже когда
используется одна инструкция.
ПРИМЕР 1
<script>
// шаблон регулярного выражения RegExp
var reg = /^[а-яё-]{3,25}$/i;
// инициализируем переменную
// var surname = "Бендер-Задунайский";
var surname = prompt("Введите фамилию. Символы [а-яё-] в количестве от 3 до
25");
// проверка соответствия вернет true или false
var res = [Link](surname);
// если res == true
if (res) {
alert ("Вы успешно справились с заданием!");
}
</script>
171
let num =12;
let isChecked = true;
if (num <10|| num >18|| isChecked)
{/* ... */}
При выполнении ИЛИ|| с несколькими значениями:
result = value1 || value2 || value3;
Оператор || выполняет следующие действия:
Вычисляет операнды слева направо.
Каждый операнд конвертирует в логическое значение. Если результат
true, останавливается и возвращает исходное значение этого операнда.
Если все операнды являются ложными (false), возвращает последний из
них. Значение возвращается в исходном виде, без преобразования.
Другими словами, цепочка ИЛИ|| возвращает первое истинное
значение или последнее, если такое значение не найдено.
ПРИМЕР 2
<script>
[Link]( 1 || 0 ); // 1
[Link]( true || 'also true' ); // true
[Link]( null || 1 ); // 1 (первое истинное значение)
[Link]( null || 0 || 'hello' ); // 1 (первое истинное значение)
[Link]( undefined || null || 0 ); // 0 (поскольку все ложно, возвращается
последнее значение)
</script>
Сокращённое вычисление
Операндами могут быть как отдельные значения, так и
произвольные выражения. ИЛИ || вычисляет их слева направо.
Вычисление останавливается при достижении первого истинного значения.
Это хорошо заметно, когда выражение, указанное в качестве второго
аргумента, имеет побочный эффект, например, изменение переменной.
В приведённом ниже примере переменная x не изменяется:
var x;
true||(x =1); // (x = 1) не станет вычисляться
alert(x); // undefined
Если бы первый аргумент имел значение false, то || приступил бы к
вычислению второго и выполнил операцию присваивания:
var x;
false||(x=1); // в этом примере (x= 1) вычисляется
alert(x); // 1
На месте первого аргумента может быть сложное выражение или,
например, функция, тогда поведение программы становится менее
очевидным.
// первым аргументам используем фунцию
172
var x;
myUserFun()||(x=1);
// в этом примере (х = 1) вычисляется
alert(x); // ?
Присваивание – лишь один пример. Но, могут быть и другие побочные
эффекты, которые не проявятся, если вычисление до них не дойдёт.
Такой вариант использования || является аналогом if. Первый операнд
преобразуется в логический, если он оказывается ложным, начинается
вычисление второго.
В большинстве случаев лучше использовать классический if, чтобы
облегчить понимание кода, но иногда это может быть удобно.
&& (И)
Оператор И пишется как два амперсанда &&.
Синтаксис:
result = a && b;
В традиционном программировании И возвращает true, если оба
аргумента истинны, а иначе – false:
alert(true && true); // true
alert(false && true); // false
alert(true && false); // false
alert(false && false); // false
Пример с if:
let hour =12;
let minute =30;
if (hour==12 && minute==30) {/*...*/}
При нескольких подряд операторах И:
result = value1 && value2 && value3;
Оператор && выполняет следующие действия:
Вычисляет операнды слева направо.
Каждый операнд преобразует в логическое значение. Если результат
false, останавливается и возвращает исходное значение этого операнда.
Если все операнды были истинными, возвращается последний.
Другими словами, И возвращает первое ложное значение, или
последнее, если ничего не найдено.
Вышеуказанные правила схожи с поведением ИЛИ. Разница в том, что
И возвращает первое ложное значение, а ИЛИ – первое истинное.
ПРИМЕР 3
<script>
// если первый операнд истинный, будет возвращен второй
[Link]( 1 && 0 ); // 0
[Link]( 1 && 5 ); // 5
173
// если первый операнд ложный, он будет возвращен, второй операнд
игнорируется
[Link]( null && 5 ); // null
[Link]( 0 && "Vivat the king" ); // 0
</script>
Можно передать несколько значений подряд. В таком случае
возвратится первое ложное значение, на котором остановились
вычисления.
alert(1 && 2 && null && 3); // null
Когда все значения верны, возвращается последнее.
alert(1 && 2 && 3); // 3
Как и оператор ИЛИ ||, И && иногда может заменять if.
let x =1;
(x >0) && alert('Hello, world!');
Действие в правой части && выполнится только в том случае, если до
него дойдут вычисления. То есть, alert() сработает, если в левой части (x > 0)
будет true. Получился аналог:
let x =1;
if (x >0) {
alert('Hello, world!');
}
Однако, как правило, вариант с if лучше читается и воспринимается.
Он более очевиден, поэтому лучше использовать его.
! (НЕ)
Оператор НЕ представлен восклицательным знаком !.
Синтаксис:
result =!value;
Оператор принимает один аргумент и выполняет следующие действия:
сначала приводит аргумент к логическомутипу true/false;
затем возвращает противоположное значение.
Например:
alert(!true); // false
alert(!0); // true
alert(!'Балалайка' ); // false
В частности, двойное НЕ!! используют для преобразования значений к
логическому типу:
alert(!!"It’s My Life"); // true
alert(!!null); // false
То есть первое НЕ преобразует значение в логическое значение и
возвращает обратное, а второе НЕ снова инвертирует его. В конце мы имеем
простое преобразование значения в логическое.
174
Есть немного более подробный способ сделать то же самое –
встроенная функция Boolean:
alert( Boolean("my-string")); // true
alert( Boolean(null)); // false
ПРИМЕР 4
<script>
// определим переменные для хранения данных
let name = "Джон Джозеф Траволта"; // не вписывается в длину
let login = "john-travolta";
let pwd = "holly@wood!"; // символ ! - не валиден
// определим шаблоны длч проверки данных
let namePattern = /^[а-яё ]{3,15}$/i;
let loginPattern = /^[a-z0-9-]{3,15}$/i;
let pwdPattern = /^[a-z_@#$0-9-]{5,15}$/i;
// выполним проверку данных на валидность
let nameValid = [Link](name);
let loginValid = [Link](login);
let pwdValid = [Link](pwd);
// выведем сообщение, если валидация не пройдена
if (!nameValid) [Link]("Значение Имя не валидно");
if (!loginValid) [Link]("Значение Логин не валидно");
if (!pwdValid) [Link]("Значение Пароль не валидно");
</script>
ПРИМЕР 5
<script>
// шаблон RegExp
var reg = /^[а-яё-]{3,25}$/i;
175
// инициализируем переменную через диалог с пользователем
var surname = prompt("Введите фамилию. Символы [а-яё-] в количестве от 3 до
25");
// проверка соответствия вернет true или false
if ([Link](surname)) {
// если true
alert ("Вы успешно справились с заданием!");
} else {
// если false
alert ("Бумс... Что-то пошло не так?");
}
</script>
ПРИМЕР 6
<script>
// дадим пользователю право определить порядок выполнения кода
if (confirm("Вы хотите изучать JavaScript?")) {
alert ("Очень хорошо!\nПриготовьтесь погрузиться в удивительный мир
frontend разработки!!!") ;
} else if (confirm("Может тогда PHP?")){
alert ("Прекрасно ;)");
}
else if (confirm("Ну может из Пастернака что-нибудь??")) {
[Link] (poem);
} else {
alert("Вам трудно угодить ...")
}
</script>
Оператор switch
Оператор switch предназначен для выполнения одного варианта
инструкций из нескольких в зависимости от значения выражения. Выбор
того или иного варианта определяется посредством строгого равенства
результата выражения значению варианта case.
Синтаксис:
switch (expression) {
case label1:
statements1
[break]
176
case label2:
statements2
[break]
...
case labelN:
statementsN
[break]
default:
statements_def
[break]
}
Параметры:
expression - выражение для сравнения.
labelN - значение, с которым сравнивать.
statementsN - ветка кода, на которую перейдет управление при
выполнении условия expression = labelN.
statements_def - ветка кода, которая будет выполнена, если expression
не совпадет ни с одним значением labelN.
Ключевое слово default является необязательным. Оно используется,
когда необходимо задать инструкции, которые нужно выполнить, если
результат выражения не будет равен ни одному значению варианта (case).
ПРИМЕР 7
<script>
let day;
// тестируем оператор switch
switch (new Date().getDay()) {
case 0:
day = 'Воскресенье';
break;
case 1:
day = 'Понедельник';
break;
case 2:
day = 'Вторник';
break;
case 3:
day = 'Среда';
break;
case 4:
day = 'Четверг';
break;
case 5:
day = 'Пятница';
break;
default:
day = 'Суббота';
}
alert ("Сегодня " + day + ". Вооот...");
</script>
177
Конструкция switch служит для сравнения значения на равенство с
различными вариантами. При этом равенство подразумевается в смысле
оператора "= = =", сравнивать с регулярным выражением или как-то еще
switch не умеет.
Если совпадение найдено, то соответствующий код исполняется до
оператора break, который прекращает выполнение switch и передает
управление дальше.
ПРИМЕР 8
<div id="app"></div>
<script>
let msg = `
Напишите, кто вы по темпераменту: \n
- Флегматик
- Сангвиник
- Холерик
- Флегматик
`;
switch (prompt(msg)) {
case "Флегматик":
temp = '<h2>Флегматик</h2>В своей деятельности они всегда склонны к
порядку и любят привычную для них обстановку. При этом флегматики с трудом
воспринимают любые перемены. В своей деятельности они всегда доводят
начатое ими дело до конца. Флегматики в меру общительны и отличаются
устойчивым настроением. Спокойствие таких людей поражает. Их сложно
вывести из себя или задеть эмоционально. Они умело уклоняются от ссор, не
теряют чувства самообладания даже в критических стрессовых ситуациях.';
break;
case "Сангвиник":
temp = '<h2>Сангвиник</h2>Это крайне непоседливые, энергичные, легкие
на подъем люди, которые очень любят движение. Сангвиникам присущи быстрая
реакция, выразительная жестикуляция и мимика. Они очень похожи на
холериков, но более уравновешены, готовы взяться за любую работу, но
максимальный эффект будет лишь в том случае, когда она вызовет у них
настоящий интерес. Люди с сангвиническим типом темперамента очень
общительны, жизнерадостны, легко приспосабливаются к любой жизненной
ситуации.';
break;
case "Холерик":
temp = '<h2>Холерик</h2>Холерики, по сравнению с сангвиниками,
вспыльчивы, непостоянны, агрессивны и импульсивны. Несмотря на все
вышесказанное, холерики, как правило, незлопамятны и очень отходчивы. Они
способны выполнять любую работу, однако монотонность им быстро надоедает.
Такие люди часто не доводят до логичного завершения начатую работу.';
break;
case "Меланхолик":
temp = '<h2>Меланхолик</h2>Достаточно ранимые, обидчивые и скрытые
личности. Они склонны к глубоким переживаниям и грустным мыслям.
Меланхоликам свойственны сдержанность, замедленная речь, движения,
нерешительность, робость и смущение.';
break;
default:
temp = '<h2>Вы неврастеник! ;)</h2>';
178
}
[Link]("div#app").innerHTML = temp;
</script>
Ключевое слово break не является обязательным, но если вы не будете
использовать его в данном примере, то в качестве значения переменной temp
всегда будете получать дефолтное значение.
Рассмотрим пример работы switch без break. В представленном
примере будут последовательно выполнены последние три вызова метода
alert().
ПРИМЕР 9
<script>
let x = 2 + 2;
switch (x) {
case 3:
alert('Маловато будет!');
case 4:
alert('Гадал?');
case 5:
alert('Перебор...');
default:
alert('Кто здесь?');
}
</script>
ПРИМЕР 10
<script>
// объявим данные для проверки
179
let name = "Denis1";
let login = "master";
let pwd = "Denis123@qw^";
// определим шаблоны проверки
let name_pattern = /^[a-zа-яё]{3,10}$/ig;
let login_pattern = /^[a-zA-Z0-9 ]{5,10}$/g;
let pwd_pattern = /^[a-zA-Z0-9@#$%^&*]{5,15}$/g;
// предположим, что проверяться будет не один пользователь
// пригодится в следующих уроках
let user = [];
// первый пользователь
user[0] = {};
// выполняем валидацию данных
user[0].name = [Link](name_pattern) ? name : "Поле name не валидно";
user[0].login = [Link](login_pattern) ? login : "Поле login не валидно";
user[0].pwd = [Link](pwd_pattern)? pwd : "Поле pwd не валидно";
// вывод массива в консоль
[Link](user);
</script>
180
ПРИМЕР 11
<script>
// 1 вариант, user - не объявлена
/*
2 вариант, user объявлена, но инициализирована пустой строкой
var user = ""; // false
*/
/*
3 вариант, user объявлена, и инициализирована строкой
var user = "Denis"; // true
*/
if (user) {
[Link]('Привет, ' + user + '!');
} else {
[Link]('Привет, гость!');
}
</script>
ПРИМЕР 12
<script>
// на сайте действует скидка - 20%
// если сумма заказа свыше 10.000, то скидка - 25%
let orderJSON = `
{
"user":{
"name":"Евгений",
"login":"master",
"email":"master@[Link]"},
"info":{
"date":"06.01.23",
"price":12500,
"newprice":"undefined"
},
"course":[
{
"id":41,
"name":"Frontend- и backend- программирование: PHP и JavaScript",
"hours":90,
"certificate":"yes",
"price":7500
},
{
"id":12,
"name":
"Веб анимация средствами JavaScript и CSS",
"hours":30,
"certificate":"yes",
"price":5000
}
]
}`;
// парсим строку JSON в JS объект
let order = [Link](orderJSON);
// текущая цена без учета скидок
181
price = [Link][0].price + [Link][1].price;
// вычисляем действующий процент скидки
if (price > 10000) {
discount = 0.25;
} else {
discount = 0.2;
}
// вычисляем новую цену
newprice = price - (price * discount);
// записыаеи в массив новую цену
[Link] = newprice;
[Link](order);
</script>
Вообще говоря, обычной практикой считается назначение статуса для
зарегистрированного пользователя. И уже, исходя, из существующего
статуса, осуществлять автоматическое регулирование системы скидок.
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В файле [Link] (в папке «Раздаточный материал - Практическая
работа №20 - Задание 1) находится разметка формы, в текстовые поля формы
вставлены пользовательские данные.
Используя регулярные выражения, напишите скрипт, проверяющий
соответствие данных пользователя указанному шаблону.
Шаблоны RegExp для проверки:
Имя: [а-яё]{3,10};
Логин: [a-z0-9]{3,10};
Email: [a-z0-9]{3,10}@[a-z]{2,5}.[a-z]{2,5};
Пароль: [a-z_@#$%^&*0-9-]{5,15}.
В случае выявления несоответствия данных шаблону:
В соответствующий текстовому полю блок <span> c class="valid"
вставьте текстовое сообщение об ошибке.
Выявите причину несоответствия шаблона и данных.
Изменив данные формы, устраните несоответствие.
ЗАДАНИЕ 2
Используя файл [Link] (в папке «Раздаточный материал -
Практическая работа №20 - Задание 2), напишите скрипт, выполняющий
следующий набор действий.
С помощью диалогового окна prompt() запросите у пользователя пару
login - email.
182
Используя конструкцию if ... else if и полученные данные login, email
определите статус (status) активного пользователя.
Соотношения для определения статуса представлены в таблице.
login email status
max max@[Link] premium
jon jon@[Link] gold
den den@[Link] silver
premium: discount = 0.2;
gold: discount = 0.15;
silver: discount =0.1.
Рассчитайте следующие значения заказа:
цену товара без скидки;
скидку в процентах;
цену товара со скидкой.
Выведите расчетные значения и данные пользователя в консоль
браузера. Примерный вывод представлен на рисунке.
183
Практическая работа 21
Содержание
Стань 1. Области видимости JavaScript
профессионалом! 2. Глобальный объект
3. Блок кода
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
184
Такое поведение тоже нежелательно.
// объявляем глобальную переменную
let login = 'master';
// объявляем глобальную переменную еще раз
let login = false; // Identifier 'login' has already been declared
Локальная область видимости
Переменные, которые используются только в определенной части кода,
считаются помещенными в локальную область видимости. Такие
переменные называются локальными.
В JavaScript выделяют следующие типы локальных областей
видимости:
область видимости блока;
область видимости функции;
лексическая область видимости.
Обычно у нас есть одна глобальная область видимости, и каждая
определяемая функция несёт в себе локальную область видимости. Все
локальные области видимости создаются только в функциональных областях
видимости, они не создаются циклами типа for или while или директивами
типа if или switch.
Новая функция – новая область видимости.
Область видимости блока
Переменная, объявленная внутри фигурных скобок {} через const или
let, доступна только внутри фигурных скобок.
Блочная область видимости является частным случаем области
видимости функции, т.к. функции объявляются с фигурными скобками
(кроме случаев использования стрелочных функций с неявным возвращением
значения).
Область видимости функции
Переменная, объявленная внутри функции, доступна только внутри
функции. Код снаружи функции не имеет к ней доступа. Если определить
функцию и задать внутри переменные, они принадлежат локальной области
видимости.
// глобальная область видимости
var myFunction = function () {
// локальная область видимости
};
Все переменные из локальной области видимости не видны в
глобальной области видимости. К ним нельзя получить доступ снаружи
напрямую.
185
ПРИМЕР 1
<script>
var myFunction = function() {
// локальная переменная
var login = 'big-johni';
[Link] (login);
};
// вызов функции
myFunction ();// big-johni
[Link] (login); // ReferenceError: login is not defined
</script>
Переменная login относится к локальной области видимости, она не
видна снаружи и поэтому не определена.
Функции не имеют доступа к областям видимости других функций,
когда они объявляются раздельно, даже если одна функция используется в
другой.
ПРИМЕР 2
<script>
// определение первой функции
function fnFirst () {
const first = `I'm variable of fnFirst`;
[Link](first);
}
// определение второй функции
function fnSecond () {
// вызов первой функции
fnFirst();
// пробуем получить доступ к переменной first
[Link](first); // Uncaught ReferenceError: first is not defined
}
// вызов второй функции
fnSecond();
</script>
С другой стороны, каждая функция, определённая внутри другой
функции, имеет свою локальную область видимости, связанную с областью
видимости внешней функции.
С таким поведением функции связана лексическая область видимости и
понятие - замыкание.
Лексическая область видимости
Если одна функция определена внутри другой, внутренняя имеет
доступ к области видимости внешней. Это называется лексической
областью видимости, или замыканием, или ещё статической областью
видимости.
В тоже время внешняя функция не имеет доступа к переменным
внутренней функции.
186
ПРИМЕР 3
<script>
var outerFunction = function () {
// внешняя переменная
let outer = 'John';
var innerFunction = function () {
// внутренняя переменная
let inner = 'Max';
[Link]('Значение внешней переменной: ' + outer);
};
// Uncaught ReferenceError: inner is not defined
[Link]('Значение внутренней переменной: ' + inner);
// вызов внутренней функции
innerFunction();
};
// вызов внешней функции
outerFunction();
</script>
С лексической областью видимости довольно просто работать – всё,
что определено в область видимости родителя, доступно в области
видимости потомка.
// область видимости A
var myFunction = function() {
// область видимости A + B
var mySecondFunction = function() {
// область видимости A + B + C
}; };
ПРИМЕР 4
<script>
var outerFunction = function () {
// внешняя переменная
let first = 'First';
var firstInnerFunction = function () {
// внутренняя переменная
let second = 'Second';
[Link]("Вложенная функция firstInnerFunction:");
[Link]('First variable: ' + first);
var secondInnerFunction = function () {
[Link]("Вложенная функция secondInnerFunction:");
[Link]('First variable: ' + first);
[Link]('Second variable: ' + second);
}
// вызов второй внутренней функции
secondInnerFunction();
};
// вызов первой внутренней функции
firstInnerFunction();
};
// вызов внешней функции
outerFunction();
</script>
187
Глобальный объект
Глобальный объект предоставляет переменные и функции, доступные в
любом месте программы. По умолчанию это те, что встроены в язык или
среду исполнения. В браузере глобальный объект называется window.
Ко всем свойствам глобального объекта можно обращаться напрямую.
ПРИМЕР 5
<script>
alert("Привет"); // это то же самое, что и
[Link]("Привет");
[Link]([Link]); // body
// это то же самое, что и
[Link]([Link]); // body
</script>
В браузере глобальные функции и переменные, объявленные с
помощью var, становятся свойствами глобального объекта:
// объявляем глобальную переменную
var value = 5;
alert ([Link]); // 5
При этом обычно рекомендуется использовать глобальные переменные
как можно реже.
Дизайн кода, при котором функция получает входные параметры и
выдаёт определённый результат, чище, надёжнее и удобнее для
тестирования, чем когда используются внешние, а тем более глобальные
переменные.
ПРИМЕР 6
<script>
// сделать информацию о пользователе можно глобальной,
// и более специфичной
[Link] = {
login: "denis",
level: "macho"
};
// доступ к переменной где угодно в коде
alert([Link]); // denis
// получить login из window можно явно
[Link]([Link]); // denis
</script>
188
Синтаксис:
[Link] = "Имя_окна";
Примечание. Окнам не обязательно иметь имя.
Если присвоить [Link] какое-то текстовое значение, например
"test", и перезагрузить страницу, то при повторном обращении к
[Link], вы получаете сохраненное свойство name со значением "test".
Такое поведение свойства позволяет сохранять и использовать данные после
перезагрузки страницы. Это могут быть любые строковые данные, в том
числе в JSON формате.
Используя подобное поведение свойства name объекта window можно
передавать данные между страницами.
ПРИМЕР 7
<script>
// присвоим свойству name строковые данные
[Link] = "I’ll be back!";
// тестируем свойство
[Link]("<h1>", [Link], "</h1>");
</script>
ПРИМЕР 8
<script>
// определение функции
189
function fnTest() {
y = 10; // y - глобальная
var x = 20; // x - уровня функции
}
// вызов функции
fnTest();
// проверяем переменные
[Link]("y = ", y); // 10
[Link]("x = ", x); // Uncaught ReferenceError: x is not defined
</script>
Различия между объявленной и необъявленной переменными
следующие:
Объявленные переменные ограничены контекстом выполнения, в
котором они были объявлены. Необъявленные переменные всегда
глобальны.
Объявленные переменные инициализируются до выполнения любого
кода. Необъявленные переменные не существуют до тех пор, пока к ним не
выполнено присваивание.
Необъявленные переменные можно удалять.
ПРИМЕР 9
Удаление необъявленных переменных:
<script>
var a = 1;
b = 2;
[Link]("a = ", window.a); // 1
[Link]("b = ", window.b); // 2
[Link]("---------------");
delete window.a;
delete window.b; // cвойство 'b' было удалено и больше не существует
[Link]("a = ", window.a); // 1
[Link]("b = ", window.b); // undefined
</script>
Оператор let
Оператор let объявляет переменную с блочной областью видимости с
возможностью инициализировать её значением.
Синтаксис:
let varname1 [= value1 [, varname2 [, varname3 ... [, varnameN]]]];
Параметры:
varnameN – имя переменной, может использовать любой допустимый
идентификатор.
valueN – начальное значение переменной, может быть любым
допустимым выражением.
Оператор let позволяет объявить локальную переменную с областью
видимости, ограниченной текущим блоком кода. В отличие от ключевого
190
слова var, которое объявляет переменную глобально или локально во всей
функции, независимо от области блока.
Область видимости переменной let – блок {...}.
Переменная, объявленная через var, видна везде в функции.
Переменная, объявленная через let, видна только в рамках блока {...}, в
котором объявлена.
ПРИМЕР 10
<script>
var x = 5; // x через var
let y = 5; // y через let
// блок кода
{
var x = 10;
let y = 10;
}
[Link]("x через var = ", x); // 10
[Link]("y через let = ", y); // 5
</script>
Это, в частности, влияет на объявления внутри if, while или for.
Переменная let видна только после объявления.
Переменные var существуют и до объявления. Ониравны undefined:
[Link](a); // undefined
var a = 5;
С переменными let всё проще. До объявления их вообще нет.
Такой доступ приведёт к ошибке:
[Link](a); // Uncaught ReferenceError: Cannot...
let a = 5;
Переменные let нельзя повторно объявлять. То есть, такой код выведет
ошибку:
let x;
let x; // Uncaught SyntaxError: Identifier ...
ПРИМЕР 11
<script>
var x = 'global x';
let y = 'global y';
// проверяем свойства глобального window
[Link](window.x); // global x
[Link](window.y); // undefined
</script>
191
В выводе программы будет отображена строка global x для window.x,
но undefined для window.y.
При использовании в цикле, для каждой итерации создаётся своя
переменная.
Блок кода
Блок кода или блок инструкций используется для группировки нуля
или более инструкций. Блок отделяется парой фигурных скобок и может
опционально быть поименован.
Синтаксис:
[name:] {
statement_1;
statement_2;
...
statement_n;
}
Параметры:
name – необязательное имя для визуальной идентификации или
использования как точки выхода для оператора break;
statement_1, statement_2, ..., statement_n – вызовы внутри блока.
Как самостоятельная конструкция используется редко. Как правило,
используется с операторами управления потоком (if, for, while и т.п.).
var auto ="Lada";
if ( auto == "Rolls Roys")
{
alert ("Жизнь удалась!");
} else
{
alert ("Упс... :(");
}
Область видимости блока с использованием var
Переменные, объявленные через var, не имеют блочной области
видимости. Переменные, введённые внутри блока, имеют областью
видимости содержащую их функцию или скрипт, и последствия записи в них
значения распространяются за границы, собственно, блока, в котором они
объявлены.
Другими словами, блок инструкций не вводит новую область
видимости. Хотя блоки не являются нарушением синтаксиса, не стоит
использовать их слишком часто, потому что они не делают то, чего вы от них
ожидаете.
Пример самостоятельного использования блока:
var x = 1;
{
var x = 2;
192
}
[Link](x); // 2
В консоль выводится 2, потому что оператор var x внутри блока - в
той же области видимости, что и оператор var x перед блоком.
Область видимости блока с использованием let и const
Наоборот, идентификаторы, объявленные с помощью let и const, имеют
блочную область видимости:
let x = 1;
{
let x = 2;
}
[Link](x); // 1
x = 2 ограничено рамками области видимости блока, в котором оно
было определено.
То же самое и для const:
const c =10;
{
const c =2;
}
[Link](c); // 10
ПРИМЕР 12
Область видимости объекта Math:
193
<script>
var maxNum = 10;
var minNum = 1;
// получение случайного числа
// используем функции [Link](), [Link]()
with (Math) {
let maxNum = 5;
float = random() * (maxNum - minNum + 1) + minNum;
num = floor(float) ;
}
// вывод расчетных значений
[Link](float);
[Link](num);
</script>
ПРИМЕР 13
Область видимости with и коллекция HTML элементов:
<script>
with ([Link]("h1").style) {
// избавились от необходимости каждый раз при упоминании свойства
// писать цепочку доступа к HTML-элементу
color = "red";
fontSize = "36pt";
fontFamily = "Arial";
fontWeight = "900";
}
</script>
Использование with с одной стороны наглядно, с другой - может
скрывать ошибки программирования, и соответствующий код плохо
сжимается компрессорами. По этим причинам злоупотреблять оператором
with не рекомендуется.
Вместо этого можно использовать чуть менее наглядный, но надежный
доступ через временную переменную:
// создание временной переменной
el = [Link]("h2").style;
// доступ к свойствам через временную переменную
[Link] = "red";
[Link] = "36pt";
[Link] = "Arial";
[Link] = "900";
Допустим, мы имеем следующий объект:
let data = {
id_user : 3,
user: {
name : "Евгений",
surname : "Даугава",
login : "master",
email : "pechora-pro@[Link]"
},
personal: {
inn : 123456789,
194
police : "12-V23",
certificate : "yes",
phone : "8(912)552-92-25"
}
};
Объект сложнее предыдущих примеров, но это ничто, по сравнению с
возможными объектами реальных приложений, так что тренируемся.
Используя область видимости with, получаем доступ к свойствам
объекта data:
with(data) {
[Link](id_user); // тест доступа
}
Получаем доступ к свойствам объекта user:
with([Link]) {
[Link](name); // тест доступа
}
Получаем доступ к свойствам объектов data, user:
// более гибкий способ работы с объектом data
with(data) {
[Link](id_user);
with(user){
[Link](name);
}
}
ПРИМЕР 14
<script>
let data = {
id_user : 3,
user:{
name : "Евгений",
surname : "Даугава",
login : "master",
email : "pechora-pro@[Link]"
},
personal:{
inn : 123456789,
police : "12-V23",
certificate :"yes",
phone : "8(912)552-92-25"
}
};
with(data) {
with(user){
var html = `
Пользователь: ${name} ${surname} <p>
Идентификатор в системе: ${id_user} <p>
`;
}
}
195
[Link](html);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В файле [Link] (в папке «Раздаточный материал - Практическая
работа №21 - Задание 1) содержится некоторая информация о заказе
студента. Напишите скрипт вывода заказа в окно браузера. При
формировании вывода используйте конструкцию блока with.
Обратите внимание, организация цепочки блоков видимости должна
предотвратить доступ к переменным по их составным именам. Таких имен
как:
[Link];
[Link].
быть не должно.
ЗАДАНИЕ 2
Ниже вам предложены данные, JS-объект которых необходимо
сформировать в файле [Link]:
team = "Гражданская оборона"
name = "Тоталитаризм"
alias = "totalitarizm"
country = "СССР"
content = "Шестой официальный альбом группы \"Гражданская оборона\".
Один из серии альбомов 1987-го года. Как и на всех альбомах серии, Егор Летов
играет один на всех инструментах."
date = 1987
path = "[Link]"
note = "Записано в начале июня 1987 года в ГрОб-студии. 5 декабря 2005
года альбом пересведен и реставрирован Егором Летовым и Натальей Чумаковой."
Напишите скрипт, передающий сформированный JS-объект из файла
[Link] в файл [Link]. Для передачи используйте свойство name
объекта window.
196
Практическая работа 22
ПРОСТЫЕ ЦИКЛЫ
Содержание
Стань 1. Цикл for
профессионалом! 2. Цикл while
3. Цикл do … while
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Циклы JavaScript обеспечивают многократное выполнение
повторяющихся вычислений. Они оптимизируют процесс написания кода,
выполняя одну и ту же инструкцию или блок инструкций, образующих тело
цикла, заданное число раз (используя переменную-счётчик) или пока
заданное условие истинно.
В JavaScript существуют следующие операторы цикла:
for используется, когда вы заранее знаете, сколько раз вам нужно что-
то сделать;
while используется, когда вы не знаете, сколько раз нужно что-то
сделать;
do ... while работает аналогично с оператором while. Отличается тем,
что do...while всегда выполняет выражение в фигурных скобках, по крайней
мере один раз, даже если проверка условия возвращает false.
for ... of используется для обхода итерируемых объектов (строк,
коллекций, массивов и некоторых других);
for ... in используется для обхода свойств объектов.
Цикл for
Самый сложный, но при этом самый распространенный цикл - цикл
for. Данный цикл в основном используется, когда известно точное
количество повторений (итераций). Этот цикл ещё называют циклом со
счётчиком.
Синтаксис:
for ( [initial-expression]; [condition]; [final-expression] ) {
statement;
};
Параметры:
initial-expression (инициализация) - выражение, которое выполняется
один раз перед выполнением цикла. Обычно используется для
инициализации счётчика;
197
condition (условие) - выражение, истинность которого проверяется
перед каждой итерацией. Если выражение вычисляется как истина, то
выполняется итерация, в противном случае цикл for завершает работу;
final-expression (финальное выражение) - выражение, которое
выполняется в конце каждой итерации. Обычно используется для изменения
счетчика.
statement (тело цикла) - одна или несколько инструкций, выполнение
которых нужно повторять. При этом если тело цикла состоит из одной
инструкции, то её можно не заключать в фигурные скобки.
Ни один из параметров не является обязательным.
Схематически цикл можно представить следующим рисунком:
ПРИМЕР 1
<script>
// цикл for
for (var i = 0; i < 5; i++) {
[Link](i + ": Hello, JavaScript!");
}
</script>
Как работает цикл for:
инициализация: var i = 0 (объявление переменной i и присвоение ей
значения 1);
условие выполнения цикла: i < 5 (пока значение переменной i
меньше 5);
тело цикла: одна или несколько инструкций, которые нужно
выполнять: [Link] (i + ": Hello, JavaScript!").
финальное выражение, которое нужно выполнять в конце каждой
итерации: i++ (увеличение значение переменной i на 1);
Необязательные части цикла цикла for
198
Ни одна часть цикла for не является обязательной.
Например, можно пропустить выражение инициализации. В этом
случае инициализацию переменной можно вынести за пределы цикла.
var i =0;
// цикл for
for (; i < 5; i++) {
[Link] (i + ": Hello, JavaScript!");
}
Условие тоже не является обязательным. Без условия цикл будет
выполняться бесконечное количество раз. В этом случае чтобы его
прервать (выйти из цикла) необходимо использовать инструкцию break.
// цикл for
for (var i = 0; ; i++) {
if (i == 5) { // условие прерывания цикла
break;
}
[Link](i + ": Hello, JavaScript!");
}
Финальное выражение в for также является не обязательным. Счётчик
цикла в этом случае можно, например, изменять в теле.
// цикл for
for (var i = 0; i <5;) {
[Link](i + ": Hello, JavaScript!");
i++; // увеличение счетчика на 1
}
Таким образом, в общем случае, цикл for можно записать в виде
выражения бесконечного цикла.
ПРИМЕР 2
<script>
var i = 0;
// цикл for
for (;;) {
// условие прерывания цикла
if (i == 5) break;
[Link](i + ": Hello, JavaScript!");
i++; // увеличение счетчика на 1
}
</script>
ПРИМЕР 3
<div id="citate"> <script>
<p>После общения с некоторыми [Link]("<h2>Динамический
людьми у меня появляется ярко вывод элементов коллекции</h2>");
выраженный комплекс // получение коллекции элементов p с
полноценности.</p> классом sel
<p class="sel">Граница между светом и let elements =
тенью — ты.</p> [Link]('#citate [Link]');
<p>Тот, кто не разбирается ни в чем, // цикл for по элементам коллекции
может взяться за что угодно.</p> for (var i = 0; i < [Link]; i++) {
<p class="sel">Безвыходным мы // доступ к элементу коллекции через
называем положение, выход из индекс
которого нам не нравится.</p> [Link]("<h4>",
<p class="sel">Я думал, что опустился на elements[i].innerText, "</h4>");
самое дно, как вдруг снизу }
постучали…</p> </script>
<p class="sel">Мгновение осознания
своей бесталантности есть вспышка
гениальности.</p>
<p>Иногда надо замолчать, чтобы тебя
выслушали.</p>
</div>
Если значение свойства length не изменяется в ходе выполнения цикла,
можно сохранить его в локальной переменной, а затем использовать эту
переменную в условном выражении. Таким образом, можно повысить
скорость выполнения цикла, так как значение свойства length будет
извлекаться всего один раз за всё время работы цикла.
let len = [Link];
// цикл for
for (var i =1; i <= len; i++) { ... }
Вот теперь объем обрабатываемых данных перестает существовать.
Циклы будут делать все за нас. Ну, почти все...
Цикл while
Цикл while предназначен для многократного выполнения одних и тех
же инструкций до тех пор, пока истинно некоторое условие. Цикл в
основном используется, когда количество повторений заранее не известно.
Синтаксис:
while (condition) {
statement;
};
Параметры:
condition - условие цикла;
200
statement - блок инструкций для выполнения во время итераций. Будет
выполняться, пока верно условие condition.
Цикл while - цикл с предварительной проверкой условного
выражения. Истинность условия проверяется перед каждым выполнением.
Если перед первой итерацией условие ложно, то цикл не выполнится ни разу.
Схематически цикл можно представить следующим рисунком:
ПРИМЕР 4
<script>
// инициализируем переменные цикла
var i = 1;
var msg = '';
// цикл while
while (i <= 10) {
// формируем строку
msg += i + ' x 3 = ' + (i * 3) + '\n';
i++;
}
// выводим строку в консоль
[Link](msg);
</script>
Перебор элементов коллекции циклом while
Следующий скрипт получает коллекцию строк таблицы (HTML-узлы
tr), в цикле создает коллекцию ячеек td текущей строки и выводит в виде
нумерованного списка:
название;
дату выпуска;
статус альбома.
ПРИМЕР 5
<table border=1 width="75%"> <script>
201
<tr> // получение коллекции строк таблицы
<th>ID</th> var elements =
<th>Альбом</th> [Link]('tbody tr');
<th>Дата выпуска</th> // количество элементов коллекции
<th>Лейбл</th> let len = [Link];
<th>Носитель</th> // инициализируем переменные цикла
<th>Статус</th> var line = '';
</tr> var i = 0;
<tbody> // цикл while
<tr> while (i < len) {
<td>1</td> // получаем коллекцию элементов td
<td>Atom Heart Mother</td> для каждой строки tr
<td>10 октября 1970</td> let td = [Link](i).children;
<td>EMI, Harvest, Capitol</td> // формируем строку для вывода в
<td>LP, CD</td> браузер
<td>Золотой (USA)</td> line += "<li><b>" + [Link](1).innerText;
</tr> line += "</b> (" + [Link](2).innerText + "
<tr> / ";
<td>2</td> line += [Link](5).innerText + ")</li>";
<td>Meddle</td> i++;
<td>30 октября 1971</td> }
<td>EMI, Harvest, Capitol</td> let html = "<h2>Динамический список
<td>Vinyl, кассета, CD</td> дискографии группы Pink Floyd</h2>";
<td>Платиновый (USA)</td> html += "<ol>" + line + "</ol>";
</tr> // выводим сформированный контент в
</tbody> браузер
</table> [Link](html);
</script>
202
Схематически цикл можно представить следующим рисунком:
ПРИМЕР 6
<script>
var i = 11;
// цикл do
do {
// выполняем инструкцию цикла
[Link](i + ": Hello, JavaScript!");
i++;
} while (i < 10); // проверяем условие
</script>
Перебор элементов коллекции циклом do...while
Следующий скрипт получает коллекцию элементов li нумерованного
списка, далее в цикле получает элементы li вложенного списка и выводит
сформированную строку в виде маркированного списка.
ПРИМЕР 7
<ol> <script>
<li>Зеленая миля // получение коллекции строк таблицы
<ul> var elements =
<li>режиссёр: Фрэнк [Link]('tbody tr');
Дарабонт</li> // количество элементов коллекции
<li>год: 1999</li> let len = [Link];
<li>страна: США</li> // инициализируем переменные цикла
</ul> var line = '';
203
</li> var i = 0;
<li>Криминальное чтиво // цикл while
<ul> while (i < len) {
<li>режиссёр: Квентин // получаем коллекцию элементов td
Тарантино</li> для каждой строки tr
<li>год: 1994</li> let td = [Link](i).children;
<li>страна: США</li> // формируем строку для вывода в
</ul> браузер
</li> line += "<li><b>" + [Link](1).innerText;
<li>Форрест Гамп line += "</b> (" + [Link](2).innerText + "
<ul> / ";
<li>режиссёр: Роберт line += [Link](5).innerText + ")</li>";
Земекис</li> i++;
<li>год: 1994</li> }
<li>страна: США</li> let html = "<h2>Динамический список
</ul> дискографии группы Pink Floyd</h2>";
</li> html += "<ol>" + line + "</ol>";
</ol> // выводим сформированный контент в
браузер
[Link](html);
</script>
Сохранение коллекций
Сохранение элементов коллекции в одномерный массив
Переработаем код сценария «Пример 3». На этот раз сохраним
коллекцию элементов в одномерный массив.
ПРИМЕР 8
<script>
// объявляем массив
var arr = [];
// получаем коллекцию элементов p
let elements = [Link]('#citate [Link]');
// циклом for заполняем массив
for (var i = 0; i < [Link]; i++) {
arr[i] = elements[i].innerText;
}
// упакуем массив в JSON формат
arrJSON = [Link](arr);
[Link]("<h2>Упакованный в JSON массив</h2>");
// массив готов к передаче (например по сети)
// вывод в браузер
[Link](arrJSON);
// вывод в консоль
[Link](arr);
</script>
Сохранение элементов коллекции в массив объектов
Переработаем код сценария «Пример 5». Сохраним коллекцию
элементов в массив, состоящий из объектов (массив объектов).
204
ПРИМЕР 9
<script>
// получаем коллекцию строк таблицы
var elements = [Link]('tbody tr');
// количество элементов коллекции
let len = [Link];
// инициируем переменные
var arr = [];
var i = 0;
// цикл while
while (i < len) {
// получаем коллекцию элементов td для каждой строки tr
let td = [Link](i).children;
// объявляем пустой объект
obj = {};
// свойствам объекта присваиваем значения ячеек
[Link] = [Link](1).innerText;
[Link] = [Link](2).innerText;
[Link] = [Link](5).innerText;
// записываем объект в массив
arr[i] = obj;
// увеличиваем итератор цикла
i++;
}
// упакуем массив объектов в JSON-формат
var arrJSON = [Link](arr);
[Link]("<h2>Упакованный в JSON массив</h2>");
// выводим сформированный JSON-контент в браузер
[Link](arrJSON);
// в консоль
[Link](arr);
</script>
Бесконечные циклы
При создании любого цикла можно получить ситуацию бесконечного
цикла, который никогда не завершится. Такой цикл может потенциально
продолжать работать до тех пор, пока работает компьютер пользователя.
Большинство современных браузеров могут обнаружить это и
предложат пользователю остановить выполнение скрипта. Чтобы избежать
создания бесконечного цикла, вы должны быть уверены, что заданное
условие в какой-то момент вернёт false.
Например, следующий цикл задаёт условие, которое никогда не
возвращает false, так как переменная i никогда не будет меньше
ПРИМЕР 10
<script>
for (var i = 15; i > 10; i++) {
[Link]("Эта музыка будет вечной...<br>");
}
</script>
205
Инструкции break и continue
Внутри тела цикла можно использовать специальные инструкции:
break и continue.
Инструкция break предназначена для прекращения выполнения
текущего цикла. Другими словами, она осуществляет выход и передачу
управления инструкции, идущей после этого цикла.
Ниже представлен пример кода, в котором прерывается цикл по
перебору элементов массива, если его текущий элемент равен 5:
ПРИМЕР 11
<script>
var i = 1;
[Link]("<h2>Считаем слоников</h2>");
while (i <= 10) {
[Link] (i + "-й слоник <p>");
// прекращаем цикл при i == 7
if (i == 7) break;
i++;
}
[Link]("<h3>Первая инструкция после цикла</h3>");
</script>
Инструкция continue предназначена для прекращения дальнейшего
выполнения кода и перехода к следующей итерации цикла.
Пример кода, в котором при переменной цикла i=5 прерывается
текущая итерация цикла.
ПРИМЕР 12
<script>
var i = 0;
[Link]("<h2>Считаем динозавриков</h2>");
do {
i++;
// прерываем цикл при i == 5
if (i == 5) continue;
[Link] (i + "-й динозаврик<br>");
} while (i < 9);
[Link]("<hr>");
[Link]("5-й динозаврик пропал :(");
[Link]("<h3>Вы 5-го динозаврика не видели??</h3>");
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Вам предложен следующий список:
<h2>Ноутбук HUAWEI MateBook</h2>
206
<div>
<ol>
<li>185</li>
<li>Ноутбук HUAWEI MateBook D16 RLEF-X</li>
<li>Intel Iris Xe Graphics</li>
<li>Intel Core i5-12500H</li>
<li>12</li>
<li>16 ГБ</li>
<li>16'</li>
<li>76.299</li>
<li>[Link]</li>
</ol>
</div>
Соберите элементы списка в коллекцию. Используя любой из циклов,
добавьте данные каждого пункта списка в одномерный массив. Выведите
полученный массив в консоль. Результат вывода представлен на рисунке.
ЗАДАНИЕ 2
Вам предложен многоуровневый список Список ноутбуков и их
характеристик:
<h2>Список ноутбуков и их характеристик</h2>
<ol>
<li>Ноутбук HUAWEI MateBook D16 RLEF-X
<ul>
<li>Intel Iris Xe Graphics</li>
<li>Intel Core i5-12500H</li>
<li>12</li>
<li>16 ГБ</li>
<li>16'</li>
<li>76.299</li>
<li>[Link]</li>
</ul>
</li>
<li>Ультрабук HUAWEI MateBook D 15 BoM-WFQ9
<ul>
<li>AMD Radeon Graphics</li>
<li>AMD Ryzen 5 5500U</li>
<li>6</li>
<li>16 ГБ</li>
<li>15.6'</li>
207
<li>62.999</li>
<li>[Link]</li>
</ul>
</li>
<li>Ноутбук MSI GF76 Katana 11SC-483XRU
<ul>
<li>GeForce GTX 1650</li>
<li>Intel Core i5-11400H</li>
<li>6</li>
<li>8 ГБ</li>
<li>17.3'</li>
<li>59.399</li>
<li>[Link]</li>
</ul>
</li>
</ol>
На основе списка составьте массив объектов. Каждый объект имеет
следующий набор ключей:
title;
gpu;
cpu;
pu_cores;
ram;
diagonal;
price;
img.
Ключи перечислены в порядке упоминания в списке. Выведите
созданный массив объектов в консоль. Результат вывода представлен на
рисунке.
208
Практическая работа 23
СПЕЦИАЛЬНЫЕ ЦИКЛЫ
Содержание
Стань 1. Разница между специальными
циклами
профессионалом! 2. Цикл for … in
3. Цикл for … of
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
ПРИМЕР 1
<script>
// инициируем массив
let arr = [3, "php", [2, 9]];
// цикл for-in перебирает !-ключи-!
for (let i in arr) {
[Link](i); // 0, 1, 2
}
[Link]("---------------");
// цикл for-of перебирает !-значения-!
for (let i of arr) {
[Link](i); // 3, "php", [2, 9]
}
</script>
Параметры:
variable – очередное имя свойства, назначается переменной на каждой
итерации.
object – объект, по чьим свойствам проходим в цикле.
209
ПРИМЕР 2
<script>
// инициируем объект
let order = {
id: 61,
title: "Утепленная стеганая куртка",
brand: "MARCO DI RADI",
colour: "Синий",
country: "Китай",
hood: "Есть",
size: "52",
price: 25.590,
image: "[Link]"
};
// инициируем переменную
out = '<ul>';
// цикл for-in перебирает !-ключи-!
for (key in order) {
out += `<li>${key}: ${order[key]}</li>`;
}
out += '</ul>';
// выведем в документ результат работы цикла
[Link]("#content").innerHTML = out;
</script>
В следующем примере создадим более читаемый вывод объекта. Для
этого преобразуем значения ключей объекта из строкового типа в массив.
ПРИМЕР 3
<script>
let order =
{
id : ["Номер",1],
title : ["Название","Утепленная стеганая куртка"],
brand : ["Бренд","MARCO DI RADI"],
colour : ["Цвет","Синий"],
country : ["Страна","Китай"],
hood : ["Капюшон","Есть"],
size : ["Размер","52"],
price : ["Цена",25.590],
image: ["Путь","images/[Link]"]
};
// инициируем переменную
out = '<ul>';
// цикл for-in перебирает !-ключи-!
for (key in order) {
out += `<li>${order[key][0]} - ${order[key][1]}</li>`;
}
out += '</ul>';
// выведем в документ результат работы цикла
[Link]("#content").innerHTML = out;
</script>
210
Упорядочение свойств объекта
Свойства упорядочены особым образом: свойства с целочисленными
ключами сортируются по возрастанию, остальные располагаются в порядке
создания.
Термин целочисленное свойство означает строку, которая может быть
преобразована в целое число и обратно без изменений.
Разберёмся подробнее. В качестве примера рассмотрим объект с
автомобильными кодами регионов России в качестве ключей.
Автомобильные коды идут в порядке возрастания, потому что они
являются целыми числами. Не целочисленные ключи перебираются в
порядке создания.
ПРИМЕР 4
<script>
// инициируем объект
let regions = {
"country": "Россия",
"40": "Калужская область",
"33": "Владимирская область",
"34": "Волгоградская область",
"23": "Краснодарский край",
"31": "Белгородская область",
"11": "Республика Коми",
"explanation": "Автомобильные коды регионов",
"note": ""
};
// перебираем ключи объекта
for (key in regions) {
[Link](key + "<p>");
}
</script>
211
Параметры:
variable – на каждом шаге итерации variable присваивается значение
нового свойства объекта iterable. Переменная variable может быть также
объявлена с помощью const, let или var.
iterable – объект, перечисляемые свойства которого обходятся во время
выполнения цикла.
Конструкция for..of помогает избежать сложностей и большого
количества логики, делая код более чистым и читаемым.
Перебор символов строки циклом for ... of
Пример использование цикла for...of для посимвольного перебора
строки.
ПРИМЕР 5
<script>
// переменная, содержащая строку
let str = 'Volgograd';
// посимвольный перебор строки
for (let char of str) {
[Link](char);
}
</script>
Перебор элементов массива циклом for ... of
ПРИМЕР 6
<script> // инициируем массив
/* let arr = [
программисту придется '135',
запоминать назначения индексов 'Toyota',
-> 'Toyota Land Cruiser',
0 - идентификатор 'Дизельный',
1 - бренд '249',
2 - модель 'V-образный',
3 - тип ДВС '4461',
4 - мощность л.с. '8'
5 - расположение цилиндров ];
6 - рабочий объем // открываем тег маркированного списка
7 - число цилиндров let html = `<ul>`;
*/ // for-of перебирает !-значения-!
for (let elem of arr) {
// значение массива в каждой итерации
[Link]("-> ", elem);
// оборачиваем значение в теги списка
html += `<li>${elem}</li>`;
}
// закрываем тег маркированного списка
html += `</ul>`;
// выводим список в браузер
[Link](html);
</script>
212
Перебор элементов двумерного массива
ПРИМЕР 7
<script>
// инициируем массив
// каждый вложенный массив представляет пару параметр-значение
let arr =
[
['Идентификатор','1'],
['Бренд', 'Toyota'],
['Модель', 'Toyota Land Cruiser'],
['Тип двигателя', 'Дизельный'],
['Мощность', '249'],
['Тип цилиндра', 'V-образный'],
['Объем двигателя', '4461'],
['Количество цилиндров', '8']
];
let html = "";
// цикл for-of перебирает !-значения-!
for (let item of arr) {
// на каждой итерации значением является массив
[Link]("-> ",item);
// формируем строку для вывода
html += `
<p>
${item[0]} - <strong>${item[1]}</strong>
</p>`;
}
// выводим сформированную строку в браузер
[Link](html);
</script>
Перебор элементов HTML коллекции циклом for ... of
Метод итератор у коллекции есть, а значит, на этот раз переберем
коллекцию HTML-элементов документа. Поработаем со списком
определений.
Список определений состоит из двух элементов — термина и его
определения. Сам список задается с помощью контейнера dl, термин —
тегом dt, а его определение — с помощью тега dd.
С версткой списка определений поработаем достаточно подробно в
следующих нескольких примерах демонстрационного кода.
ПРИМЕР 8
<h2>Словарь Web - Дизайнера</h2>
<dl>
<div>
<dt>Контент</dt>
<dd>Содержимое макета, которое не относится непосредственно к дизайну -
тексты, графика (фотографии, иконки, логотипы и иллюстрации), видео.</dd>
</div>
<div>
213
<dt>Композиция</dt>
<dd>Способ размещения всех элементов макета друг относительно друга.
Самые часто встречаемые виды композиции - центральная и боковая.</dd>
</div>
<div>
<dt>Навигация</dt>
<dd>Система ссылок, с помощью которых посетитель перемещается по
страницам. Стандартным элементом навигации являются меню.</dd>
</div>
</dl>
<script>
// получение коллекции определений
var elements = [Link]('dl > div');
// переменная для формирования строки
var line = "";
// цикл for-of перебирает !-значения-!
for (item of elements) {
// в item попал весь блок div
// выбор элемента dt
dt = [Link];
// формируем строку для вывода
line += `<li><a href="#">${[Link]}</a></li>`;
};
let html = `<h2>Динамический список определений</h2><ul> ${line} </ul>`;
// выводим список в браузер
[Link](html);
</script>
Если в предыдущем демонстрационном примере собрали термины
списка определений и вывели их в виде списка ссылок, то теперь запишем
термины в массив и выведем массив в консоль браузера.
ПРИМЕР 9
<script>
// получение коллекции определений
var elements = [Link]('dl > div');
// переменная для формирования строки
var line = "";
// массив хранения элементов
var arr = [];
// итератор цикла
var i = 0;
// цикл for-of перебирает !-значения-!
for (item of elements) {
// в item попал весь блок div
// выбор элемента dt
dt = [Link];
// записываем элемент в массив
arr[i] = [Link];
i++;
};
// вывод массива в консоль
[Link] (arr);
</script>
214
Вся информация хранится в таблицах баз данных (почти вся, за
редким исключением). Задача разработчика либо вывести данные таблицы в
браузер, либо собрать данные от пользователя (из браузера) для записи их в
базу данных. И в том, и в другом случае, сценарий выполняет
предварительный сбор обрабатываемых данных.
Удобно, если обрабатываемые данные будут иметь структуру, схожую
с табличным представлением баз данных. Таким образом, данные в сценарии
могут представляться либо в виде массива массивов:
let arr = [
[1, "Утепленная стеганая куртка", "MARCO DI RADI", "Синий", "Китай", "52",
"25.590"],
[2, "Пальто", "Allsaints", "Коричневый", "Китай", "50", "53.990"],
[ ... ]
];
Либо в виде массива объектов:
let arr2 = [
{
id: 1,
title: "Утепленная стеганая куртка",
brand: "MARCO DI RADI",
colour: "Синий",
country: "Китай",
size: "52",
price: "25.590"
},
{
id: 2,
title: "Пальто",
brand: "Allsaints",
colour: "Коричневый",
country: "Китай",
size: "50",
price: "53.990"
},
{ ... }
];
Имея сложные структуры данных, встает вопрос о наиболее
эффективном способе переборе элементов этой структуры операторами
циклов.
В JavaScript существуют следующие операторы цикла:
for используется, когда вы заранее знаете, сколько раз вам нужно что-
то сделать;
while используется, когда вы не знаете, сколько раз нужно что-то
сделать;
do ... while работает аналогично с оператором while. Отличается тем,
что do...while всегда выполняет выражение в фигурных скобках, по крайней
мере один раз, даже если проверка условия возвращает false.
215
for ... of используется для обхода итерируемых объектов (строк,
коллекций, массивов и некоторых других);
for ... in используется для обхода свойств объектов.
Если вы работает с объектами все очень просто, цикл, перебирающий
свойства объекта for...in.
Если вы работаете со строками, массивами или HTML-коллекциями,
вариантов немного больше:
for...of – основной оператор обхода строк, массивов и HTML-
коллекций, подойдет в большинстве случаев;
for – если по какой-то причине не подошел первый способ или вам
нужны индексы элементов. Равноправен с первым способом, используется
очень часто;
while – если не подошли первые два способа (что маловероятно);
do...while – вряд ли будете использовать, в JS используется редко.
А теперь практикуем сохранение коллекции HTML-элементов в
двумерный массив.
Сохранение данных в двумерный массив
ПРИМЕР 10
<h2>Словарь Web - Дизайнера</h2>
…
<script>
// получение коллекции определений
var elements = [Link]('dl > div');
// переменная для формирования строки
var line = "";
// массив хранения элементов
var arr = [];
// итератор цикла
var i = 0;
// цикл for-of перебирает !-значения-!
for (item of elements) {
// ! не забудьте указать, что значением массива будет другой массив
arr[i] = [];
// выбор элемента dt
dt = [Link]("dt");
// выбор элемента dd
dd = [Link]("dd");
// заполняем вложенный массив
arr[i][0] = [Link];
arr[i][1] = [Link];
i++;
};
// вывод массива в консоль
[Link] (arr);
</script>
216
Сохранение данных в массив объектов
ПРИМЕР 11
<script>
// получение коллекции определений
var elements = [Link]('dl > div');
// переменная для формирования строки
var line = "";
// массив хранения элементов
var arr = [];
// итератор цикла
var i = 0;
// цикл for-of перебирает !-значения-!
for (item of elements) {
// инициируем объект
obj = {};
// выбор элемента dt
dt = [Link]("dt");
// выбор элемента dd
dd = [Link]("dd");
// создаем свойства объекта
[Link] = [Link];
[Link] = [Link];
// записываем объект в массив
arr[i] = obj;
i++;
};
// вывод массива в консоль
[Link] (arr);
</script>
Список определений из массива объектов
ПРИМЕР 12
<script>
// инициируем массив объектов
let arr =
[
{dt: 'Контент', dd: 'Содержимое макета, которое не относится
непосредственно к дизайну - тексты, графика (фотографии, иконки, логотипы и
иллюстрации), видео.'},
{dt: 'Композиция', dd: 'Способ размещения всех элементов макета друг
относительно друга. Самые часто встречаемые виды композиции - центральная и
боковая.'},
{dt: 'Навигация', dd: 'Система ссылок, с помощью которых посетитель
перемещается по страницам. Стандартным элементом навигации являются
меню.'},
]
[Link]("<dl>");
for (item of arr) {
[Link] (
`
<div>
<dt>${[Link]}</dt>
217
<dd>${[Link]}</dd>
</div>
`
);
}
[Link]("</dl>");
</script>
Список определений из двумерного массива
ПРИМЕР 13
<script>
// инициируем двумерный массив
let arr =
[
['Контент', 'Содержимое макета, которое не относится непосредственно к
дизайну - тексты, графика (фотографии, иконки, логотипы и иллюстрации),
видео.'],
['Композиция', 'Способ размещения всех элементов макета друг относительно
друга. Самые часто встречаемые виды композиции - центральная и боковая.'],
['Навигация', 'Система ссылок, с помощью которых посетитель перемещается
по страницам. Стандартным элементом навигации являются меню.'],
]
[Link]("<dl>");
for (item of arr) {
[Link] (
`
<div>
<dt>${item[0]}</dt>
<dd>${item[1]}</dd>
</div>
`
);
}
[Link]("</dl>");
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Вам предложено определение объекта teams:
let teams =
{
id: 1,
name: "Aerosmith",
alias: "aerosmith",
country: "США",
content: "Группа Aerosmith ...",
date: 1970,
style: "хард-рок",
link: "[Link]
}
218
Используя цикл for...in загрузите данные объекта в текстовые элементы
input формы. Сделайте так, чтобы:
ключи объекта стали значением атрибута name;
значения ключей объекта стали значением атрибута value.
<input type="text" name="{key}" value="{value}">
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №23 - Задание
№2» вам предложены файлы:
[Link] – основной файл приложения;
[Link] – файл данных в виде массива объектов;
images – директория хранения файлов изображений.
Подключите файл данных к основному файлу приложения. Используя
цикл for...of выведите в браузер данные массива объектов.
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №23 - Задание
№3» вам предложен файл [Link]. Каждая цитата представляет из себя
заголовок уровня h3 с тегом span, содержащим информацию об авторе
данной цитаты.
Пример заголовка представлен ниже.
<h3>Убежденность, что ваша работа необычайно важна, — верный
симптом приближающегося нервного срыва <span> (Бертран Рассел)
</span></h3>
Соберите заголовки в массив объектов. Каждый вложенный в массив
объект должен иметь два ключа: citate, author.
Выведите полученный массив в консоль браузера
219
Практическая работа 24
ВЛОЖЕННЫЕ ЦИКЛЫ
Содержание
1. Обработка коллекций вложенными
Стань циклами
2. Обработка сложных структур
профессионалом! вложенными циклами
3. Обработка файлов текстовых
форматов
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Циклы можно вкладывать один внутри другого, при этом первый цикл
называется внешним циклом, второй цикл называется вложенным
(внутренним).
При каждой итерации внешнего цикла, вложенный цикл выполняется
полностью.
ПРИМЕР 1
<script>
// внешний цикл for
for (var i = 1; i < 4; i++) {
// вывод переменной внешнего цикла - i
[Link](i + ". Строка ВНЕШНЕГО цикла<p>");
// внутренний цикл for
for (var k = 1; k < 5; k++) {
// вывод переменной внутреннего цикла - k
[Link](" " + k + " - Строка
ВЛОЖЕННОГО цикла<p>");
}
}
</script>
Переменные внешнего цикла доступны внутри вложенного цикла.
ПРИМЕР 2
<script>
// внешний цикл for
for (var i = 1; i < 4; i++) {
// i - переменная внешнего цикла
// внутренний цикл for
for (var k = 1; k <= 10; k++) {
// k - переменная внутреннего цикла
// выводим произведение переменных i * k
[Link](i + " * " + k + " = " + i * k, "<br/>" );
220
}
// вывод по завершении внутреннего цикла
[Link]("<hr><p>");
}
</script>
При организации вложенных циклов позволительна любая комбинация
циклических конструкций. В примере 3 для организации вывода используем
две конструкции while.
ПРИМЕР 3
<script>
// инициируем переменную внешнего цикла
let i = 1;
while (i < 5) {
// инициируем переменную внутреннего цикла
let k = 1;
while (k <= 10) {
// выводим произведение переменных i * k
[Link](i + " * " + k + " = " + i * k, "<br/>" );
k++; // инкремент внутренней переменной
}
// вывод по завершении внутреннего цикла
[Link]("<hr><p>");
i++; // инкремент внешней переменной
}
</script>
В примере 4 внешний цикл использует конструкцию while, вложенный
– конструкцию.
ПРИМЕР 4
<script>
// инициируем переменную внешнего цикла
let i = 1;
while (i < 5) {
for (k=1; k <= 10; k++) {
// выводим произведение переменных i * k
[Link](i + " * " + k + " = " + i * k, "<br/>" );
}
// вывод по завершении внутреннего цикла
[Link]("<hr><p>");
i++; // инкремент внешней переменной цикла
}
</script>
221
ПРИМЕР 5
<h3>Топ лучших смартфонов 2024 <script>
года</h3> // получение коллекции элементов
<div id="top"> var elements =
<ol> [Link]('top').firstElementChild.c
<li>VIVO X100 Pro</li> hildren;
<li>iPhone 15 Pro Max</li> // количество элементов коллекции
<li>Apple iPhone 13 mini</li> let len = [Link];
<li>Samsung Galaxy S23 Ultra</li> // вывод в цикле for
<li>ASUS Zenfone 10</li> for (var el of elements) {
<li>Xiaomi 13T Pro</li> [Link] ([Link], "<br/>");
<li>Find N3 Flip</li> }
<li>Google Pixel 8</li> </script>
<li>Huawei P70 Art</li>
</ol>
</div>
<hr>
ПРИМЕР 6
<h3>Дискография группы Pink <script>
Floyd</h3> // получение коллекции строк таблицы
<table border=1> let elements = [Link]('tr');
<tr> // количество элементов коллекции
<td>1</td> let len = [Link];
<td>Atom Heart Mother</td> // инициируем переменные
<td>10 октября 1970</td> let i = 0; // итератор цикла
<td>EMI, Harvest, Capitol</td> let arr = []; // одномерный массив для
<td>Золотой (USA)</td> хранения табличных данных
</tr> // цикл while
<tr> while (i < len) {
<td>2</td> // получаем коллекцию элементов td для
<td>Meddle</td> каждой строки tr
<td>30 октября 1971</td> let td = [Link](i).children;
<td>EMI, Harvest, Capitol</td> // значением i-го элемента массива будет -
<td>Платиновый (USA)</td> массив
</tr> arr[i] = [];
<tr> // цикл for
<td>3</td> for (j=0; j<[Link]; j++) {
<td>Obscured by Clouds</td> arr[i][j] = [Link](j).innerHTML;
<td>3 июня 1972</td> }
<td>EMI, Harvest, Capitol</td> // переход к следующей строке таблицы
<td>Золотой (USA), Серебряный i++; // приращение итератора цикла
(GBR)</td> }
</tr> [Link](arr);
</table> </script>
222
Сохранение вложенного списка в массив
В примере 7 обработаем и сохраним в массив данные вложенного
списка.
<h3>Лучшие книги — рейтинг Топ 100</h3>
<ol>
<li>Гарри Поттер и узник Азкабана
<ul>
<li>Джоан Роулинг</li>
<li>978-389-17021-6</li>
<li>2019</li>
<li>Махаон</li>
</ul>
</li>
<li>Зелёная миля
<ul>
<li>Стивен Кинг</li>
<li>978-5-17-085348-9</li>
<li>2014</li>
<li>АСТ</li>
</ul>
</li>
<li>Унесенные ветром
<ul>
<li>Маргарет Митчел</li>
<li>978-5-17-122888-0</li>
<li>2020</li>
<li>АСТ</li>
</ul>
</li>
</ol>
За элементами списка li первого уровня следует вложенный список
элементов списка li второго уровня (ul). Это значит, что для обработки
коллекции может понадобиться вложенный цикл. Для наглядности
выполним пошаговый анализ обработки элементов коллекции на каждом
этапе кодирования.
Запись в массив названий книг
ПРИМЕР 7_1
<script>
// массив хранения списка
var arr = [];
// получение HTML-коллекции элементов li
let elements = [Link]('ol > li');
// убедитесь, понимаете ли вы, какая коллекция отобрана
// [Link](elements);
// цикл for по элементам коллекции
for (var i = 0; i < [Link]; i++) {
// текстовый узел - название фильма
223
[Link] (elements[i].[Link]);
arr[i] = elements[i].[Link];
};
[Link]("Массив хранения списка");
[Link](arr);
</script>
На каждой итерации по элементам исходной коллекции выбираем
элементы li вложенного списка. Выполняем цикл по элементам вложенного
списка.
Получение данных вложенного списка
ПРИМЕР 7_2
<script>
// массив хранения списка
var arr = [];
// получение HTML-коллекции элементов li
let elements = [Link]('ol > li');
// цикл for по элементам коллекции
for (var i = 0; i < [Link]; i++) {
arr[i] = elements[i].[Link];
// выбираем ul > li вложенного списка на каждой итерации
list = elements[i].[Link];
// цикл по элементам li вложенного списка
for(var k = 0; k < [Link]; k++){
// выводим каждый вложенный элемент li
[Link](list[k].[Link]);
}
// разделитель между вложенными элементами ul
[Link]("----------");
};
[Link]("Массив хранения списка");
[Link](arr);
</script>
Обратите внимание, на то, каким образом формируется основной
массив и на обнуление вложенного подмассива на каждой итерации по
коллекции внешнего списка.
Сохранение вложенного списка в массив
ПРИМЕР 7_3
<script>
// массив хранения списка
var arr = [];
// получение HTML-коллекции элементов li внешнего списка
let elements = [Link]('ol > li');
// цикл for по элементам коллекции
for (i = 0; i < [Link]; i++) {
// массив хранения вложенного списка объявлен внутри цикла,
// потому, что ->
// для каждого вложенного списка должен быть свой массив subarr
var subarr = [];
224
arr[i] = [];
// первый элемент подмассива - скалярное значение
// -> Название книги
arr[i][0] = elements[i].[Link];
// выбираем ul > li вложенного списка на каждой итерации
list = elements[i].[Link];
// цикл по элементам li вложенного списка
for(k = 0; k < [Link]; k++){
// собираем в массив каждый вложенный элемент li
subarr[k] = list[k].[Link];
}
// второй элемент подмассива - тоже массив
// -> Элементы вложенного списка
arr[i][1] = subarr;
};
[Link]("Массив хранения списка");
[Link](arr);
</script>
Таким образом выполняется обработка вложенных данных, не
обязательно коллекций, это могут быть любые структурированные данные.
Какова бы ни была сложность структуры, алгоритм обработки от этого не
меняется.
Посмотрим на обрабатываемый циклом фрагмент HTML разметки еще
раз. Характеристика вложенного списка:
количество пунктов списка везде одинаково,
последовательность перечисления одинаково,
данные каждого пункта списка - простая строка,
данные атомарны и неделимы (делимость имени автора не учитываем).
Посмотрим, можно ли обойтись без усложнения кода
дополнительными циклическими конструкциями.
ПРИМЕР 8
<script>
// массив хранения списка
var arr = [];
// получение HTML-коллекции элементов li внешнего списка
let elements = [Link]('ol > li');
// цикл for по элементам коллекции
for (i = 0; i < [Link]; i++) {
// массив хранения вложенного списка объявлен внутри цикла,
// потому, что ->
// для каждого вложенного списка должен быть свой массив subarr
var subarr = [];
arr[i] = [];
// первый элемент подмассива - скалярное значение
// -> Название книги
arr[i][0] = elements[i].[Link];
// выбираем ul > li вложенного списка на каждой итерации
list = elements[i].[Link];
// избавились от вложенного цикла
225
// иногда так легче читается код и больше маневра для верстки
subarr[0] = list[0].[Link];
subarr[1] = list[1].[Link];
subarr[2] = list[2].[Link];
subarr[3] = list[3].[Link];
// второй элемент подмассива - тоже массив
// -> Элементы вложенного списка
arr[i][1] = subarr;
};
[Link]("Массив хранения списка");
[Link](arr);
</script>
ПРИМЕР 9
let arr = [ <h3>Дискография группы Pink Floyd</h3>
[ <div id="data"></div>
"1", <script>
"Atom Heart Mother", let data = [Link]("data");
"10 октября 1970", let list = "";
"EMI, Harvest, Capitol", for (let i = 0; i < [Link]; i++) {
"Золотой (USA)", // в список первого уровня забрали
], // arr[i][0] - идентификатор альбома
[ // arr[i][1] - название альбома
"2", list += `<li>${arr[i][1]} (id = ${arr[i][0]})</li>`;
"Meddle", // инициируем переменные для вложенного
"30 октября 1971", цикла
"EMI, Harvest, Capitol", // так как индексы 0 и 1 ушли в список первого
"Платиновый (USA)" уровня
], // начинаем счет с индекса - 2
[ let j = 2;
"3", let subList = "";
"Obscured by Clouds", // в этот раз используем цикл do (совсем не
"3 июня 1972", обязательно)
"EMI, Harvest, Capitol", do {
"Золотой (USA), Серебряный subList += `<li>${arr[i][j]}</li>`;
(GBR)" j++;
], }
]; while (j < arr[i].length);
list += `<ul>${subList}</ul>`;
}
[Link]('afterbegin',
`<ol>${list}</ol>`);
</script>
226
При динамическом обходе свойств объектов удобно использовать
альтернативный доступ к свойствам объекта через квадратные скобки.
Квадратные скобки позволяют обратиться к свойству, имя которого может
быть результатом выражения. Например, имя свойства может храниться в
переменной.
ПРИМЕР 10
<script>
let user = {
name: "John",
login: "master",
age: 30
};
//
[Link]([Link]); // John
[Link]([Link]); // master
[Link]("----------");
// динамическое формирование ключа
let key = "name";
[Link]([Link]); // undefined
[Link](user[key]); // John
</script>
В большинстве случаев, когда имена свойств известны используется
запись через точку. Если же нам нужно что-то более сложное, то мы
используем квадратные скобки.
ПРИМЕР 11
let courses =
[
{"id": 1, "name": "JavaScript разработчик с нуля" , "time": "7 месяцев", "shedule":"По
будним дням 13:00-15:00", "level": "Junior", "teacher":"Данилов В.Е.", "price":40000},
{"id": 2, "name": "Python-рузработчик" , "time": "12 месяцев", "shedule":"По будним
дням 12:00-15:00", "level": "Middle", "teacher":"Ливанов Б.В.", "price":55000},
{"id": 3, "name": "Data Scientist" , "time": "10 месяцев", "shedule":"По выходным
18:00-20:00", "level": "Junior", "teacher":"Вавилов Н.И.", "price":48000},
];
<script>
var tbody = "";
// перебор объектов массива courses
for (obj of courses) {
let str = "";
// перебор ключей объекта
for (key in obj) {
str += `<td>${obj[key]}</td>`;
}
// [Link](obj);
// формируем строки таблицы
tbody += `<tr>${str}</tr>`;
}
// формируем контент страницы
let content = `
<table border=1>
227
<tr>
<th>ID</th>
<th>Название</th>
<th>Время обучения</th>
<th>Расписание</th>
<th>Уровень</th>
<th>Преподаватель</th>
<th>Цена</th>
</tr>
${tbody}
</table>`;
[Link](`${content}`);
</script>
ПРИМЕР 12
// строка формата CSV <div id="console"></div>
let data = <script>
`1;Aerosmith;aerosmith;США;1970 // разбиваем исходную строку построчно в массив
;хард-рок;assets/[Link] // разделителем является символ переноса строк '\n'
2;Pink Floyd;pink- let groups = [Link]("\n");
floyd;Великобритания;1965;психо // [Link](groups);
делический-рок;assets/pink- let arr = [];
[Link] i = 0;
3;Ленинград;ленинград;Россия;1 for (line of groups) {
997;ска, фолк, // разбиваем каждый элемент массива groups в
панк;assets/[Link]`; массив
// разделителем является символ ';'
arr[i] = [Link](";");
i++;
}
[Link](arr);
</script>
228
Управление циклом
Метка представляет собой оператор с идентификатором, который
позволяет ссылаться на какое-то место в программе.
Вы можете использовать метку, чтобы обозначить цикл, а затем
использовать операторы break или continue, чтобы указать, должна ли
программа прерывать цикл или продолжать его выполнение.
Синтаксис:
myLabel: {
statement;
}
Именем метки может быть любой корректный JavaScript
идентификатор, не являющийся зарезервированным словом. Оператор,
указанный вами после метки, может быть любым выражением.
Пример использования метки:
myLabel: while (condition) {
if (condition 2) {
break myLabel;
}
}
Вызов break myLabel приведёт к выходу из цикла, перед которым
указана метка myLabel.
Если метка используется с ключевым словом continue, то в этом случае
выполнение этого действия приведёт к немедленному переходу к следующей
итерации цикла, перед которым данная метка указана.
В примере ниже вызов оператора break и оператора с меткой break
inner приведет к одному и тому же эффекту – выход из ближайшего
(внутреннего) цикла.
ПРИМЕР 13
<script>
// метка внешнего цикла
outer:
for(var i = 0; i <= 3; i++) {
// метка внутреннего цикла
inner:
for(var j = 0; j <= 3; j++) {
// каждый раз при j > 3 внутренний цикл будет прерываться
// if (j > 3) break; // выход из внутреннего цикла
// аналогично, но с использованием метки inner:
if (j > 3) break inner // выход из внутреннего цикла
[Link]("i = " + i + "; j = " + j + "<br>");
}
} // end for
229
// первая инструкция после цикла for
// всегда выполнится
[Link]("<hr>FINAL i = " + i + "; j = " + j + "<br>");
</script>
Вот теперь вызов оператора с меткой приведет не просто к выходу из
цикла, а к выходу из указанного меткой цикла.
Прерывание выполнения внешнего цикла
ПРИМЕР 14
<script>
// метка внешнего цикла
outer:
for(var i = 0; i <= 3; i++) {
// метка внутреннего цикла
inner:
for(var j = 0; j <= 3; j++) {
if (i == 2) break outer; // выход из внешнего цикла
[Link]("i = " + i + "; j = " + j + "<br>");
}
} // end outer:for
// первая инструкция после цикла outer:for
// всегда выполнится
[Link]("<hr>FINAL i = " + i + "; j = " + j + "<br>");
</script>
И в последнем примере метка outer обозначает конструкцию – блок {}.
А это значит, что оператор с меткой break outer приведет к выходу из всего
блока.
Прерывание выполнения блока кода
ПРИМЕР 15
<script>
// метка внешнего цикла
// поместим инструкции внешней метки в блок {} (!)
outer: {
for(var i = 0; i <= 3; i++) {
// метка внутреннего цикла
inner:
for(var j = 0; j <= 3; j++) {
if (i == 2) break outer; // выход из внешней метки outer:
[Link]("i = " + i + "; j = " + j + "<br>");
}
} // end outer:for
// теперь эта инструкция не выполнится
[Link]("<hr>FINAL i = " + i + "; j = " + j + "<br>");
} // конец блока кода
</script>
Операторы break и continue нельзя использовать в выражениях
тернарных операторов.
230
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №24 - Задание
№1» вам предложен файл [Link]. Сценарий файла выполняет сбор и
запись в массив названий книг из предложенного вложенного списка.
Обратите внимание, в названии книг присутствуют управляющие
символы переноса строки и табуляции ("\n\t\t\t"). Происхождение символов
вызвано имеющейся версткой вложенного списка.
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №24 - Задание
№2» вам предложен файл [Link] и подключенный к нему файл данных
CSV формата [Link].
Файл CSV имеет следующую структуру:
ID;
Название;
Цена;
GPU;
CPU;
Количество ядер;
RAM;
OC (Операционная система);
231
Диагональ;
Тип экрана;
Цвет;
Описание.
Напишите сценарий, выполняющий обработку и вывод в браузер
содержимого файла [Link]. Вывод организовать в виде табличного
представления данных.
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №24 - Задание
№3» вам предложены следующие файлы:
images – директория хранения файлов изображений;
[Link] – основной файл приложения;
[Link] – файл хранения массива данных товаров.
Ознакомьтесь со структурой массива файла [Link]. Напишите
скрипт вывода данных массива в браузер. Примерный формат вывода
представлен на рисунке.
Обратите внимание на текст атрибута title изображения.
232
Практическая работа 25
ОБРАБОТКА ОШИБОК
Содержание
Стань 1. Исключения
2. Объект ошибок
профессионалом! 3. Генерация собственных ошибок
4. Проброс исключения
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Синтаксическая конструкция try...catch позволяет ловить ошибки и
вместо падения делать что-то более осмысленное.
Синтаксис:
try…catch
Конструкция try...catch состоит из двух основных блоков: try, и затем
catch, но может использоваться только с одним, обязательным блоком try.
try { try_statements
// основной код
} [catch(err) {
catch_statements
// обработка ошибки
}][finally {
finally_statements
// завершающий код
}]
Параметры:
try_statements - код для выполнения и контроля над генерируемыми
им исключениями.
catch_statements - все исключения будут попадать в блок
catch_statements.
err - переменная, которой присваивается пойманное исключение.
Переменной можно давать любое имя.
finally_statements - блок finally_statements будет выполнен после
окончания работы try...catch, вне зависимости от того, было ли сгенерировано
исключение
Если детали ошибки вас не интересуют, то аргумент при вызове catch
можно пропустить:
try{
// ...
}catch{ // <- без (err)
// ...
}
233
Конструкция try...catch в JavaScript может быть представлена в своей
полной форме, включая необязательную секцию finally.
Допускается использование всех трех форм:
try...catch
try...finally
try...catch...finally
Работает конструкция следующим образом:
1. Сначала выполняется код внутри блока try {...}.
2. Если в нём нет ошибок, то блок catch(err) игнорируется: выполнение
доходит до конца try и потом далее, полностью пропуская catch.
3. Если же в нём возникает ошибка, то выполнение try прерывается, и
поток управления переходит в начало catch(err). Переменная err (можно
использовать любое имя) содержит объект ошибки с подробной
информацией о произошедшем.
Таким образом, при ошибке в блоке try {…} скрипт не падает, и мы
получаем возможность обработать ошибку внутри catch.
ПРИМЕР 1
<script>
try {
// объявляем переменные
let name, login;
// инициируем переменные
name = "Карим";
login = "admin";
// ошибка, переменная -> logim <- не определена
let user = `${name} (${logim})`;
} catch {
// сообщение о возникшем исключении
234
alert(`Возникла ошибка!`);
}
</script>
В следующем примере последние две инструкции блока try никогда не
выполнятся (ну, то есть до тех пор, пока не будет исправлена опечатка).
ПРИМЕР 2
<script>
try {
[Link] ('Начало блока try');
// объявляем переменные
let name, login;
// ошибка, переменная -> logim <- не определена
let user = `${name} (${login})`;
[Link] ('Конец блока try (никогда не выполнится)');
alert ("Как жалко, что мы никогда не встретимся...");
} catch {
// сообщение о возникшем исключении
alert(`Возникла ошибка!`);
}
</script>
Исключения
try...catch работает только для ошибок, возникающих во время
выполнения кода. Чтобы try...catch работал, код должен быть выполнимым.
Другими словами, это должен быть корректный JavaScript-код.
Он не сработает, если код синтаксически неверен, например,
содержит несовпадающее количество открывающих скобок:
// JS движок не прочитает такой файл,
// файл синтаксически некорректен
try {
[Link] (('В коде присутствует лишняя скобка');
// ...
} catch {
// ...
}
JavaScript-движок сначала читает код, а затем исполняет его. Ошибки,
которые возникают во время фазы чтения кода, называются ошибками
парсинга.
Их нельзя обработать (изнутри этого кода), потому что движок не
понимает код.
В примере ниже все таже неопределенная переменная (logim), но код в
секции catch не сработает, возникла ошибка парсинга.
ПРИМЕР 3
<script>
try {
[Link] ('Начало блока try');
235
// объявляем переменные
let name, login;
// ошибка, переменная -> logim <- не определена
let user = `${name} (${login})`;
[Link] ('Конец блока try');
// ошибка, опечатка в ключевом слове catch
} cath {
// сообщение о возникшем исключении не возникнет
alert(`Возникла ошибка!`);
}
</script>
Исключения не возникло. Возникла синтаксическая ошибка.
ПРИМЕР 4
<script>
236
try {
let name, login;
// место генерирования объекта ошибки
let user = `${name} (${logim})`;
// имя может быть любым
} catch(err) {
[Link]("Тип ошибки: ", typeof err); // object
// можем вывести ошибку
// ошибка типа object приводится к строке
[Link]("Сообщение: ", err); // ReferenceError: logim is not defined
}
</script>
В следующем примере выводим свойства объекта ошибки.
ПРИМЕР 5
<script>
try {
let name, login;
// место генерирования объекта ошибки
let user = `${name} (${logim})`;
} catch(error) {
[Link]("Свойства ошибки:");
[Link]("Свойство name: ", [Link]); // ReferenceError
[Link]("Свойство message: ", [Link]); // logim is not defined
[Link]("Свойство stack: ", [Link]); // ReferenceError: logim is not
defined
}
</script>
JavaScript поддерживает метод [Link]() для чтения JSON данных.
Обычно он используется для декодирования данных, полученных по сети, от
сервера или из другого источника.
Вызываем метод [Link]() для чтения и преобразования данных в
JS объект.
ПРИМЕР 6
<script>
// такие данные могли прийти с сервера
// свойство age не обернуто кавычками
let json = '{"name":"John",age:30}';
// преобразуем текстовое JSON-представление в JS-объект
let user = [Link](json);
// хотим получить JS-объект user со свойствами name и age
[Link]([Link]); // John
[Link]([Link]); // 30
</script>
Если JSON некорректен, [Link] генерирует ошибку, то есть
скрипт падает.
237
Пренебрежение конструкцией обработки ошибок, дает рухнувший
скрипт с выводом сообщения синтаксической ошибки (SyntaxError) в консоль
(плюс потеря вами репутации адекватного программиста*).
ПРИМЕР 7
<script>
try {
// такие данные могли прийти с сервера
let json = '{"name":"John",age:30}';
// преобразуем текстовое JSON-представление в JS-объект
let user = [Link](json);
// user - JS-объект со свойствами name и age
[Link]([Link]); // John
[Link]("<br>");
[Link]([Link]); // 30
} catch(err){
// возможно не имеет смысла посвящать во все тонкости пользователя,
// поэтому ему достаточно и такого сообщения
alert( "Извините, при получении данных произошла ошибка.\nВиновные
будут приговорены к тюремным срокам!");
// а вот веб-разработчику куда полезнее окажется эта информация
[Link] ("Ошибка (" + [Link] + "): " + [Link]);
}
</script>
Здесь мы используем блок catch только для вывода сообщения, но
разработчик может сделать гораздо больше: отправить новый сетевой запрос,
предложить попробовать получить данные позже, обозвать пользователя
неудачником ... *
ПРИМЕР 8
<script>
try {
// данные с сервера
let json = '{"name":"John","age":30}';
// преобразуем текстовое JSON-представление в JS-объект
let user = [Link](json);
// user - JS-объект со свойствами - name и age
// и отсутствующим свойством - login
[Link]([Link]); // John
[Link]([Link]); // 30
[Link]([Link]); // ???
} catch(err){
// хорошо бы получить ошибку, но синтаксически все верно и ошибки не
будет
[Link] ("Ошибка (" + [Link] + "): " + [Link]);
}
</script>
Здесь [Link] выполнится без ошибок, но на самом деле
отсутствие свойства login для нашего приложения ошибка.
ПРИМЕР 9
<script>
// ошибка типа Error
239
let error = new Error("Шеф, все пропало, все пропало!!! Гипс снимают, клиент
уезжает!");
[Link]([Link]); // Error
[Link]([Link]); // Шеф, все пропало ...
// ошибка типа SyntaxError
let syntaxError = new SyntaxError("Все на выход. Сохраняйте спокойствие. Или
паникуйте и кричите, уже не важно.");
[Link]([Link]); // SyntaxError
[Link]([Link]); // Все на выход. Сохраняйте спокойствие ...
// ошибка типа ReferenceError
let referenceError = new ReferenceError("Приказ избегать паники отменяется!
Пусть все сидят по домам и боятся!");
[Link]([Link]); // ReferenceError
[Link]([Link]); // Приказ избегать паники отменяется ...
</script>
Ошибку мало создать, ее необходимо вызвать (генерировать). Для того
чтобы вызвать объект ошибки, воспользуемся оператором throw.
Оператор throw
Оператор throw генерирует ошибку указанного типа.
Синтаксис:
throw <объект_ошибки>
Генерировать ошибку можно, например, так:
ПРИМЕР 10
<script>
// создаем объект ошибки типа Error
let error = new Error("Шеф, все пропало, все пропало!!! Гипс снимают, клиент
уезжает!");
// генерируем ошибку
throw error;
// чтобы увидеть это сообщение закомментируйте вызов throw
[Link]("Не будет выведено, в случае генерирования ошибки");
</script>
Код может быть короче, если совместить процесс создания и
генерирова генерирования ошибки, например так:
// создаем и вызываем объект ошибки типа Error
throw new Error("Шеф, все пропало, все пропало!!! Гипс снимают, клиент
уезжает!");
или так
// создаем и вызываем объект ошибки типа SyntaxError
throw new SyntaxError("Все на выход. Сохраняйте спокойствие. Или паникуйте
и кричите, уже не важно.");
Для встроенных ошибок (не для любых объектов, только для ошибок):
свойство name – имя конструктора,
свойство message – значение аргумента.
Например:
240
let myError =new ReferenceError("Приказ избегать паники отменяется! Пусть все
сидят по домам и боятся!");
// [Link] – ReferenceError
// [Link] – "Приказ избегать паники отменяется! Пусть все сидят по
домам и боятся!"
Как итог, создадим сценарий с вызовом и обработкой ошибки
отсутствия свойства login в полученных данных.
ПРИМЕР 11
<script>
try {
// данные с сервера
let json = '{"name":"John","age":30}';
// преобразуем текстовое JSON-представление в JS-объект
let user = [Link](json);
// user - JS-объект со свойствами - name и age
[Link]("Начинаем выводить свойства объекта:");
[Link]([Link]); // John
[Link]([Link]); // 30
// свойство login может отсутствовать
// поэтому проверяем его особо
if ([Link]){
[Link]([Link]);
} else {
// генерируем ошибку типа Error со свойством message
throw Error ("Упс. Что-то пошло не так...");
}
} catch(err){
// ситуация, когда ошибка скорее хорошо, чем плохо
// выводим информацию о сгенерированной ошибке
[Link] ([Link] + ". ", [Link]);
[Link] ("Ошибка обработки JSON данных.");
}
</script>
Технически в качестве объекта ошибки можно передать что угодно.
Это может быть пользовательский объект или даже примитив: число или
строка, но всё же лучше, чтобы это был объект, желательно со свойствами
name и message (для совместимости со встроенными ошибками).
ПРИМЕР 12
<script>
try {
if (0){
// ...
} else {
// вместо объекта стандартной ошибки - строка
throw "Упс. Что-то пошло не так ...";
}
} catch(err){
// вывод сообщения ошибки
[Link](err);
}
241
</script>
Вместо объекта стандартной ошибки - число
ПРИМЕР 13
<script>
try {
if (0){
// ...
} else {
// вместо объекта стандартной ошибки - число
throw 555;
}
} catch(err){
// вывод информации об ошибки
[Link](err);
}
</script>
Вместо объекта стандартной ошибки – пользовательский объект
ПРИМЕР 14
<script>
// пользовательский объект ошибки
let objErr = {
name: "UserError",
message: "Упс. Что-то пошло не так ...",
description: "Пользовательский объект ошибки"
}
try {
if (0){
// ...
} else {
// вместо объекта стандартной ошибки - пользовательский объект
throw objErr;
}
} catch(err){
// вывод информации об ошибке
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
}
</script>
Проброс исключений
В примерах выше мы использовали конструкцию try...catch для
обработки ошибок, происхождение которых нам было хорошо известно.
А что, если в блоке try {...} возникнет другая неожиданная ошибка?
Например, программная (неопределённая переменная) или какая-то
ещё.
242
По своей природе catch получает все свои ошибки из try. И если он
получает неожиданную ошибку, но показывает заранее подготовленное
сообщение, например: "Ошибка парсинга JSON строки", то такое поведение
неправильно и только затрудняет отладку кода.
Можно выяснить, какую ошибку получили, например, по её свойству
name. При этом надо понимать, что синтаксическая (SyntaxError) ошибка
может появиться не только вследствие преобразования JSON-строки, также
как и ошибка – ReferenceError результат не только отсутствующего свойства
login.
ПРИМЕР 15
<script>
try {
// данные с сервера
let json = '{"name":"John","age": 30}';
// возможная ошибка преобразования данных
let user = [Link](json);
// возможная ошибка отсутствия данных
if (![Link]){
throw ReferenceError ("Неполные данные сервера");
}
/*
код, в котором возможно появление других ошибок
*/
} catch(err){
if ([Link] == "SyntaxError") {
[Link] ([Link] + ". Ошибка преобразования данных");
} else if ([Link] == "ReferenceError") {
[Link] ([Link] + ". " + [Link]);
// если это неизвестная ошибка, пробросим ее дальше
} else
throw err;
}
</script>
В коде примера выше секция catch обрабатывает только те ошибки,
происхождение которых нам известно: SyntaxError или ReferenceError.
243
Ошибки, происхождение которых нам неизвестно, пробрасываем дальше,
такая техника обработки ошибок называется пробросом исключения.
ПРИМЕР 16
<h2>О сколько нам открытий чудных…</h2>
<script>
try {
// программа проявляет чудеса толерантности
if (confirm("Вы хотите получить ошибку?")){
// ну, если пользователь так хочет ...
244
throw Error("Ошибка на ровном месте... :-(");
} else {
// жить без ошибок - здорово!
alert ("Спасибо, вы настоящий друг!");
}
} catch(err){
// вывод информации об ошибке
[Link]("Пользователь тешится ;)");
[Link]([Link] + ": " + [Link]);
// следующий блок выполнится в любом случае
} finally {
// красивые стихи уместны всегда
let msg = `
<pre><h2>
О сколько нам открытий чудных
Готовят просвещенья дух
И Опыт, сын ошибок трудных,
И Гений, парадоксов друг,
И Случай, бог изобретатель.</h2>
(Александр Пушкин)
</pre>`;
// вывод сообщения в браузер
[Link](msg);
}
</script>
У кода есть два пути выполнения:
Если вы утвердительно ответите на вопрос: «Вы хотите получить
ошибку?», то try -> catch -> finally.
Если ответите отрицательно, то try -> finally.
Секцию finally часто используют, когда мы начали что-то делать и
хотим завершить это вне зависимости от того, будет ошибка или нет.
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №25 - Задание
№1» вам предложен файл данных JSON формата [Link]. Изучите
структуру данных файла.
Используя конструкцию try-catch и любой из циклических
операторов выведите данные JSON-формата в браузер. Данные об альбоме
группы могут быть выведены с помощью вложенного цикла.
Обратите внимание, строка JSON-формата содержит ошибки.
Выведите в консоль ошибки преобразования формата в JS-объект. По итогам
вывода найдите и исправьте ошибки формирования строки.
245
ЗАДАНИЕ 2
Ссоздайте пользовательский объект ошибки со следующими
свойствами:
name: "AuthenticationError";
message: "Ошибка входа в систему";
description: "Неверный логин и/или пароль".
Используя диалоговое окно prompt() запросите у пользователя логин и
пароль. Если логин или пароль не соответствуют аутентификационным
данным сгенерируйте пользовательскую ошибку.
Примерный вывод ошибки в консоль представлен на скриншоте
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №25 - Задание
№3» вам предложены исходные файлы и каталоги для выполнения задания.
[Link] – основной файл приложения;
[Link], [Link] – целевые файлы для перехода по ссылкам
из файла [Link];
[Link] – файл данных, содержащий объект ответа сервера;
[Link] – стилевой файл.
Для выполнения практической работы, выполните следующий набор
действий.
В файле [Link]:
изучите структуру объекта ответа сервера.
В сценарии файла [Link]:
подключите файл данных [Link];
получите доступ и выведите в браузер данные ключей объекта:
o code - код бронирования;
o cost - стоимость бронирования;
протестируйте переход по ссылкам на страницы [Link],
[Link];
Примерный формат вывода данных представлен на скриншоте.
246
В сценарии файла [Link]:
подключите файл данных [Link];
используя любой из операторов цикла выведите в браузер данные
ключа flights;
Примерный формат вывода данных представлен на скриншоте.
247
Практическая работа 26
МАССИВЫ
Содержание
Стань 1. Общая информация о массивах
2. Одномерные массивы
профессионалом! 3. Многомерные массивы
4. Стек и очередь
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Массив (Array) – это специальная структура данных, которая
предназначена для хранения значений упорядоченных коллекций.
Массивы очень полезны и очень часто используются в коде, т.к.
позволяют хранить набор значений в одной переменной.
Значения массива называются элементами. Каждый элемент в массиве
имеет свой порядковый номер (индекс). Первый элемент массива имеет
индекс 0, второй – 1, третий – 2 и т.д.
248
его. При объявлении массива его можно сразу инициализировать
начальными значениями. Для этого внутрь скобок необходимо поместить
элементы, отделив их друг от друга запятой:
// инициализация массива при объявлении c помощью литерала
let lang = ["javaScript", "php", "perl", "python"];
// инициализация массива при объявлении с помощью конструктора
let lang = new Array ("javaScript", "php", "perl", "python");
Если конструктору Array() передать один аргумент, который является
числом, то он создаст массив с указанным количеством элементов. Значения
элементов при этом будут неопределёнными (пустыми)
let arr = new Array(3);
[Link](arr) // [ , , ]
ПРИМЕР 1
<script>
// объявляем массив
// инициализируем массив начальными значениями
// литерал
var film = ["Зеленая миля", "Криминальное чтиво", "Форрест Гамп"];
// конструктор
let books = new Array("Чемодан", "Зона", "Соло на IBM")
// выводим данные массивов
[Link](film);
[Link](books);
</script>
ПРИМЕР 2
<script>
// объявляем массив
// инициализируем массив начальными значениями
249
var film = ["Зеленая миля", "Криминальное чтиво", "Форрест Гамп"];
// обновляем элемент массива
film[2] = "Общество мертвых поэтов";
// добавляем элементы в массив
film[3] = "Бойцовский клуб";
film[4] = "Умница Уилл Хантинг";
film[5] = "Побег из Шоушенка";
// выводим обновленные данные массива
[Link](film);
</script>
Если при добавлении элемента случайно пропустить индекс, то в
массиве появится неопределенный элемент undefined:
let lang = ["javaScript","php","perl","python"];
lang[5] = "visual basic";
[Link](lang[4]); // undefined
alert(lang); // вывести массив целиком можно при помощи alert
При попытке получить доступ к несуществующему элементу также
получим undefined:
let lang =new Array ("Doors","Aerosmith","Creedence");
[Link]( lang[3]); // undefined
Совсем необязательно, чтобы все элементы массива имели один и тот
же тип данных. Элементами могут быть любые значения – даже другие
массивы. Это позволяет создавать сложные структуры данных, например,
массивы массивов или массивы объектов.
В приведенном ниже примере не нужно погружаться в изучение
объектов или функций, необходимо уяснить – элементами массива может
быть все что угодно.
ПРИМЕР 3
<script>
// массив может хранить значения разного типа
// 0 – строка
// 1 – объект
// 2 – boolean
// 3 - функция
// 4 - другой массив
let arr = [ 'Яблоко', {name: 'Джон'}, true, function() {return('Привет');}, ['PHP',
'JavaScript'] ];
// получить элемент с индексом 1 (объект),
// затем показать его свойство
alert( arr[1].name ); // Джон
// получить элемент с индексом 3 (функция) и выполнить её
alert(arr[3]()); // Привет
// получить элемент с индексом 4 (массив)
// затем вывести его второй элемент
alert(arr[4][1]); // JavaScript
</script>
250
Различают одномерные и двумерные массивы. Одномерный массив –
это список переменных, двумерный массив – таблица, имеющая строки и
столбцы.
Элементы одномерного массива обозначаются одним индексом, он
определяет порядковый номер элемента в массиве (как элемент имеет свой
номер в списке). Элементы двумерного массива обозначаются двумя
индексами (как ячейка обозначается номером строки и столбца).
Одномерные массивы
Одномерный массив — структура данных, хранящая набор значений
(элементов массива), идентифицируемых по индексу, принимающему
значения из некоторого заданного непрерывного диапазона.
Одномерный массив можно рассматривать как реализацию
абстрактного типа данных — вектор.
Попробуем визуализировать одномерный массив в виде векторного
представления.
Пример вектора в объявлении одномерного массива:
let albums =["Meddle", "Obscured by Clouds", "The Dark Side of the Moon"];
Это в самом простом случае. Но массив — это структура данных,
позволяющая хранить гораздо более информативные, а поэтому и более
сложные значения.
В случае с альбомами, набор значений для каждого элемента массива
может выглядеть, например, следующим образом:
// одномерный массив данных об альбомах группы PinkFloyd
let albums=[ "2; Meddle; 30 октября 1971; EMI, Harvest, Capitol; Vinyl,
Кассета, CD; Платиновый (USA)", "3; Obscured by Clouds; 3 июня 1972; EMI,
Harvest, Capitol; LP, Кассета, CD; Золотой (USA), Серебряный (GBR)", "4; The Dark
Side of the Moon; 17 марта 1973; Harvest, Capitol, EMI; LP, Кассета, CD, SACD;
Платиновый (USA), Платиновый (GBR), Бриллиантовый (CAN)" ];
Каждое значение такого элемента массива описывает набор свойств
определенного альбома.
Многомерные массивы
Двумерный массив
Таблица — это структура, хранящая информацию о совокупности
объектов, которые имеют схожие характеристики.
Таблица состоит из одной или множества строк, каждая строка
содержит информацию об одном объекте реального мира.
Преобразуем векторное представление в двумерную таблицу. В
приведенной двумерной таблице каждая строка представляет набор данных
об одном альбоме. Представить получившуюся таблицу можно с помощью
переменной двумерного массива:
251
// объявление двумерного массива
let albums=[ ["2; Meddle; 30 октября 1971; EMI, Harvest, Capitol; Vinyl,
Кассета, CD; Платиновый (USA)"],
["3; Obscured by Clouds; 3 июня 1972; EMI, Harvest, Capitol; LP, Кассета, CD;
Золотой (USA), Серебряный (GBR)"],
["4; The Dark Side of the Moon; 17 марта 1973; Harvest, Capitol, EMI; LP,
Кассета, CD, SACD; Платиновый (USA), Плати-новый (GBR), Бриллиантовый
(CAN)"] ];
Двумерный массив — это одномерный массив (внешний массив),
элементами которого являются одномерные массивы (вложенные массивы).
Другими словами, это набор структурированных данных, имеющих общее
имя, в которых доступ к элементам осуществляется по двум индексам.
Первый индекс идентифицирует номер вложенного массива, второй
индекс - номер элемента текущего массива.
ПРИМЕР 4
<script>
let albums =
[
["2; Meddle; 30 октября 1971; EMI, Harvest, Capitol; Vinyl, Кассета, CD;
Платиновый (USA)"],
["3; Obscured by Clouds; 3 июня 1972; EMI, Harvest, Capitol; LP, Кассета, CD;
Золотой (USA), Серебряный (GBR)"],
["4; The Dark Side of the Moon; 17 марта 1973; Harvest, Capitol, EMI; LP,
Кассета, CD, SACD; Платиновый (USA), Платиновый (GBR), Бриллиантовый (CAN)"]
];
// исходный массив albums
[Link]("Исходный массив: ");
[Link](albums);
// второй вложенный массив
[Link]("Второй вложенный массив: ");
[Link](albums[1]);
// первый элемент второго вложенного массива
[Link]("Первый элемент второго вложенного массива: ");
[Link](albums[1][0]); // пример неатомарных данных
</script>
В приведенном примере каждый элемент массива представляет из себя
текстовый набор разнотипных значений и не является атомарным. Это
значит, что в наборе текстовых символов затруднительно получить доступ,
например, к названию, дате выхода или статусу альбома.
Атомарность данных - важное понятие из теории разработки
реляционных баз данных. Данные ячеек таблицы должны быть семантически
неделимы. Это значит, что в проектируемой базе данных не должно быть
столбца ФИО, должны быть столбцы: Фамилия, Имя, Отчество. Тоже
самое относительно столбцов: Адрес, Паспортные данные и некоторых
других.
252
Атомизация данных упрощает обработку данных, но приводит к
усложнению структуры. Как правило, это приводит к увеличению
размерности массива.
Теория реляционных баз данных предполагает, что в таблицах хранятся
данные об объектах реального мира. Каждый объект представляется
определенным набором свойств (атрибутов). Каждое свойство должно быть
атомарно, и иметь значение определенного типа.
Тогда данные об альбомах, трансформируются из строкового
литерала:
["2; Meddle; 30 октября 1971; EMI, Harvest, Capitol; Vinyl, Кассета, CD;
Платиновый (USA)"],
к атомарному представлению:
[2, "Meddle", "30 октября 1971", "EMI, Harvest, Capitol", "Vinyl, кассета, CD",
"Платиновый (USA)"];
Заменим каждое вхождение альбома во вложенном массиве атомарным
представлением:
let albums=[
[2, "Meddle", "30 октября 1971", "EMI, Harvest, Capitol", "Vinyl, Кассета, CD",
"Платиновый (USA)"],
[3, "Obscured by Clouds", "3 июня 1972", "EMI, Harvest, Capi-tol", "LP, Кассета,
CD", "Золотой (USA), Серебряный(GBR)"],
[4, "The Dark Side of the Moon", "17 марта 1973", "Harvest, Capitol, EMI", "LP,
Кассета, CD, SACD", "Платиновый (USA), Платиновый (GBR), Бриллиантовый
(CAN)"]
];
Таким образом, получим двумерный массив albums, который можно
представить в виде следующей таблицы:
EMI, Harvest, Vinyl, Кассета,
2 Meddle 30 октября 1971 Платиновый (USA)
Capitol CD
Obscured by EMI, Harvest, LP, Кассета, Золотой (USA),
3 3 июня 1972
Clouds Capi-tol CD Серебряный(GBR)
Платиновый (USA),
The Dark Side of Harvest, LP, Кассета Платиновый (GBR),
4 17 марта 1973
the Moon Capitol, EMI CD, SACD Бриллиантовый
(CAN)
ПРИМЕР 5
<script>
let albums =
[
[2, "Meddle", "30 октября 1971", "EMI, Harvest, Capitol", "Vinyl, Кассета, CD",
"Платиновый (USA)"],
[3, "Obscured by Clouds", "3 июня 1972", "EMI, Harvest, Capitol", "LP, Кассета,
CD", "Золотой (USA), Серебряный (GBR)"],
[4, "The Dark Side of the Moon", "17 марта 1973", "Harvest, Capitol, EMI", "LP,
Кассета, CD, SACD", "Платиновый (USA), Платиновый (GBR), Бриллиантовый
(CAN)"]
253
];
[Link]("Название альбома: ");
[Link](albums[1][1]); // пример атомарных данных
</script>
Иногда массивы объектов – лучшее решение. По мере того, как
заполняется массив, код может стать всё менее поддерживаемым. Один из
способов структурирования данных – использовать вложенные объекты.
ПРИМЕР 6
<script>
let albums =
[
{
id: 2,
name: "Meddle",
date: "30 октября 1971",
label: "EMI, Harvest, Capitol",
format: "Vinyl, Кассета, CD",
status: "Платиновый (USA)"
},
{
id: 3,
name: "Obscured by Clouds",
date: "3 июня 1972",
label: "EMI, Harvest, Capitol",
format: "LP, Кассета, CD",
status: "Золотой (USA), Серебряный (GBR)"
},
{
id: 4,
name: "The Dark Side",
date: "17 марта 1973",
label: "Harvest, Capitol, EMI",
format: "LP, Кассета, CD, SACD",
status: "Платиновый (USA), Платиновый (GBR), Бриллиантовый (CAN)"
}
];
with(albums[1]) {
[Link](`
<pre>
id: ${id},
Название: ${name},
Дата выхода: ${date},
Лейбл: ${label},
Формат: ${format},
Статус: ${status}
</pre>
`);
}
</script>
Вообще, в массивах и объектах можно хранить разные структуры
данных. Для лучшей масштабируемости кода вам практически всегда
нужна будет комбинация из нескольких структур:
254
массивы внутри объектов;
объекты внутри массивов;
массивы внутри массивов;
объекты внутри объектов.
Выбирая структуру данных, помните, объекты внутри внешнего
массива – классическая структура реляционных баз данных.
Как получаются многомерные массивы
Еще раз обратим внимание на атомарность данных, хранящихся в
массиве. Допустим, в своем распоряжении мы имеем двумерный массив,
представленный следующей таблицей.
id name date label format status
EMI, Harvest, Vinyl, Кассета,
2 Meddle 30 октября 1971 Платиновый (USA)
Capitol CD
Obscured by EMI, Harvest, LP, Кассета, Золотой (USA),
3 3 июня 1972
Clouds Capi-tol CD Серебряный(GBR)
Платиновый (USA),
The Dark Side Harvest, LP, Кассета Платиновый (GBR),
4 17 марта 1973
of the Moon Capitol, EMI CD, SACD Бриллиантовый
(CAN)
Harvest, LP, 8-track, Платиновый (USA),
Wish Vou Were
5 15 сентября 1975 EMI, Кассета CD, Золотой (GBR),
Here
Capitol SACD Платиновый (CAN)
Простой анализ данных показывает, что столбцы id, name, date –
имеют простой (скалярный) тип данных. Значения в этих столбцах
атомарны.
Тогда как столбцы label, format, status содержат перечисляемые
значения. Данные этих столбцов не атомарны. Это значит, что получить
доступ к статусу альбома "The Dark Side of the Moon" в Великобритании не
так-то просто, придется разбирать строковое значение.
Выходом является дальнейшее усложнение структуры массива.
Во избежание подобных ситуаций такие значения принято
представлять в виде массива, теперь уже массива третьего уровня. Заменим
значения строкового литерала неатомарных столбцов вложенным
массивом третьего уровня.
Для трехмерного массива, необходимо три индекса для выбора
элемента.
ПРИМЕР 7
<script>
let albums =
[
[
2,
"Meddle",
"30 октября 1971",
255
["EMI", "Harvest", "Capitol"],
["Vinyl", "Кассета", "CD"],
["Платиновый (USA)"]
],
[
3,
"Obscured by Clouds",
"3 июня 1972",
["EMI", "Harvest", "Capitol"],
["LP", "Кассета", "CD"],
["Золотой (USA)", "Серебряный (GBR)"]
],
[
4,
"The Dark Side of the Moon",
"17 марта 1973",
["Harvest", "Capitol", "EMI"],
["LP", "Кассета", "CD", "SACD"],
["Платиновый (USA)", "Платиновый (GBR)", "Бриллиантовый (CAN)"]
]
];
[Link](`
<pre>
id: ${albums[2][0]},
Название: ${albums[2][1]},
Дата выхода: ${albums[2][2]},
Лейбл: ${albums[2][3][0]}, ${albums[2][3][1]}, ${albums[2][3][2]}
Формат: ${albums[2][4][0]}, ${albums[2][4][1]}, ${albums[2][4][2]},
${albums[2][4][3]}
Статус: ${albums[2][5][0]}, ${albums[2][5][1]}, ${albums[2][5][2]}
</pre>
`);
</script>
Статус альбома "Meddle" имеет строковое скалярное значение, тем не
мене он так же должен быть в массиве. Структура данных объектов должна
быть одинакова.
Стек и очередь
Две из наиболее часто используемых структур данных в веб-разработке
— это стеки и очереди.
Очередь – один из самых распространённых вариантов применения
массива. В области компьютерных наук так называется упорядоченная
коллекция элементов, поддерживающая два вида операций:
push – добавляет элемент в конец;
shift – удаляет элемент в начале, сдвигая очередь, так что второй
элемент становится первым.
256
На практике необходимость в этом возникает очень часто. Например,
очередь сообщений, которые надо показать на экране.
Другой вариант применения для массивов – структура данных,
называемая стек.
Стек поддерживает два вида операций:
push – добавляет элемент в конец.
pop – удаляет последний элемент.
ПРИМЕР 8
<script>
// инициировали массив альбомов группы Pink Floyd
let albums = ["Atom Heart Mother", "Meddle"];
// добавим в конец массива новый элемент
[Link]("Obscured by Clouds");
// добавим два элемента
[Link]("The Dark Side of the Moon", "Animals");
// последний элемент удалим и сохраним в переменной
let el = [Link]();
// выведем результат
[Link]("Массив: ", albums);
[Link]("Удаленный элемент: ", el);
</script>
Методы push и pop в многомерных массивах.
ПРИМЕР 9
<script> [
// инициировали массив альбомов 7,
группы Pink Floyd "The Wall",
var albums = [ "30 ноября 1979",
[ "Harvest, EMI, Columbia, Capitol",
2, "LP, 8-track, кассета, CD",
"Meddle", "Платиновый (USA), Платиновый
"30 октября 1971", (GBR), Бриллиантовый (CAN)"
"EMI, Harvest, Capitol", ]
258
"Vinyl, кассета, CD", ];// выведем исходный массив
"Платиновый (USA)" [Link]("Исходный массив: ",
], albums);
[ // добавим в конец массива новый
3, элемент
"Obscured by Clouds", [Link]([
"3 июня 1972", 5,
"EMI, Harvest, Capitol", "Wish You Were",
"LP, кассета, CD", "15 сентября 1975",
"Золотой (USA), Серебряный "Harvest, EMI, Columbia, Capitol",
(GBR)" "LP, 8-track, кассета, CD, SACD",
], "Платиновый (USA), Золотой (GBR),
[ Платиновый (CAN)"
4, ]);
"The Dark Side", // добавили в массив элемент
"17 марта 1973", [Link]("Исходный массив + новый
"Harvest, Capitol, EMI", элемент: ", albums);
"LP, кассета, CD, SACD", // добавим два элемента
"Платиновый (USA), [Link](newAlbum[0], newAlbum[1]);
Платиновый (GBR), Бриллиантовый // выведем обновленный массив
(CAN)" [Link]("Обновленный массив: ",
] albums);
]; // последний элемент удалим и
var newAlbum = [ сохраним в переменной
[ let el = [Link]();
6, // выведем результирующий массив
"Animals", [Link]("Результирующий массив: ",
"23 января 1977", albums);
"Harvest, EMI, Columbia, [Link]("Этот массив был удален: ",
Capitol", el);
"LP, 8-track, кассета, CD", </script>
"Платиновый (USA), Золотой
(GBR), Платиновый (CAN)"
],
ПРИМЕР 10
<script>
// инициируем массив
let albums = ["Меркурий", "Венера"];
// добавим в начало массива новый элемент
[Link]("Земля");
// добавим в начало еще три элемента
259
[Link]("Плутон", "Юпитер", "Сатурн");
// первый элемент удалим и сохраним в переменной
let el = [Link]();
// выведем результат
[Link]("Массив: ", albums);
[Link]("Удаленный элемент: ", el);
</script>
Пример использования методов для многомерного массива.
ПРИМЕР 11
<script> // выведем исходный массив
// инициировали массив альбомов [Link]("Исходный массив: ",
группы Pink Floyd albums);
var albums = [ // добавим в начало массива новый
[ элемент
2, [Link]([
"Meddle", 1,
"30 октября 1971", "Atom Heart Mother",
"EMI, Harvest, Capitol", "10 октября 1970",
"Vinyl, кассета, CD", "EMI, Harvest, Capitol",
"Платиновый (USA)" "LP, CD",
], "Золотой (USA)"
[ ]);
3, // добавили в массив элемент
"Obscured by Clouds", [Link]("Исходный массив + новый
"3 июня 1972", элемент: ", albums);
"EMI, Harvest, Capitol", // добавим еще один элемент
"LP, кассета, CD", [Link](newAlbum);
"Золотой (USA), Серебряный // удалим первый элемент и сохраним его
(GBR)" в переменной
], let el = [Link]();
[ // выведем результирующий массив
4, [Link]("Результирующий массив: ",
"The Dark Side", albums);
"17 марта 1973", [Link]("Удаленный массив: ", el);
"Harvest, Capitol, EMI", </script>
"LP, кассета, CD, SACD",
"Платиновый (USA), Платиновый
(GBR), Бриллиантовый (CAN)"
]
];
var newAlbum = [
6,
"Animals",
"23 января 1977",
"Harvest, EMI, Columbia, Capitol",
"LP, 8-track, кассета, CD",
"Платиновый (USA), Золотой
(GBR), Платиновый (CAN)"
];
ПРИМЕР 12
<h2>Мудрые цитаты из Гарри Поттера <script>
(50 цитат)</h2> // получение коллекции элементов
<div id="citate"> абзацев
<p>Для высокоорганизованного let elements =
разума смерть – это очередное [Link]('div#citate p');
приключение.</p> // количество элементов коллекции
<p>Величие порождает зависть, let len = [Link];
зависть рождает зло, ложь – искры // инициируем переменные
зла.</p> let arr = [];
<p>Все, что мы теряем, обязательно к var i = 0;
нам вернется, только не всегда так, как // цикл while
мы ожидаем.</p> while (i < len) {
<p>Если не спросишь, никогда не // заполняем массив
узнаешь. Если знаешь, нужно лишь [Link]([Link](i).innerText);
спросить.</p> i++;
<p>Нельзя цепляться за мечты и сны, }
забывая о настоящем, забывая о своей // выводим массив в консоль
жизни.</p> [Link](arr);
</div> // доступ к одномерному массиву
через один индекс
[Link](arr[2]);
</script>
Запись в многомерный массив
Усложним задачу, сохраним табличные данные в двумерный массив.
Используем вложенную конструкцию цикла.
ПРИМЕР 13
<table border=1> <script>
<thead> // получение коллекции элементов
<tr> списка
<th>Компания</th> let tr = [Link]('table >
<th>Инвестиции (₽)</th> tbody > tr');
<th>Прибыль (₽)</th> // [Link](tr);
<th>Окупаемость</th> // количество элементов коллекции
<th>Количество точек</th> let len = [Link];
<th>Описание</th> // инициируем массив
</tr> let franchise = [];
</thead> // внешний цикл for
<tbody> for (let i=0; i < len; i++) {
<tr> franchise[i] = [];
<td>SmartyKids</td> td = [Link](i).querySelectorAll("td");
<td>750 000</td> // [Link](td);
<td>250 000</td> franchise[i] = [];
<td>6 месяцев</td> // вложенный цикл for
<td>303</td> for (k=0; k < [Link]; k++) {
<td>Smartykids - это бизнес // заполняем массив третьего
для людей, которым важно уровня
понимать, что их работа приносит franchise[i].push([Link](k).innerText);
261
пользу обществу.</td> }
</tr> }
<tr> // выводим массив в консоль
<td>Lil Ballerine</td> [Link](franchise);
<td>850 000</td> // доступ к двумерному массиву через
<td>500 000</td> два индекса
<td>3 месяца</td> [Link](franchise[1][0]);
<td>121</td> </script>
<td>Lil Ballerine – детская
школа балета. Уникальная школа с
авторскими методами обучения в
сочетании с традициями русской
школы балета.</td>
</tr>
</tbody>
</table>
И еще раз усложним задачу. Сохраним эти же табличные данные
теперь в трехмерный массив.
ПРИМЕР 14
<table border=1> <script>
<thead> // получение коллекции элементов списка
<tr> let tr = [Link]('table >
<th>Компания</th> tbody > tr');
<th>Инвестиции (₽)</th> // [Link](tr);
<th>Прибыль (₽)</th> // количество элементов коллекции
<th>Окупаемость</th> let len = [Link];
<th>Количество точек</th> // инициируем массив
<th>Описание</th> let franchise = [];
</tr> // внешний цикл for
</thead> for (let i=0; i < len; i++) {
<tbody> franchise[i] = [];
<tr> td = [Link](i).querySelectorAll("td");
<td>SmartyKids</td> // [Link](td);
<td>750 000</td> franchise[i].push([Link](0).innerText);
<td>250 000</td> franchise[i][1] = [];
<td>6 месяцев</td> // вложенный цикл for
<td>303</td> for (k=1; k < [Link]; k++) {
<td>Smartykids - это бизнес // заполняем массив третьего уровня
для людей, которым важно franchise[i][1].push([Link](k).innerText);
понимать, что их работа }
приносит пользу обществу.</td> }
</tr> // выводим массив в консоль
<tr> [Link](franchise);
<td>Lil Ballerine</td> // доступ к трехмерному массиву через три
<td>850 000</td> индекса
<td>500 000</td> [Link](franchise[1][1][4]);
<td>3 месяца</td> </script>
<td>121</td>
<td>Lil Ballerine – детская
школа балета. Уникальная школа
с авторскими методами обучения
в сочетании с традициями
русской школы балета.</td>
262
</tr>
</tbody>
</table>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Вам предложена таблица содержащая данные о ноутбуках. Составьте
на основе данных таблицы двумерный массив (массив массивов). Выведите
полученный массив в консоль браузера.
ID Название Экран Цвет Разрешение CPU RAM Накопитель
Ноутбук
Full HD Intel Celeron
1 DEXP 14 Cеребристый 4 Гб SSD 128 ГБ
(1920x1080) N4020
Aquilon
Ноутбук Intel Celeron
2 14 Cерый HD (1366x768) 4 Гб eMMC 64 ГБ
Irbis NB257 3350
Ноутбук Full HD
Intel Celeron
3 Digma EVE 14 Cерый (1920x1080) 4 Гб MMC 64 ГБ
N4020
14 C414
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №26 - Задание
№2» вам предложен файл данных [Link]. Используя методы push и
unshift, добавьте в массив информацию о ноутбуках.
Выведите полученный массив в документ в виде таблицы.
Примерный формат вывода представлен на скриншоте.
263
Практическая работа 2 7
Содержание
Стань
1. Методы массива
профессионалом! 2. Перебор массива
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Методы массива
isArray()
Массивы не являются отдельным типом данных языка JavaScript.
Массивы являются видом объектов.
[Link](typeof {}); // object
[Link](typeof []); // object
Но массивы являются неотъемлемой частью любого приложения,
поэтому существует специальный метод на проверку принадлежности
переменной массиву.
Метод isArray() возвращает true, если объект является массивом и
false, если он массивом не является.
Синтаксис:
[Link](obj);
obj - объект для проверки.
ПРИМЕР 1
<script>
// инициируем массив из смешанных элементов
let courses =[
{id: 1, name: "JavaScript разработчик с нуля", price: 40000},
[2, "Python-разработчик", "12 месяцев", 55000],
[3, "Data Scientist", 48000],
{id: 4, name: "Фронтенд-разработчик", price: 78000},
{id: 5, name: "Тестирование веб-приложений на Python", price: 40000},
{id: 6, name: "Разработчик C++", price: 126000},
[4, "Фронтенд-разработчик на JavaScript", 65000],
{id: 7, name: "Android-разработчик", price: 168000}
]
// переберем элементы внешнего массива
for (i=0; i < [Link]; i++) {
if ([Link](courses[i])) [Link](`Элемент ${i} - массив`);
}
</script>
264
concat()
Метод concat() — конкатенация массивов, возвращает новый массив,
состоящий из массива, на котором он был вызван, соединённого с другими
массивами и/или значениями, переданными в качестве аргументов.
Синтаксис:
[Link](arg1, arg2...);
arg1, arg2 – массивы и/или значения, соединяемые в новый массив.
Метод concat() создаёт новый массив, состоящий из элементов
массива, на котором он был вызван, за которыми по порядку следуют, для
каждого аргумента, все его элементы (если аргумент является массивом),
либо сам аргумент (если он массивом не является).
Метод concat() не изменяет исходный массив или любой из массивов,
переданных в аргументах, а вместо этого возвращает поверхностную копию,
содержащую копии тех элементов, что были объединены с исходными
массивами.
ПРИМЕР 2
<script>
// инициируем первый массив
let rus = ["Толстой", "Достоевский", "Набоков", "Чехов"];
[Link] ("Русская литература: ", rus);
// инициируем второй массив
let west = ["Шекспир", "Фолкнер", "Диккенс", "Флобер", "Остин"];
[Link] ("Западная литература: ", west);
// складываем массивы
let world = [Link](west, "Булгаков");
[Link] ("Мировое литературное наследие: ", world);
</script>
slice()
Метод slice() — создает новый массив из элементов исходного массива
с индексами указанного диапазона. Говоря другими словами - возвращает
подмассив указанного массива.
Синтаксис:
[Link]([begin[, end]]);
Параметры:
begin – необязательный. Индекс (счёт начинается с нуля), по которому
начинать извлечение.
Если индекс отрицательный, begin указывает смещение от
конца последовательности. Вызов slice(-2) извлечёт два
последних элемента последовательности.
Если begin не определён, slice() начинает работать с индекса 0.
Если begin больше длины последовательности вернётся пустой
массив.
265
end – необязательный. Индекс (счёт начинается с нуля), по которому
заканчивать извлечение. Метод slice() извлекает элементы с индексом
меньше end.
Если индекс отрицательный, end указывает смещение от конца
последовательности.
Если end опущен, slice() извлекает все элементы до конца
последовательности ([Link]).
Описание
Метод slice() не изменяет исходный массив, а возвращает новую
одноуровневую копию, содержащую копии элементов, вырезанных из
исходного массива.
ПРИМЕР 3
<script>
// инициируем исходный массив
var arr = new Array("php", "mysql", "laravel", "javaScript", ["css", "bootstrap"]);
// создаем подмассивы из исходного массива
let serv = [Link](0,3);
let client = [Link](3,);
// выводим полученные массивы
[Link] ("Изучаем серверные технологии: ", serv); // php, mysql, laravel
[Link] ("Изучаем клиентские технологии: ", client); // javaScript, [css,
bootstrap]
</script>
splice()
Метод splice() изменяет содержимое массива, удаляя существующие
элементы и/или добавляя новые. Метод используется для вставки и удаления
элементов из массива.
Синтаксис:
[Link](start[, deleteCount[, item1[, item2[, ...]]]]);
Параметры:
start – индекс, по которому начинает изменять массив. Если больше
длины массива, реальный индекс будет установлен на длину массива. Если
отрицателен, указывает индекс элемента с конца.
deleteCount – необязательный. Целое число, показывающее количество
старых удаляемых из массива элементов.
Если deleteCount равен 0, элементы не удаляются. В этом случае
вы должны указать как минимум один новый элемент.
Если deleteCount больше количества элементов, оставшихся в
массиве, начиная с индекса start, то будут удалены все элементы
до конца массива.
itemN – необязательные параметры. Добавляемые к массиву элементы.
Если вы не укажете никакого элемента, splice() просто удалит элементы из
массива.
266
Возвращаемое значение: массив, содержащий удалённые элементы.
Если будет удалён только один элемент, вернётся массив из одного элемента.
Если никакие элементы не будут удалены, вернётся пустой массив.
Если количество указанных вставляемых элементов будет отличным от
количества удаляемых элементов, массив изменит длину после вызова.
В следующем примере удалим три элемента и возвратим массив из
удалённых элементов.
ПРИМЕР 4
<script>
// инициируем исходный массив
var arr = new Array("php", "mysql", "laravel", "javaScript", "css", "bootstrap");
// удаляем и возвращаем три элемента, начиная с индекса 0
let trash = [Link](0,3);
[Link] ("Мы изучаем клиентские технологии: ", arr); // javaScript, css,
bootstrap
[Link] ("А это мы выбросили на помойку: ", trash); // php, mysql, laravel
[Link] ("... это шутка была ;)");
</script>
Метод splice() также может вставлять элементы без удаления, для
этого достаточно установить deleteCount в 0.
split()
Метод split() разбивает объект String на массив строк путём
разделения строки указанной подстрокой. Метод возвращает новый массив.
Синтаксис:
[Link]([separator[, limit]]);
Параметры:
separator – необязательный параметр. Указывает символы,
используемые в качестве разделителя внутри строки. Параметр separator
может быть как строкой, так и регулярным выражением.
limit – необязательный параметр. Целое число, определяющее
ограничение на количество найденных подстрок. Метод split() всё равно
разделяет строку на каждом сопоставлении с разделителем separator, но
обрезает возвращаемый массив так, чтобы он содержал не более limit
элементов.
ПРИМЕР 5
<script>
// инициируем строку
let strTags = " #PHP #JavaScript #CSS #MySQL";
// разобьем строку в массив
arr = [Link](" #");
// отбросим первый элемент из массива
arrTags = [Link](1, );
// конечный массив выведем в консоль
267
[Link] (arrTags);
</script>
Метод split с управляющим символом \n.
ПРИМЕР 6
<script>
// инициируем строку разделенную символом переноса строки: \n
let albums = `2; Meddle; 30 октября 1971; EMI, Harvest, Capitol; Vinyl, Кассета,
CD; Платиновый (USA),
3; Obscured by Clouds; 3 июня 1972; EMI, Harvest, Capitol; LP, Кассета, CD;
Золотой (USA), Серебряный (GBR),
4; The Dark Side of the Moon; 17 марта 1973; Harvest, Capitol, EMI; LP, Кассета, CD,
SACD; Платиновый (USA), Платиновый (GBR), Бриллиантовый (CAN)`;
// разобьем строку в массив
arr = [Link]("\n");
// вывод элементов массива
[Link] ("Элемент 0:", arr[0]);
[Link] ("Элемент 1:", arr[1]);
[Link] ("Элемент 2:", arr[2]);
</script>
join()
Метод join() — объединяет все элементы массива в строку.
Синтаксис:
[Link]([separator]);
Параметры:
separator – необязательный. Определяет строку, разделяющую
элементы массива. Если параметр не задан, элементы массива разделяются
запятой ','. Если разделитель - пустая строка, элементы массива ничем не
разделяются в возвращаемой строке.
Преобразует все элементы массива в строки и объединяет их в одну
большую строку. Элемент массива с типом undefined или null преобразуется
в пустую строку.
ПРИМЕР 7
<script>
// инициируем массив
let tags = new Array("PHP", "JavaScript", "CSS", "MySQL");
// преобразуем массив к строке
// 1.
[Link] ("-> ", [Link](", ")); // PHP, JavaScript, CSS, MySQL
// 2.
[Link] ("-> ", [Link](" ")); // PHP JavaScript CSS MySQL
// 3.
[Link] ("-> ", [Link]("\n")); // PHP\nJavaScript\nCSS\nMySQL
// 4.
let line = "#" + [Link](" #");
[Link] ("-> ", line) // #PHP #JavaScript #CSS #MySQL
</script>
268
delete()
Есть еще один метод для удаления элемента из массива. Так как
массивы – это особый тип объектов, то к ним можно применить метод
delete().
ПРИМЕР 8
<script>
// инициируем исходный массив
var arr = new Array("php", "матрешка", "javaScript", "балалайка", "css",
"революция");
// удаляем из массива лишнее
delete arr[1];
delete arr[3];
delete arr[5];
// удалили не сам элемент, удалили его значение
[Link] ("А осадочек остался... ", arr);
</script>
Элементы удалены, но количество элементов массива не изменилось.
Метод delete хорош для объектов, но для массивов мы обычно хотим, чтобы
оставшиеся элементы сдвинулись и заняли освободившееся место. Мы ждём,
что массив станет короче.
По этой причине оптимальнее использовать специальные методы.
Перебор массива
Ранее мы рассмотрели классические циклы и их разновидность –
специальные циклы for...of и for...in. Но массивы обладают еще рядом
методов, предназначенных специально для обхода его элементов. Эти
методы чрезвычайно полезны.
Метод forEach позволяет запускать функцию для каждого элемента
массива.
Синтаксис:
[Link](function(elem, index, array) {
// …
}
Параметры:
function(elem, index, array) – callback-функция, которая будет вызвана
для каждого элемента массива. Она принимает от одного до трёх аргументов:
elem – текущий обрабатываемый элемент в массиве.
index – необязательный. Индекс текущего обрабатываемого
элемента в массиве.
array – необязательный. Массив, по которому осуществляется
проход.
Благодаря возможности написания короткой версии callback-
функции синтаксис может быть записан следующим образом:
269
[Link] ((elem, index, array) => {
// ...
});
Метод forEach() выполняет функцию callback один раз для каждого
элемента, находящегося в массиве в порядке возрастания. Она не будет
вызвана для удалённых или пропущенных элементов массива. Однако, она
будет вызвана для элементов, которые присутствуют в массиве и имеют
значение undefined.
ПРИМЕР 9
<script>
// инициируем двумерный массив
let teams = new Array(
[1, "Aerosmith", "США", "1970", ["хард-рок", "блюз-рок", "рок-н-ролл", "глэм-
метал"]],
[2, "Pink Floyd", "Великобритания", "1965", ["психоделический-рок", "арт-рок",
"эйсид-рок", "прогрессивный-рок"]],
[3, "The Beatles", "Великобритания", "1960", ["рок", "рок-н-ролл", "поп", "хард-
рок"]],
[4, "AC/DC", "Австралия", "1973", ["хард-рок", "блюз-рок", "рок-н-ролл"]],
[5, "Scorpions", "ФРГ", "1965", ["хард-рок", "глэм-метал", "хеви-метал"]],
[6, "Ленинград", "Россия", "1997", ["рок", "ска", "фолк", "панк", "панк-рок"]]
);
let line = "";
// выполняем перебор элементов массива teams
[Link] ((item, index, teams) => {
line += `<li>${item[1]}</li>`;
})
// исходный массив
[Link](teams);
// вывод в браузер сформированного списка
[Link] ("<ul>", line, "</ul>");
</script>
Результат функции, если функция что-то возвращает, будет отброшен
и проигнорирован. Для возврата результата в функциях предусмотрено
ключевое слово return. Ключевое слово return завершает работу функции и
возвращает значение, которое является результатом вызова данной функции.
ПРИМЕР 10
<script>
// исходный массив объектов
let teams = new Array(
{id:1, name:"Aerosmith", country:"США", date:"1970", style:["хард-рок", "блюз-
рок", "рок-н-ролл", "глэм-метал"]},
{id:2, name:"Pink Floyd", country:"Великобритания", date:"1965",
style:["психоделический-рок", "арт-рок", "эйсид-рок", "прогрессивный-рок"]},
{id:3, name:"The Beatles", country:"Великобритания", date:"1960", style:["рок",
"рок-н-ролл", "поп", "хард-рок"]},
{id:4, name:"AC/DC", country:"Австралия", date:"1973", style:["хард-рок", "блюз-
рок", "рок-н-ролл"]},
270
{id:5, name:"Scorpions", country:"ФРГ", date:"1965", style:["хард-рок", "глэм-
метал", "хеви-метал"]},
{id:6, name:"Ленинград", country:"Россия", date:"1997", style:["рок", "ска",
"фолк", "панк", "панк-рок"]}
);
newArray = Array();
// результат метода forEach игнорируется
// в теле цикла массив teams доступен через переменную myArr
newArray = [Link] ((item, index, myArr) => {
// вычеркнем Британию из списка демократических стран
if ([Link] == "Великобритания") {
// заменим элемент исходного массива
myArr[index] = "There is no democracy in this country";
// что-то вернем (не важно что)
return [Link];
}
})
// заменили элементы массива текстовым значением
[Link](teams);
// метод не возвращает результат
[Link](newArray); // undefined
</script>
В теле функции forEach можно выполнять операции любой сложности.
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Вам предложен файл массивов данных:
let album1 = ["Atom Heart Mother; 10 октября 1970; EMI, Harvest, Capitol, LP,
CD; Золотой (USA)", "Meddle; 30 октябр я 1971; EMI, Harvest, Capitol; Vinyl,
кассета, CD; Платиновый (USA)"];
let album2 = ["Obscured by Clouds; 3 июня 1972; EMI, Harvest, Capitol; LP,
кассета, CD; Золотой (USA), Серебряный (GBR)", "The Dark Side of the Moon; 17
марта 1973; Harvest, Capitol; EMI, LP, кассета, CD, SACD; Платиновый (USA),
Платиновый (GBR), Бриллиантовый (CAN)"];
let album3 = ["Wish You Were Here; 15 сентября 1975; Harvest, EMI,
Columbia, Capitol; LP, 8-track, кассета, CD, SACD; Платиновый (USA), Золотой
(GBR), Платиновый (CAN)", "Animals; 23 января 1977; Harvest, EMI Columbia,
Capitol; LP, 8-track, кассета, CD; Платиновый (USA), Золотой (GBR), Платиновый
(CAN)"];
let album4 = ["The Wall; 30 ноября 1979; Harvest, EMI, Columbia, Capitol; LP,
8-track, кассета, CD; Платиновый (USA), Платиновый (GBR), Бриллиантовый
(CAN)", "The Final Cut; 21 марта 1983; Harvest, EMI, Columbia, Capitol; LP, 8-track,
кассета, CD; Платиновый (USA), Золотой (GBR)"];
let album5 = ["A Momentary Lapse of Reason; 8 сентября 1987; EMI, Columbia;
LP, кассета, CD; Платиновый (USA), Золотой (GBR), Платиновый (CAN)", "The
Division Bell; 30 марта 1994; EMI, Columbia, LP; кассета, CD; Платиновый (USA),
Платиновый (GBR), Платиновый (CAN)"];
Используя цепочку вызовов, объедините массивы. Выведите
результирующий массив в консоль браузера.
271
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №27 - Задание
№1» вам предложен файл данных [Link]. Подключите данные к шаблону
файла сценария. Напишите скрипт, выполняющий перебор элементов
массива courses. Сохраните вложенные массивы и вложенные объекты
массива courses в разные переменные.
Выведите результирующие массивы в консоль браузера.
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №27 - Задание
№1» вам предложен файл данных [Link]. Подключите данные к шаблону
файла сценария. Изучите объект ответа сервера. Напишите скрипт,
сохраняющий в массив данные о следующих рейсах:
1. flight_code = S7-1012
2. flight_code = S7-1012 или flight_code = F1201
Выведите массив в консоль браузера.
272
Практическая работа 28
Содержание
Стань
1. Поиск в массиве
профессионалом! 2. Преобразование массива
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Поиск в массиве
Если вам нужно найти позицию элемента или наличие элемента в
массиве, используйте методы indexOf() или includes() соответственно.
При изучении строк мы рассматривали методы поиска подстрок.
Среди прочих были методы includes и indexOf, но массивы содержат методы
с такими же названиями.
Таким образом, в коде программы равновероятно могут быть
следующие конструкции:
[Link](str);
[Link](str);
Внешне очень похоже, но работает это по-разному.
// массив из одной строки
let note = ["Acer Extensa 15 EX215-22-R8E3"];
// наличие подстроки в строке
[Link](note[0].includes("Acer")); // true
// наличие элемента в массиве
[Link]([Link]("Acer")); // false
Будьте внимательны, проверяйте, на каком объекте вызывается метод.
ПРИМЕР 1
<script>
// инициируем одномерный массив строк
let note = [
"Acer Extensa 15 EX215-22-R8E3",
"Asus VivoBook 15 OLED K513EA",
"HUAWEI MateBook D 15",
"Apple MacBook Air 13 2022" ];
// проверяем на вхождение в элементы массива подстроки -Asus-, выполняем
[Link]()
[Link](note[0].includes("Asus")); // false
[Link](note[1].includes("Asus")); // true
[Link](note[2].includes("Asus")); // false
[Link](note[3].includes("Asus")); // false
273
</script>
ПРИМЕР 2
<script>
// инициируем одномерный массив строк
let note1 = ["Acer", "Asus", "HUAWEI", "Apple"];
// проверяем на наличие в массиве note1 элемента -Asus-
// выполняем [Link]()
[Link]([Link]("Asus")); // true
// инициируем одномерный массив строк
let note2 = [
"Acer Extensa 15 EX215-22-R8E3",
"Asus VivoBook 15 OLED K513EA",
"HUAWEI MateBook D 15",
"Apple MacBook Air 13 2022"
];
// проверяем на наличие в массиве note2 элемента -Asus-
// выполняем [Link]()
// элемента -Asus- в массиве note2 нет
[Link]([Link]("Asus")); // false
</script>
Если нужно проверить вхождение подстроки в элементе воспользуемся
методом перебора элементов массива.
ПРИМЕР 3
<script>
// инициируем одномерный массив строк
let note = [
"Acer Extensa 15 EX215-22-R8E3",
"Asus VivoBook 15 OLED K513EA",
"HUAWEI MateBook D 15",
"Apple MacBook Air 13 2022"
];
// проверим каждый элемент массива на вхождение подстроки
[Link](elem => {
274
// выполняем [Link]()
[Link] ([Link]("Asus"));
});
</script>
Выбор способа поиска зависит от поставленной перед вами задачи.
indexOf()
Метод indexOf() возвращает индекс первого вхождения, по которому
данный элемент может быть найден в массиве или -1, если такого индекса
нет.
Синтаксис:
[Link](searchElem[, fromIndex = 0])
Параметры:
searchElement – искомый элемент в массиве.
fromIndex - индекс, с которого начинать поиск. Если индекс больше
или равен длине массива, возвращается -1, что означает, что массив даже не
просматривается. Если индекс является отрицательным числом, он
трактуется как смещение с конца массива.
Метод indexOf() сравнивает искомый элемент searchElem с
элементами в массиве, используя строгое сравнение (оператор = = =, тройное
равно).
ПРИМЕР 4
<script>
// инициируем одномерный массив строк
let note1 = ["Acer", "Asus", "HUAWEI", "Apple"];
// проверяем наличие элементов в массиве note1
// выполняем [Link]()
[Link]([Link]("Asus")); // 1
[Link]([Link]("Apple")); // 3
[Link]([Link]("Samsung")); // -1
// инициируем одномерный массив строк
let note2 = [
"Acer Extensa 15 EX215-22-R8E3",
"Asus VivoBook 15 OLED K513EA",
"HUAWEI MateBook D 15",
"Apple MacBook Air 13 2022"
];
// проверяем наличие элемента в массиве note2
// выполняем [Link]()
[Link]([Link]("VivoBook")); // -1
</script>
Как и в случае с методом includes() воспользуемся методом перебора
элементов массива.
ПРИМЕР 5
<script>
275
// инициируем одномерный массив строк
let note = [
"Acer Extensa 15 EX215-22-R8E3",
"Asus VivoBook 15 OLED K513EA",
"HUAWEI MateBook D 15",
"Apple MacBook Air 13 2022"
];
// проверим каждый элемент массива на вхождение подстроки
[Link](elem => {
// выполняем [Link]()
[Link] ([Link]("VivoBook"));
});
</script>
Методы includes() и indexOf() в многомерных массивах.
ПРИМЕР 6
<script>
// инициируем двумерный массив
let note = [
["Acer", "14'", "1920x1080", "Swift 3"],
["Asus", "16'", "3840х2400", "VivoBook Pro"],
["HUAWEI", "15.6'", "1920x1080", "MagicBook"],
["Apple", "13.3'", "2560x1600", "MacBook Air"]
];
// поиск в двумерном массиве
[Link]([Link]("Apple")); // false
[Link]([Link]("Apple")); // -1
// поиск в одномерном массиве
//[Link](note[3].includes("Apple"));
//[Link](note[3].indexOf("Apple"));
</script>
Для поиска в массивах с размерностью два и более используйте метод
find().
find()
Метод find() возвращает значение первого найденного в массиве
элемента, которое удовлетворяет условию, переданному в callback функции.
В противном случае возвращается undefined.
Синтаксис:
let result = [Link](function(elem, index, array) {
// ...
});
Короткая форма синтаксиса имеет вид:
let result = [Link]( elem => {
// ...
});
Параметры:
function(elem, index, array) - функция, вызываемая для каждого
значения массива, принимает три аргумента:
276
elem–текущий обрабатываемый элемент в массиве.
index–необязательный. Индекс текущего обрабатываемого элемента в
массиве.
array–необязательный. Массив, по которому осуществляется проход.
Возвращаемое значение: значение элемента массива, если элемент
прошёл проверку, иначе undefined.
Метод find() вызывает переданную функцию callback один раз для
каждого элемента, присутствующего в массиве, до тех пор, пока она не
вернёт true. Если такой элемент найден, метод find немедленно вернёт
значение этого элемента. В противном случае, метод find вернёт undefined.
ПРИМЕР 7
<script>
let courses = [
{id: 1, name: "Python-рузработчик" , time: "12 месяцев", shedule: "По будним
дням 12:00-15:00", level: "Middle", teacher: "Ливанов Б.В.", price: 55000},
{id: 2, name: "Data Scientist" , time: "10 месяцев", shedule: "По выходным
18:00-20:00", level: "Junior", teacher: "Вавилов Н.И.", price: 48000},
{id: 3, name: "JavaScript разработчик с нуля" , time: "7 месяцев", shedule: "По
будним дням 13:00-15:00", level: "Junior", teacher: "Данилов В.Е.", price: 40000},
{id: 4, name: "Фронтенд-разработчик" , time: "5 месяцев", shedule: "По
выходным дням 10:00-12:00", level: "Middle", teacher: "Татарский А.М.", price:
78000},
];
// метод находит одно вхождение
course = [Link] ( item => {
// если выражение true - вернуть текущий элемент item
return [Link]("JavaScript");
});
// вывод найденного объекта JS в консоль
[Link](course);
</script>
Обратите внимание, условие конца поиска - возврат значения true.
Именно поэтому в следующем демонстрационном примере будет возвращен
первый объект из массива.
Метод find() работает до первого значения true.
ПРИМЕР 8
<script>
let courses = [
{id: 1, name: "Python-рузработчик" , time: "12 месяцев", shedule: "По будним
дням 12:00-15:00", level: "Middle", teacher: "Ливанов Б.В.", price: 55000},
{id: 2, name: "Data Scientist" , time: "10 месяцев", shedule: "По выходным
18:00-20:00", level: "Junior", teacher: "Вавилов Н.И.", price: 48000},
{id: 3, name: "JavaScript разработчик с нуля" , time: "7 месяцев", shedule: "По
будним дням 13:00-15:00", level: "Junior", teacher: "Данилов В.Е.", price: 40000},
{id: 4, name: "Фронтенд-разработчик" , time: "5 месяцев", shedule: "По
выходным дням 10:00-12:00", level: "Middle", teacher: "Татарский А.М.", price:
78000},
277
];
// находит одно вхождение
// или возвращает -undefined
course = [Link] ( item => {
// на первой же итерации вернем true
return 1;
});
// вывод первого объекта массива
[Link](course);
</script>
filter()
Метод filter() создаёт новый массив со всеми элементами,
прошедшими проверку, задаваемую в передаваемой функции.
Синтаксис:
let result = [Link](function(elem, index, array){
// ...
});
Как обычно, можно записать так:
let result = [Link]( elem => {
// ...
});
Параметры:
function(elem, index, array) - функция-предикат, которая будет вызвана
для проверки каждого элемента массива. Если функция возвращает true, то
элемент остаётся в массиве, если false, то удаляется. Функция, принимает три
аргумента:
elem–текущий обрабатываемый элемент в массиве.
index–необязательный. Индекс текущего обрабатываемого
элемента в массиве.
array–необязательный. Массив, по которому осуществляется
проход.
Возвращаемое значение: вернётся новый массив с элементами,
которые прошли проверку. Если ни один элемент не прошёл проверку, то
будет возвращён пустой массив.
Метод filter() вызывает переданную функцию callback один раз для
каждого элемента, присутствующего в массиве, и создаёт новый массив со
всеми значениями, для которых функция callback вернула значение, которое
может быть приведено к true.
ПРИМЕР 9
<script>
let televisions = [
["24", "LED", "60 Гц", "DEXP", "H24F7000E", "HD", 25000, "img/[Link]",
`Телевизор LED DEXP H24F7000E отличается столь компактными размерами, что
278
место для него найдется даже на самой маленькой кухне. Благодаря VESA-
креплению разместить его получится даже на стене, чтобы освободить на
горизонтальных поверхностях место для других вещей.`],
["24", "LED", "60 Гц", "Telefunken", "TF-LED24S19T2", "HD", 20500, "img/TF-
[Link]", `Телевизор Telefunken оснащен экраном с диагональю 60 см,
светодиодной подсветкой (LED). Модель Telefunken LED24S19T2 обладает
приемом сигнала: DVB-T2/T/C разрешением 1366 x 768, воспроизведением
аудио-, фото- и видеофайлов через USB, прогрессивной разверткой.`],
["24", "LED", "50 Гц", "Harper", "24R470T", "HD", 18000, "img/[Link]",
`Телевизор LED Harper 24R470T – это небольшое устройство с диагональю экрана
24" (61 см) в черном корпусе. Он поддерживает воспроизведение видео в
разрешении 1366x768 (HD) и обладает прекрасными характеристиками
изображения, которые делают просмотр телепередач максимально комфортным.
Это угол обзора 178°/178°, цветность до 16.7 млн. цветов, яркость 210 Кд/м².`],
];
// условие отбора
var price = 25000;
// находит одно вхождение
// или возвращает - undefined
let result = [Link] ( item => {
// проверка вернет либо true либо false
// если true, текущий item попадет в результирующий массив
return item[6] <= price;
});
// вывод результирующего массива
[Link](result);
</script>
В следующем примере поработаем с объектом ответа сервера из
регионального чемпионата «Профессионалы». Применим вложенный
перебор массивов для поиска рейсов, отправляющихся из Москвы.
ПРИМЕР 11
// JS объект ответа сервера "to": {
let flights = { "city": "Moscow",
"data": { "airport": "Sheremetyevo",
"items": [ "iata": "SVO",
{ "date": "2020-10-12",
"code": "MGERS", "time": "13:35"
"cost": 40000, },
"flights": [ "cost": 9500,
{ "availability": 58
"flight_id": 1, }
"flight_code": "FP2100", ],
"from": { "passengers": [
"city": "Moscow", {
"airport": "Sheremetyevo", "id": 1,
"iata": "SVO", "first_name": "Ivan",
"date": "2020-10-01", "last_name": "Ivanov",
"time": "08:35" "birth_date": "1990-02-20",
}, "document_number": "1234567890",
"to": { "place_from": null,
"city": "Kazan", "place_back": null
"airport": "Kazan", },
"iata": "KZN", {
279
"date": "2020-10-01", "id": 2,
"time": "10:05" "first_name": "Ivan",
}, "last_name": "Sergeev",
"cost": 10500, "birth_date": "1990-03-20",
"availability": 58 "document_number": "1234567890",
}, "place_from": null,
{ "place_back": null
"flight_id": 2, }
"flight_code": "FP1200", ]
"from": { }
"city": "Kazan", ]
"airport": "Kazan", }
"iata": "KZN", }
"date": "2020-10-12",
"time": "12:00"
},
<script>
// сохраним массив [Link] в переменную items
let items = [Link];
// переберем массив items
[Link] ((item, items) => {
// сохраним массив [Link] в переменную flights
let flights = [Link];
// цикл для отбора рейсов
result = [Link]( flight => {
// если рейс выполняется из Москвы,
// поместии текущий объект массива в результирующий массив
return [Link] == "Moscow";
})
});
// результат поиска
[Link](result);
</script>
Обратите внимание, массив [Link] состоит из одного
объекта, но мы все равно перебираем его с помощью метода forEach(). Дело
в том, что в реальном приложении, в том числе в чемпионате Профессионалы
это будет массив нескольких объектов.
Преобразование массива
map()
Метод map() создаёт новый массив с результатом вызова указанной
функции для каждого элемента массива.
Синтаксис:
let new_array = [Link](function(elem, index, array) {
// ...
});
Как обычно, можно записать так:
let new_array = [Link]( elem => {
// ...
});
280
Параметры:
function(elem, index, array) - функция, вызываемая для каждого
значения в массиве, принимает три аргумента:
elem–текущий обрабатываемый элемент в массиве.
index–необязательный. Индекс текущего обрабатываемого
элемента в массиве.
array–необязательный. Массив, по которому осуществляется
проход.
Возвращаемое значение: новый массив, где каждый элемент является
результатом callback функции.
Метод map() вызывает переданную функцию callback один раз для
каждого элемента, в порядке их появления и конструирует новый массив из
результатов её вызова. Функция callback вызывается только для индексов
массива, имеющих присвоенные значения, включая undefined. Она не
вызывается для пропущенных элементов массива, то есть для индексов,
которые никогда не были заданы, которые были удалены или которым
никогда не было присвоено значение.
ПРИМЕР 12
let televisions = [
{
diag: "24",
matr: "LED",
freq: "60 Гц",
firm: "Telefunken",
model: "TF-LED24S19T2",
perm: "HD",
price: 20500,
path: "img/[Link]",
descr: "Телевизор Telefunken оснащен экраном с диагональю 60 см,
светодиодной подсветкой (LED).
},
{
diag: "24",
matr: "LED",
freq: "50 Гц",
firm: "Harper",
model: "24R470T",
perm: "HD",
price: 18000,
path: "img/[Link]",
descr: "Телевизор LED Harper 24R470T – это небольшое устройство с
диагональю экрана 24\" (61 см) в черном корпусе.
},
{
diag: "32",
matr: "LED",
freq: "50 Гц",
firm: "LG",
281
model: "32LM577BPLA",
perm: "HD",
price: 32000,
path: "img/[Link]",
descr: "Телевизор LED LG 32LM577BPLA с диагональю 32\" (80 см) представлен
в черном корпусе и укомплектован подставкой, которая крепится с двух сторон
по краям корпуса.
},
];
<script>
// метод map в отличии от forEach возвращает результат
// результатом будет новый массив
let res = [Link]( item => {
// если фирма LG, то запишем в новый массив сочетание данных firm-model
if ([Link]("LG"))
return `${[Link]} (${[Link]})`;
});
// исходный массив
[Link](televisions);
// результирующий массив
[Link](res);
</script>
ПРИМЕР 13
<script>
// инициируем массив массивов
let teams = new Array(
[1, "Aerosmith", "США", "1970", ["хард-рок", "блюз-рок", "рок-н-ролл", "глэм-
метал"]],
[2, "Pink Floyd", "Великобритания", "1965", ["психоделический-рок", "арт-рок",
"эйсид-рок", "прогрессивный-рок"]],
[3, "The Beatles", "Великобритания", "1960", ["рок", "рок-н-ролл", "поп", "хард-
рок"]],
);
// создадим копию массива, в которой
// вложенные массивы заменим на вложенные объекты
res = [Link] ( item => {
// вернем объект
282
return {
"id" : 10 + item[0],
"name" : item[1],
"country" : item[2],
"year" : item[3],
// приведем массив третьего уровня к строке
"style" : item[4].join()
}
});
// исходный массив
[Link](teams);
// результирующий массив
[Link](res);
</script>
В следующем примере проявим великодушие негоцианта и создадим
новый массив, в котором уменьшим цену каждого телевизора из
подключенного массива на 10%.
ПРИМЕР 14
let televisions = … из примера 12 …
<script>
// установим скидку в размере 10% на каждый телевизор
results = [Link] ( item => {
// меняем цену каждого телевизора
item[6] = item[6] - (item[6] * 0.1);
// возвращаем элемент
return item;
});
// исходный массив
[Link](televisions);
// измененный массив
[Link](results);
</script>
Мы сделали широкий жест. Но цены изменились не только в
результирующем массиве, но и в исходном теперь как люди узнают о нашем
величии, если не будет с чем сравнивать? Исходный массив желательно
оставить в неизменном состоянии.
В таком случае необходимо сделать копию элемента массива, и уже в
копию внести требуемые изменения.
ПРИМЕР 15
let televisions = … из примера 12 …
<script>
// установим скидку в размере 10% на каждый телевизор
results = [Link] ((item, index, televisions) => {
// сделаем срез массива item
newArr = [Link](0,);
// меняем цену для телевизора нового массива
newArr[6] = item[6] - (item[6] * 0.1);
// возвращаем новый массив
return newArr;
283
});
// исходный массив
[Link](televisions);
// измененный массив
[Link](results);
</script>
Вот теперь [Link] свидетель нашего величия.
Таким образом.
Метод map() возвращает новый массив.
Размер результирующего массива равен размеру исходного.
sort()
Метод sort() - сортирует массив на месте, меняя в нём порядок
элементов. Он также возвращает отсортированный массив, но обычно
возвращаемое значение игнорируется, так как изменяется сам исходный
массив.
Синтаксис:
[Link]([compareFunction])
Параметры:
compareFunction–необязательный параметр. Указывает функцию,
определяющую порядок сортировки. Если опущен, массив сортируется в
соответствии со значениями кодовых точек каждого символа Unicode,
полученных путём преобразования каждого элемента в строку.
Возвращаемое значение: отсортированный массив. Важно, что копия
массива не создаётся - массив сортируется на месте.
Если функция сравнения compareFunction не предоставляется,
элементы сортируются путём преобразования их в строки и сравнения
строк в порядке следования кодовых точек Unicode.
ПРИМЕР 16
<script>
// инициируем исходный массив
var arr = ['e', 2, 10, 'g', '7', 'д', undefined];
// сортируем массив
[Link]();
// порядок сортировки:
// 1. цифры
// 2. символы En
// 3. символы Ru
[Link](arr);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
284
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №28 - Задание
№1» вам предложен двумерный массив в файле [Link]. Подключите файл
к шаблону сценария. Используя метод filter(), напишите скрипт,
сохраняющий в массив данные только тех альбомов, которые получали
статус в Канаде (CAN).
Выведите массив в консоль браузера.
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №28 - Задание
№2» вам предложен файл данных [Link]. Подключите данные к шаблону
файла сценария. Напишите скрипт, сохраняющий в массив данные о рейсах,
выполняемых из Москвы.
Выведите массив в консоль браузера.
ЗАДАНИЕ 3
В папке «Раздаточный материал - Практическая работа №28 - Задание
№2» вам предложен файл данных televisions_array.js. Подключите данные к
шаблону файла сценария [Link]. Напишите скрипт, выполняющий
пересчет цен на телевизоры фирмы DEXP. Пересчет выполнить из расчета
20% скидки от первоначальной цены.
Выведите исходный и результирующие массивы в консоль браузера.
285
Практическая работа 29
Содержание
Стань 1. LocalStorage
2. SessionStorage
профессионалом! 3. Перебор ключей
4. Событие Storage
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Объекты веб-хранилища localStorage и sessionStorage позволяют
хранить пары ключ/значение в браузере. Объекты являются ключевым
элементом при разработке асинхронных веб-приложений.
Что в них важно – данные, которые в них записаны, сохраняются после
обновления страницы (в случае sessionStorage) и даже после перезапуска
браузера (при использовании localStorage).
Но ведь у нас уже есть куки. Зачем тогда нужны объекты веб-
хранилища?
Объекты веб-хранилища не отправляются на сервер при каждом
запросе. Именно поэтому можно хранить гораздо больше данных.
Большинство современных браузеров могут выделить как минимум 5
мегабайтов данных (или больше), и этот размер можно поменять в
настройках.
Сервер не может манипулировать объектами хранилища через HTTP-
заголовки. Всё делается при помощи JavaScript.
Хранилище привязано к источнику (домен/протокол/порт). Это
значит, что разные протоколы или поддомены определяют разные объекты
хранилища, и они не могут получить доступ к данным друг друга.
Объекты хранилища localStorage и sessionStorage предоставляют
одинаковые методы и свойства:
setItem(key, value) – сохранить пару ключ/значение;
getItem(key) – получить данные по ключу key;
removeItem(key) – удалить данные с ключом key;
clear() – удалить всё;
key(index) – получить ключ на заданной позиции;
length – количество элементов в хранилище.
Интерфейс объектов Storage похож на Map, но также позволяет
получить доступ к элементу по индексу – key(index).
286
localStorage
Основные особенности объекта localStorage:
Этот объект один на все вкладки и окна в рамках источника (один и
тот же домен/протокол/порт).
Данные не имеют срока давности, по которому истекают и удаляются.
Сохраняются после перезапуска браузера и даже ОС.
Например, если запустить следующий код:
[Link]('key', 'test');
…и закрыть/открыть браузер или открыть ту же страницу в другом
окне, то можно получить данные следующим образом:
alert ([Link]('key'));// test
ПРИМЕР 1
<script>
let test = "Мы перестали искать монстров у себя под кроватью, когда осознали,
что они внутри нас (Джокер)";
// сохраняем в localStorage строку
[Link]('key', test);
// получаем значение localStorage по ключу
[Link]([Link]('key'));
</script>
В объектах Storage можно хранить не только строковые данные. Хотя,
есть нюансы. В примере 2 продемонстрирована возможность сохранения в
объект хранилища данных разных типов. Обратите внимание на вывод этих
данных в консоль браузера.
ПРИМЕР 2
<script>
// сохраняем в localStorage число
[Link]("num", 55);
// сохраняем в localStorage булево значение
[Link]("bol", true);
// сохраняем в localStorage массив
[Link]("arr", [55, true, "hello"]);
// сохраняем в localStorage объект
[Link]("obj", { num: 255, bool:true, msg:"hello" });
// извлекаем из localStorage данные
let num = [Link]('num');
let bol = [Link]('bol');
let arr = [Link]('arr');
let obj = [Link]('obj');
// выводим данные в консоль браузера
[Link](num);
[Link](bol);
// ! обратите внимание, как выводится массив
[Link](arr);
// ! обратите внимание, как выводится объект
[Link](obj);
287
</script>
Веб хранилища позволяют хранить структуры любой сложности.
Объект веб-хранилища хранит только строки
Ключ и значение объекта хранилища должны быть строками. Если мы
используем любой другой тип, например число, массив или объект, то он
автоматически преобразуется в строку.
А это значит, что если необходимо сохранить сложный тип данных, то
предварительно его необходимо сериализовать. Чаще всего для этого вы
будете использовать формат JSON-представления данных.
ПРИМЕР 3
<script>
// объект для сохранения в localStorage
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
};
// просто сохранить объект не получится
// объект необходимо перевести в формат JSON
let userJSON = [Link](user);
// сохраняем объект JSON в localStorage
[Link]("user", userJSON);
// проверим значение localStorage
[Link]([Link]("user"));
</script>
Также возможно привести к строке весь объект хранилища, например
для отладки:
[Link](localStorage);
Доступ как к обычному объекту
Также можно получать/записывать данные в объект хранилища, как в
обычный JS-объект. Это возможно по историческим причинам.
// установить значение для ключа
[Link] =2;
// получить значение по ключу
alert( [Link] );// 2
// удалить ключ
delete [Link];
288
ПРИМЕР 4
<script>
// сложная структура данных для хранения
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
};
// предварительно очистим объект
[Link]();
// доступ как к обычному объекту
[Link] = 100;
[Link] = "Добро пожаловать!";
[Link] = true;
[Link] = ["js", "шпрехшталмейстер", "балалайка"];
[Link] = user;
// вывод свойств объекта в консоль
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
</script>
И если вы решили использовать хранилище как обычный объект,
принцип хранения не меняется – значение свойства объекта веб-
хранилища должно быть строкой.
ПРИМЕР 5
<script>
// сложная структура данных для хранения
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
};
// предварительно очистим объект
[Link]();
289
// доступ как к обычному объекту
[Link] = 100;
[Link] = "Добро пожаловать!";
[Link] = true;
[Link] = [Link](["js", "шпрехшталмейстер", "балалайка"]);
[Link] = [Link](user);
// вывод свойств объекта в консоль
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
[Link]([Link]([Link]));
[Link]([Link]([Link]));
</script>
И несмотря на то, что как правило, это работает, делать так обычно не
рекомендуется.
Если ключ генерируется пользователем, то он может быть каким
угодно, включая length или toString или другой встроенный метод
localStorage. В этом случае getItem/setItem сработают нормально, а вот
чтение/запись как свойства объекта не пройдут.
Когда мы модифицируем данные, то срабатывает событие storage. Но
это событие не происходит при записи без setItem, как свойства объекта.
Домен / протокол / порт
Нет никакого смысла сохранять данные в объект Storage и тут же его
извлекать. Есть смысл сохранить объект на одной странице, для
использования данных этого объекта на другой странице.
Для выполнения достаточно находиться на том же источнике
(домен/протокол/порт), при этом URL-путь может быть разным.
Передача данных хранилища LocalStorage между страницами.
ПРИМЕР 6_1
<script>
// JS-объект данных
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
}
// JSON-представление объекта
userJSON = [Link](user);
// сохраним представление в localStorage
290
[Link]("user", userJSON);
// JSON-объект, который получим на странице example_6-[Link]
[Link]("Предварительный вывод объекта JSON:");
[Link]([Link]("user"));
</script>
</head>
<body>
<a href="example_6-[Link]">Тестируем передачу объекта в localStore</a>
</body>
Получим данные на другой странице.
ПРИМЕР 6_2
<script>
// получим JSON-представление объекта из localStorage
let userJSON = [Link]('user');
[Link]("Объект создан на странице example_6-[Link]:");
// объект JSON
[Link](userJSON);
// объект JS
[Link]([Link](userJSON));
</script>
Объект localStorage доступен всем окнам из одного источника,
поэтому, если мы устанавливаем данные в одном окне, изменения становятся
видимыми в другом.
В следующем примере обратите внимание на атрибут target ссылки:
<a href="example_7-[Link]" target="_blank">Тестируем передачу объекта в
localStore</a>
Передача данных хранилища localStorage между вкладками
ПРИМЕР 7_1
<script>
// JS-объект данных
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
}
// преобразуем JS в JSON
userJSON = [Link](user);
// сохраним строку JSON в localStorage
[Link]("user", userJSON);
// JSON-объект, который получим на странице example_7-[Link]
291
[Link]("Предварительный вывод объекта:");
[Link]([Link]("user"));
</script>
</head>
<body>
<a href="example_7-[Link]" target="_blank">Тестируем передачу объекта в
localStore</a>
</body>
Получаем данные на другой вкладке браузера.
ПРИМЕР 7_2
<script>
// получаем информацию из localStorage
let userJSON = [Link]('user');
// объект JSON
[Link]("<b>строка JSON:</b> ", userJSON, "<p>"); //
{"name":"Евгений","surname": ...
// объект JS
[Link]("<b>объект JS:</b> ", [Link](userJSON)); // [object Object]
</script>
Как правило, сохраняемый в веб-хранилище объект – это результат
каких-либо вычислений или обработки данных. Очень часто это данные,
полученные с сервера.
Данные веб-хранилище всегда результат обработки данных.
ПРИМЕР 8
В папке «Раздаточный материал - Практическая работа №31 - Пример
№9»
sessionStorage
Объект sessionStorage используется гораздо реже, чем localStorage.
Свойства и методы такие же, но есть существенные ограничения:
1. sessionStorage существует только в рамках текущей вкладки
браузера.
Другая вкладка с той же страницей будет иметь другое хранилище.
Но оно разделяется между ифреймами на той же вкладке (при условии,
что они из одного и того же источника).
2. Данные продолжают существовать после перезагрузки страницы, но не
после закрытия/открытия вкладки.
Если запустить следующий код:
[Link]('test', "I'm Sylvia");
и обновить страницу, данные всё ещё можно получить:
alert([Link]('test')); // I'm Sylvia
292
Но если вы откроете ту же страницу в другой вкладке и попробуете
получить данные снова, то код выше вернёт null, что значит «ничего не
найдено».
Так получилось, потому что sessionStorage привязан не только к
источнику, но и к вкладке браузера. Поэтому sessionStorage используется
нечасто.
Передача данных хранилища sessionStorage между страницами.
ПРИМЕР 9_1
<script>
// JS-объект данных
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
}
// преобразуем JS в JSON
userJSON = [Link](user);
// сохраняем JSON в sessionStorage
[Link]("user", userJSON);
// JSON-объект, который получим на странице example_10-[Link]
[Link]("Предварительный вывод объекта:");
[Link]([Link]("user"));
</script>
</head>
<body>
<a href="example_10-[Link]">Тестируем передачу объекта в sessionStorage</a>
</body>
Получим данные на другой странице.
ПРИМЕР 9_2
<script>
// получение значения хранилища sessionStorage
let userJSON = [Link]('user');
// объект JSON
[Link]("<b>Cтрока JSON:</b> ", userJSON, "<p>");
// объект JS
[Link]("<b>Объект JS:</b> ", [Link](userJSON));
</script>
Передача данных хранилища sessionStorage между вкладками.
293
ПРИМЕР 10_1
<script>
// JS-объект данных
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Ленинград",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
]
}
// преобразуем JS в JSON
userJSON = [Link](user);
// сохраняем JSON в sessionStorage
[Link]("user", userJSON);
// JSON-объект, который получим на странице example_11-[Link]
[Link]("Предварительный вывод объекта:");
[Link]([Link]("user"));
</script>
</head>
<body>
<a href="example_11-[Link]" target="_blank">Тестируем передачу объекта в
sessionStorage</a>
</body>
Получим данные на другой вкладке браузера.
ПРИМЕР 10_2
<script>
// получение значения хранилища sessionStorage
let userJSON = [Link]('user');
// объект JSON
[Link]("<b>Строка JSON:</b> ", userJSON, "<p>");
// объект JS
[Link]("<b>Объект JS:</b> ", [Link](userJSON));
</script>
Перебор ключей
Методы работы с объектами веб-хранилищ позволяют
читать/писать/удалять данные. Необходимо рассмотреть, каким образом
можно получить все значения или ключи хранилища. К сожалению,
объекты веб-хранилища нельзя перебрать в цикле, они неитерируемы.
Но, если с объектами веб-хранилищ можно работать как с обычными
объектами JavaScript, то можно пройти по ним, как по обычным массивам.
Используем для этого метод key() – получение ключа на заданной позиции.
294
ПРИМЕР 11
<script>
// JS-объект
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Печора",
post: 101101
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
],
edu: [
"Даугавпилсское высшее военное авиационное инженерное училище",
"Ивановский энергетический университет"
]
}
// очистим хранилище
[Link]();
// сохраним ключи JS объекта в объект хранилища
[Link]("name", [Link]);
[Link]("surname", [Link]);
[Link]("address", [Link]([Link]));
[Link]("phone", [Link]([Link]));
[Link]("edu", [Link]([Link]));
// пройдем циклом по ключам хранилища
for(let i=0; i<[Link]; i++) {
// метод key – получим ключ на заданной позиции
let key = [Link](i);
// значения ключей выводятся в виде строк
[Link](key, " -> ", [Link](key));
}
</script>
Другой способ – использовать цикл, как по обычному объекту c
помощью специального цикла for...in.
В следующем примере перебираются ключи, но вместе с этим
выводятся несколько встроенных полей объекта, которые нам не нужны.
Перебор ключей веб-хранилища специальным циклом for...in.
ПРИМЕР 12
<script>
// JS-объект
let user = {
name: "Евгений",
surname: "Лукашин",
address: {
street: "3-я улица Строителей, дом 25",
city: "Печора",
post: 101101
295
},
phone: [
"(912)552-92-25",
"(904)104-17-06"
],
edu: [
"Даугавпилсское высшее военное авиационное инженерное училище",
"Ивановский энергетический университет"
]
}
// очистим хранилище
[Link]();
[Link]("name", [Link]);
[Link]("surname", [Link]);
[Link]("address", [Link]([Link]));
[Link]("phone", [Link]([Link]));
[Link]("edu", [Link]([Link]));
// специальный цикл for
for(key in localStorage) {
// значения ключей выводятся в виде строк
[Link](key, " -> ", [Link](key));
}
</script>
Другой способ получить собственные ключи объекта с помощью
[Link], а затем при необходимости вывести их при помощи цикла.
Перебор массива ключей веб-хранилища специальным циклом
for...of.
ПРИМЕР 13
let personnel = [ <script>
{ // очистим хранилище
id_personnel : 1, [Link]();
surname : 'Бородина', // сохраним объекты массива в
name : 'Ксения', localStorage
patronymic : 'Алексеевна', [Link]( (item, key) => {
post : 'Преподаватель', itemJSON = [Link](item);
category : 'Соответствие занимаемой [Link](key, itemJSON);
должности', });
level_edu : 'Высшее профессиональное' // получим набор ключей объекта
}, localStorage
{ let keys = [Link](localStorage);
id_personnel : 2, // тестовый вывод
surname : 'Кошкина', // [Link]([Link]());
name : 'Вера', // специальный цикл по массиву ключей
patronymic : 'Николаевна', for(let key of [Link]()) {
post : 'Преподаватель', // извлекаем значение ключа
category : 'Первая', itemJSON = [Link](key);
level_edu : 'Высшее профессиональное' // преобразуем строку JSON в JS
}, объект
{ item = [Link](itemJSON);
id_personnel : 3, // выводим в консоль пару ключ ->
surname : 'Рыбкина', значение
name : 'Ольга', [Link](key, " -> ", item);
patronymic : 'Витальевна', }
post : 'Преподаватель', </script>
category : 'Соответствие занимаемой
296
должности',
level_edu : 'Высшее профессиональное'
},
];
localStorage sessionStorage
Совместно используется между Разделяется в рамках вкладки
всеми вкладками и окнами с браузера, среди ифреймов из того же
одинаковым источником источника
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №31 - Задание
№1» вам предложены файлы:
[Link] – шаблон сценария основного файла.
[Link] – шаблон сценария целевого файла.
[Link] – внешний файл данных, массив объектов persons.
Подключите внешний файл данных. Напишите сценарий,
сохраняющий в веб-хранилище localStorage объект массива с
идентификатором id_person = 3.
Выполните переход по ссылке в целевой файл. В целевом файле
выведите в консоль сохраненный в хранилище объект.
ЗАДАНИЕ 2
Веб хранилище localStorage. Поиск, сохранение, извлечение объекта.
В папке «Раздаточный материал - Практическая работа №31 - Задание
№2» вам предложен [Link] – файл данных, массив объектов,
содержащий информацию о зарегистрированных в приложении педагогах.
Для выполнения практической работы, выполните следующий набор
действий.
Изучите структуру объекта файла данных [Link].
В сценарии файла [Link]:
используя стандартные диалоговые окна prompt() предоставьте
пользователю возможность ввести логин и пароль интересующего его
педагога;
при нахождении в файле данных преподавателя с указанными
учетными данными:
выведите кнопку / ссылку «Перейти в профиль», для перехода в
файл [Link];
сохраните объект с информацией о преподавателе в веб-
хранилище localStorage.
при отсутствии в приложении преподавателя с указанными учетными
данными выведите в документ соответствующее сообщение.
В сценарии файла [Link]:
извлеките данные о преподавателе из веб-хранилища localStorage;
выведите данные в документ.
298
ЗАДАНИЕ 3
Веб хранилище localStorage. Фильтрация, сохранение, извлечение
объектов.
В папке «Раздаточный материал - Практическая работа №31 - Задание
№3» вам предложен [Link] – файл данных, массив объектов, содержащий
информацию о пользователях и их заказах. Для выполнения практической
работы, выполните следующий набор действий.
Изучите структуру объекта файла данных [Link].
В сценарии файла [Link]:
Подключите массив данных заказов;
Сохраните массив заказов, за исключением заказа с номером 2341/4, в
веб-хранилище localStorage.
Создайте ссылку для перехода в файл [Link].
В сценарии файла [Link]:
Используя любой из операторов цикла выведите в браузер данные о
заказах хранилища localStorage.
ЗАДАНИЕ 4
Веб хранилище localStorage. Динамическое создание и вывод объектов.
В папке «Раздаточный материал - Практическая работа №31 - Задание
№4» вам предложены файлы. Для выполнения практической работы,
выполните следующий набор действий.
В файле [Link]:
изучите структуру карточек каталога товаров документа;
если объект веб-хранилища localStorage содержит информацию о
товарах, выведите имеющиеся данные в документ. Вставку динамически
формируемых карточек товаров выполнять после статических карточек
документа.
В сценарии файла [Link]:
используя диалоговые окна prompt() запросите следующую
информацию о добавляемом товаре:
- название;
- описание;
- цена;
- путь к изображению.
для добавления данных используйте информацию текстового файла
[Link];
сохраните данные в объект веб-хранилища localStorage;
299
используя ссылку «Назад к каталогу товаров» вернитесь в файл
вывода каталогов товаров;
убедитесь в выводе карточек статических товаров документа и
динамических товаров из объекта веб-хранилища;
добавьте все имеющиеся данные о товарах.
300
Практическая работа 3 0
ВВЕДЕНИЕ В ФУНКЦИИ JS
Содержание
Стань 1. Объявление и вызов функций
профессионалом! 2. Особенности функциональных
выражений
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Функция — это именованный фрагмент кода, к которому можно
многократно обратиться из любого места внутри программы. Как правило,
функция возвращает значение.
Процедура (функция-процедура) — это функция, которая возвращает
пустое значение. При этом выполнение кода функции сказывается на
выполнении программы или на состоянии DOM-документа.
Метод — это функция, которая является свойством объекта. Объявлять
функции в JavaScript можно с помощью синтаксиса:
function declaration;
function expression.
Объявление и вызов функций
Функция вида function declaration (функция инструкция)
Функция вида function declaration (или function definition или function
statement) по синтаксису является инструкцией. Объявление функции
состоит из ключевого слова function и следующих частей:
Синтаксис:
function name([param1, param2, ..., paramN]) {
statements;
};
где:
function - ключевое слово;
name - имя функции;
paramN - список параметров (принимаемых функцией) заключённых в
круглые скобки и разделённых запятыми;
statements - инструкции, которые будут выполнены после вызова
функции, заключают в фигурные скобки { }.
301
ПРИМЕР 1
<script>
// объявление declaration функции cube
function cube(number) {
let res = number * number * number;
return res;
}
// вызов функции cube
// функция возвращает значение переменной х
let x = cube(3);
[Link](x); // 27
</script>
Функция cube() принимает параметр - number, и состоит из
нескольких действий. Инструкция return указывает на значение, которое
будет возвращено функцией. Функция всегда возвращает значение, если
инструкция return не используется, будет возвращено значение undefined.
Функция вида function expression (функциональное выражение)
Другой вид функции - function expression (функциональное
выражение). В данном случае ключевое слово function может использоваться
для определения функции внутри выражения. Такая функция может быть
анонимной (не иметь имени).
Синтаксис:
var myFunction = function [name]([param1[, param2[, ..., paramN]]]) {
statements;
};
где:
function - ключевое слово;
name - имя функции, является локальным для её тела, может быть
опущено (в таком случае функция является анонимной). Пример
использования имени рассмотрим дальше;
paramN - имя аргумента, передаваемого в функцию;
statements - инструкции (программный код), составляющие тело
функции.
ПРИМЕР 2
<script>
// объявление функции
var cube = function (number) {
result = number * number * number;
return result;
};
// инициируем переменную value
var value = 5;
// передаем переменную value в качестве аргумента анонимной функции
var x = cube(value);
[Link](x); // 125
302
</script>
Функции вида expression удобны, когда функция передаётся
аргументом другой функции.
ПРИМЕР 3
<header>
<div id="console"><h1></h1></div>
</header>
<script>
// объявление функции
var myHello = function () {
[Link]("console").[Link] = "Будь таким, каким
хочешь казаться (Сократ)";
};
var el = myHello();
[Link](el); // undefined
</script>
Функция вида arrow function expression (функция стрелка)
Существует ещё один вариант синтаксиса для создания expression
функций, он называется функции-стрелки или стрелочные функции (arrow
functions).
Стрелочная функция представляет собой более короткий синтаксис
функции expression. Функцию cube() можно определить с использованием
синтаксиса стрелки.
ПРИМЕР 4
<script>
// объявление однострочной стрелочной функции cube()
var cube = (num) => num * num * num;
// вызов функции cube()
var x = cube(3);
alert(x); // 27
</script>
Если у нас только один аргумент, то круглые скобки вокруг параметров
можно опустить, сделав запись ещё короче:
// для одного параметра скобки можно опустить
var square = num => num * num;
Если аргументов нет, круглые скобки будут пустыми, но они должны
присутствовать:
// если аргументов функции нет - пустые скобки должны присутствовать
var present = () => prompt("Представьтесь, пожалуйста");
Если вы хотите использовать стрелочную функцию с несколькими
выражениями и инструкциями, необходимо использовать фигурные скобки.
При этом важное отличие – в том, что в таких скобках для возврата значения
необходимо использовать return (как в обычных функциях).
303
ПРИМЕР 5
<script>
// объявление многострочной стрелочной функции cube()
// единственный аргумент num используем без скобок
var cube = num => {
let result = num * num * num;
return result;
};
// вызов функции cube()
var x = cube(3);
alert(x); // 27
</script>
Так-же как предыдущие функции, стрелочная может быть
процедурой.
ПРИМЕР 6
<script>
// объявление многострочной стрелочной функции
// аргументов нет – скобки нужны
var present = () => {
let login = prompt("Введите логин");
let pwd = prompt("Введите пароль");
if (login == "admin" && pwd == "12345"){
[Link] ("<h1>Добро пожаловать!</h1>");
} else {
[Link] ("<h1>А вот вам, товарищ, вход запрещен!</h1>");
}
}
// вызов многострочной стрелочной функции
present();
</script>
Стрелочные функции очень удобны для выполнения простых
однострочных действий.
Функция — это всегда значение
Независимо от того, как создаётся функция – она является значением.
В обоих приведённых ниже примерах функция хранится в переменной sayHi.
// создаем переменную sayHi через function declaration
function sayHi() {
alert( "Привет" );
}
// создаем переменную sayHi через function expression
let sayHi = function() {
alert( "Привет" );
};
Значение переменной всегда можно вывести.
Обратите внимание, в коде демонстрационного примера ниже мы
сначала выполняем функцию, затем выводим ее код сначала в браузер,
затем в консоль. Код функции и есть значение переменной discr.
304
ПРИМЕР 7
<script>
// объявление стрелочной функции discr()
var discr = () => {
let b = 6;
let a = 2;
let c = 1;
let d = b**2 - 4 * a * c;
return d;
};
// вызов функции discr()
[Link](discr());
// вывод кода функции discr() в браузер
[Link](discr);
// вывод кода функции discr() в консоль
[Link](discr);
</script>
Упоминание имени функции без круглых скобок приводит к выводу
ее кода – значения переменной с именем функции. Приведённый выше код
показывает строковое представление функции, которое является её исходным
кодом.
Размещение функций
Чтобы основной файл был избавлен от излишнего нагромождения
программных конструкций, объявления функций принято выносить в
отдельные файлы (впоследствии объединять в модули).
И не забывайте, если функция взаимодействует с деревом DOM, она не
может быть вызвана раньше, чем это дерево будет построено.
ПРИМЕР 8
<head> // объявление многострочной стрелочной
... функции
<!-- подключаем файл с функцией --> var welcome = () => {
<script src="[Link]"></script> let user = prompt("Представьтесь, пожалуйста");
</head> if (user == null || [Link](/\s/g, '') == "")
<body> [Link] ("<h1>Здрасссьте вам ...</h1>");
<script> else
// вызов функции welcome() [Link] ("<h1>Добро пожаловать,
welcome(); уважаемый ", user, "!</h1>");
</script> }
</body>
305
Если необходимо сослаться на текущую функцию внутри тела этой
функции, то нужно создать именованное функциональное выражение.
Имя будет локальным (только для тела функции, её области видимости).
Самый яркий пример использования ссылки на текущую функцию
внутри тела этой функции - рекурсивный вызов.
ПРИМЕР 9
<script>
// общий вид вычисления факториала
// n! = 1 * 2 * 3 * 4 * ... * n
// факториал числа 5
// 5! = 1 * 2 * 3 * 4 * 5 (=120)
// именованная функция expression
var fact = function fnFact (num) {
if (num >= 1) {
[Link](num);
// рекурсивный вызов именованной функции,
// где fnFact - имя функции
return num * fnFact(num - 1);
};
// выход из рекурсии
return 1;
};
res = fact(5);
[Link]("==========");
[Link]("5! = ", res);
</script>
Свойство name функционального выражения
Переменная, которой присвоено функциональное выражение, будет
иметь свойство name, содержащее имя функции, и которое не изменяется
при переприсваивании другой переменной:
для анонимной функции значением свойства name будет имя
переменной (неявное имя);
для именованной функции будет использовано имя функции (явное
имя).
Следующий пример основан на том, что функция по сути является
объектом. Звучит немного запутано, но на то она и практика, чтобы
разобраться.
ПРИМЕР 10
<script>
// анонимное выражение
var cube = function (num) {
return num * num * num;
};
// вывод свойства name
[Link]([Link]); // cube
// переприсвоим значение новой переменной
306
var varCube = cube;
// вывод свойства name новой переменной
[Link]([Link]); // сube
// именованное выражение
var cube = function fnCube (num) {
return num * num * num;
};
// вывод свойства name
[Link]([Link]); // fnCube
// переприсвоим значение новой переменной
var varCube = cube;
// вывод свойства name новой переменной
[Link]([Link]); // fnCube
</script>
Подъем функции в области видимости
Функции, объявленные как function declaration (инструкция), всегда
поднимаются наверх в текущей области видимости.
ПРИМЕР 11
<script>
// два представленных примера эквивалентны
// 1. - вызов, объявление
// 2. - объявление, вызов
// вызов функции sayHello
sayHello("Greta");
// объявление функции sayHello
function sayHello (name) {
[Link]('Hello,', name, '!');
}
// ====================
// объявление функции myGreeting
function myGreeting (name) {
[Link]('Welcome friend', name, '!');
};
// вызов функции myGreeting
myGreeting ("Jimmy");
</script>
Если же функция объявляется как function expression (выражение), то
такая функция не поднимается в текущей области видимости.
ПРИМЕР 12
<script>
// два представленных примера НЕ эквивалентны
// 1. - объявление, вызов
// 2. - вызов, объявление
// объявление функции sayHello
const sayHello = function (name) {
[Link]('Hello,', name, '!');
}
// вызов функции sayHello
sayHello("Mari");
// ====================
307
// вызов функции myGreeting
myGreeting("John");
// объявление функции myGreeting
const myGreeting = function (name) {
[Link]('Welcome friend', name, '!');
}
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №30 - Задание
№1» вам предложены файлы:
[Link] – основной файл.
[Link] – внешний файл данных, массив объектов
fnSelectionQuotes().
Подключите внешний файл с функцией к основному файлу. Напишите
функцию-процедуру, выбирающую блок div, отмеченный классом cur.
Сохраните текст цитат выбранного блока в массив. Выведите
созданный массив в консоль браузера.
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №30 - Задание
№2» вам предложены файлы:
[Link] – основной файл.
[Link] – внешний файл данных определения кода функции
fhOutAuto().
Подключите внешний файл с функцией к основному файлу. Напишите
код функции-процедуры, выбирающей элемент внешнего нумерованного
списка с классом best. Сохраните элементы вложенного списка в массив.
Выведите элементы массива в виде самостоятельного маркированного
списка.
308
Практическая работа 3 1
Содержание
Стань
1. Параметры функций
профессионалом! 2. Возврат значений
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Параметры функций
Функции можно передать любую информацию, используя параметры.
Параметры представляют способ передачи в функцию данных. Параметры
указываются в скобках после названия функции. Если функция принимает
несколько параметров, то они перечисляются через запятую.
Значение, передаваемое в качестве параметра функции, также
называется аргументом.
Если быть более точным:
Параметр – это переменная, указанная в круглых скобках в
объявлении функции.
Аргумент – это значение, которое передаётся функции при её вызове.
Мы объявляем функцию со списком параметров, затем вызываем ее,
передавая список аргументов. В приведённом примере функция объявляется
с двумя параметрами: user и role, и вызывается с двумя аргументами
'Евгений' и 'Администратор'.
// параметры: user, role
function showUser(user, role) {
let msg = user + ' (' + role + ') '; alert(msg);
}
// аргументы: 'Евгений', 'Администратор'
showUser('Евгений', 'Администратор');
Когда функция вызывается, переданные значения параметров
копируются в локальные переменные user и role. Затем они используются в
теле функции.
Параметры можно именовать, как угодно, их имена имеют смысл
исключительно в теле функции. При наименовании параметров
применяются те же правила, что и для переменных.
309
Особенности использования параметров (аргументов) функций
JavaScript:
Параметры, которые передаются функции, могут передаваться как по
значению, так и по ссылке.
Определения функций JavaScript не указывают типы данных для
параметров.
Функции JavaScript не выполняют проверку типа на передаваемых
аргументах.
Функции JavaScript не проверяют количество полученных
аргументов.
ПРИМЕР 1
<script>
// объявляем функцию
function mult(num1, num2) {
// тело функции
let res = num1 * num2;
return res;
}
// объявим переменную value
var value = 4;
// во внешний код вернем значение, возвращаемое функцией
// значение запишем в переменную
var x = mult(value, 6);
[Link](x); // 24
</script>
В функцию могут передаваться параметры не только примитивных
типов (числа, строки, логический булев). Рассмотрим передачу в функцию в
качестве параметров следующие типы и структуры данных:
массив;
объект;
коллекция.
Параметр функции – массив.
ПРИМЕР 2
<script>
// инициируем массив
let auto = ["Buick", "Cadillac", "Chevrolet", "Chrysler", "Dodge", "Ford", "Pontiac", "Hummer"];
// объявляем функцию
// параметр функции - переменная arr
function fnArray (arr) {
// теперь arr - локальная переменная-массив внутри функции
// инициализируем строку для вывода списка
let line = "";
// формируем список
for (elem of arr) {
line += `<li>${elem}</li>`;
}
// возвращаем строку, которая является списком
310
return "<ul>" + line + "</ul>";
}
// вызов функции, аргумент - массив auto
// вывод на экран результата вызова
[Link] (fnArray(auto));
</script>
ПРИМЕР 3
<script> // объявляем функцию
// инициируем объект // параметр функции - переменная obj
let tel = function fnObject(obj) {
{ // теперь obj - локальная переменная-объект внутри
firm: "DEXP", функции
model: "H24F7000E", // инициализируем строку для вывода
diag: "24", let line = `
perm: "HD", Фирма: <b>${[Link]}</b><br>
matr: "LED", Модель: <b>${[Link]}</b><br>
freq: "60 Гц", Диагональ: <b>${[Link]}</b><br>
price: 25000, Разрешение экрана: <b>${[Link]}</b><br>
path: "[Link]", Матрица: <b>${[Link]}</b><br>
descr: "Телевизор LED DEXP Количество кадров в секунду:
H24F7000E отличается столь <b>${[Link]}</b><br>
компактными размерами, что Цена: <b>${[Link]}</b><br>
место для него найдется даже на Изображение: <br><img src='${[Link]}'><br>
самой маленькой кухне. Описание: <b>${[Link]}</b><br>
Благодаря VESA-креплению `;
разместить его получится даже // возвращаем строку
на стене, чтобы освободить на return line;
горизонтальных поверхностях }
место для других вещей." // вызов функции, аргумент - объект tel
} // вывод на экран результата вызова
[Link] (fnObject(tel));
</script>
ПРИМЕР 4
<h2>Мудрые цитаты Лао Цзы</h2> <script>
<div id="citate"> // инициируем коллекцию
<p>Если вы измеряете свой успех // выбираем коллекцию элементов p
мерой чужих похвал и порицаний, let citate = [Link]("div#citate
ваша тревога будет p");
бесконечной.</p> // объявляем функцию
<p>Когда я освобождаюсь от // параметр функции - переменная coll
того, кто я есть, я становлюсь тем, function fnCollection(coll) {
кем я могу быть.</p> // теперь coll - локальная переменная-
<p>Если кто-то причинил тебe коллекция внутри функции
зло, не мсти. Сядь на берегу реки, и // инициализируем строку для вывода
вскоре ты увидишь, как мимо тебя let line = "";
проплывает труп твоего врага.</p> for (el of coll) {
<p>Голос истины противен line += `<li>${[Link]}</li>`;
слуху.</p> }
</div> line = "<ol>" + line + "</ol>";
<hr> // возвращаем строку
return line;
}
// вызов функции, аргумент - коллекция citate
// вывод на экран результата вызова
311
[Link](fnCollection(citate));
</script>
ПРИМЕР 5
<ol> <script>
<li>Японские марки авто // инициируем строку
<ul> let str = "Тестируем параметры функции";
<li>Acura</li> // инициируем коллекцию
<li>Daihatsu</li> let coll = [Link]("ul li");
<li>Datsun</li> // инициируем объект
</ul> let obj = {login:"master", pwd:"12345"};
</li> // инициируем массив
<li>Американские марки let arr = ["Buick", "Cadillac", "Chevrolet", "Chrysler"];
авто // объявляем функцию
<ul> // в качестве параметров - строка, коллекция, объект,
<li>Buick</li> массив
<li>Cadillac</li> function fnOutData (myStr, myCollection, myObj, myArray){
<li>Chevrolet</li> [Link]("Строка: ", myStr);
</ul> [Link]("Коллекция: ", myCollection);
</li> [Link]("Объект: ", myObj);
</ol> [Link]("Массив: ", myArray);
}
// вызов функции
fnOutData (str, coll, obj, arr);
</script>
Необязательные параметры
В отличие от ряда других языков программирования мы можем не
передавать значения параметрам. Если параметр не указан, то его значением
становится undefined.
Например, в коде демонстрационного примера ниже функция
showUser(user, role) может быть вызвана с одним аргументом:
showUser('Евгений');
Это не приведёт к ошибке. В вызове не указан параметр role, поэтому
предполагается, что role == undefined.
ПРИМЕР 6
<script>
// объявляем функцию с двумя параметрами
// параметры: user, role
function showUser(user, role) {
let msg = user + ' (' + role + ') ';
alert(msg);
[Link](msg);
}
// вызываем функцию с одним аргументом: 'Евгений'
showUser('Евгений');
</script>
Параметры по умолчанию
312
Однако иногда бывает необходимо, чтобы параметры обязательно
имели какие- то значения, например, значения по умолчанию. Если мы
хотим задать параметру role значение по умолчанию, мы должны указать его
значение при объявлении функции.
ПРИМЕР 7
<script>
// объявляем функцию с двумя параметрами
// параметры: user, role
// параметр role задан по умолчанию
function showUser(user, role = 'Модератор') {
let msg = user + ' (' + role + ') ';
alert(msg);
[Link](msg);
}
// вызываем функцию с одним аргументом: 'Евгений'
showUser('Евгений');
</script>
Остаточные параметры (Rest parameters)
Остаточные параметры или неопределенное количество параметров
(или Rest-параметры).
Оператор "..." (многоточие) указывает, что с помощью параметра
можно передать переменное количество значений.
ПРИМЕР 8
<script>
// объявляем функцию с неопределенным количеством параметров
function fnParamsDisplay(...params) {
// params - массив
[Link]("params - это массив:");
[Link](params);
[Link]("==========\n");
[Link](params[0]);
[Link](params[1]);
[Link](params[2]);
[Link](params[3]);
}
// вызов функции c 4 аргументами
/*
"99" - строка
10 - число
true - булев
[{user:"sa"}, "php"] - массив из двух элементов (объект, строка)
*/
fnParamsDisplay("99", 10, true, [{user:"sa"}, "php"]);
</script>
В данном случае параметр ...params указывает, что вместо него можно
передать неопределенное количество значений. В теле функции params
313
фактически представляет массив переданных значений, которые мы можем
получить.
Вместо params вы можете использовать любое другое имя. Здесь
важен оператор "...".
Если params – массив, то и работать с ним можно как с массивом.
ПРИМЕР 9
<script>
// объявляем функцию с неопределенным количеством параметров
function fnParamsDisplay(...vars) {
// params - массив
// массив можно перебрать в цикле
for (value of vars){
[Link](value);
}
}
// вызов функции c 4 аргументами
[Link] ("-> вызов функции с 4 аргументами:");
fnParamsDisplay("99", 10, true, [{user:"sa"}, "php"]);
[Link] ("==========\n");
// вызов функции с 2 аргументами
[Link] ("-> вызов функции с 2 аргументами:");
fnParamsDisplay("перестройка", "плоскогубцы");
</script>
Можно сочетать параметры, сначала указать явный, потом -
неопределенное количество параметров.
В примере ниже первый параметр – строковый, далее следует
неопределенное количество параметров (параметр – params).
ПРИМЕР 10
<script>
// объявляем функцию c двумя параметрами:
/*
1) str - явный параметр (строка)
2) ...params - неопределенным количеством параметров
*/
function display(str, ...params){
[Link] ("-> это первый параметр: ", str);
[Link] ("-> далее массив параметров: ");
// params - массив
for (value of params){
[Link](value);
}
}
// вызов функции
display("html", "javascript", true, "css", 1);
[Link] ("==========\n");
// вызов функции может быть и такой
[Link] ("вызов функции может быть и такой:\n");
display();
314
</script>
Можно сделать так: первый параметр – массив, далее –
неопределенное количество параметров.
ПРИМЕР 11
<script>
// объявляем функцию c двумя параметрами:
/*
1) arr - явный параметр (массив)
2) ...params - неопределенным количеством параметров
*/
function display(arr, ...params){
// первый параметр
[Link]("-> первый параметр:");
[Link](arr);
// второй параметр
[Link]("-> второй параметр:");
[Link](params);
}
// вызов функции, первый параметр явный, массив - ["html", "javascript", "css"]
// второй параметр неопределенный, массив из элементов - true, [1,2,3]
display(["html", "javascript", "css"], true, [1,2,3] );
</script>
Не стоит путать неопределенное количество параметров и массив. В
качестве неопределенного количества параметров могут передаваться
массивы. Тогда внутри функции это многомерный массив (массив
массивов).
ПРИМЕР 12
<script>
// инициируем первый массив
let arr1 = [1,2,3];
// инициируем второй массив
let arr2 = [4,5,6];
// объявляем функцию c неопределенным количеством параметров
function display(...params){
// контрольный вывод
[Link](params);
// params - массив массивов
for (items of params){
// items - элемент, который сам является массивом, а если это массив, то
перебираем его в цикле
for (val of items) {
[Link](val);
}
}
}
// вызов функции
display(arr1, arr2);
</script>
Массив аргументов arguments
315
При необходимости мы можем получить все переданные параметры
через глобально доступный специальный объект arguments. Объект
arguments функции является псевдо-массивом. Внутри функции вы можете
ссылаться к аргументам следующим образом: arguments[i];
где: i — это порядковый номер аргумента, отсчитывающийся с 0.
ПРИМЕР 13
<script>
// объявляем функцию суммирования чисел
function sum () {
let result = 0;
// arguments - специальный объект
// [Link](arguments);
// выполняем перебор аргументов циклом for
for(i = 0; i < [Link]; i++) {
result += arguments[i];
}
// выводим результат в консоль
[Link](result);
}
// вызываем функцию с разным количеством аргументов
sum(5); // 5
sum(5, 5); // 10
sum(5, 5, 5); // 15
</script>
При этом не важно, что при определении функции мы не указали
никаких параметров, мы все равно можем их передать и получить их
значения через массив arguments.
Объект arguments позволяет вызвать функцию, передавая в неё больше
аргументов, чем формально объявлено. Это очень полезно, если вы не знаете
точно, сколько аргументов будет принимать ваша функция. Вы можете
использовать [Link] для определения количества аргументов,
переданных функции, а затем получить доступ к каждому аргументу,
используя цикл по псевдо-массиву arguments.
Перебор элементов можно организовать и с помощью специального
цикла for...of.
// выполняем перебор аргументов
for(let num of arguments) {
result += num;
}
Функции в качестве параметров
316
Аргументы функции не ограничиваются простыми, сложными типами
данных или коллекциями, на месте аргумента может быть выражение,
которое бы вычислялось и присваивалось при отсутствии параметра.
ПРИМЕР 14
<script>
// эта функция будет выступать в качестве аргумента
function getRole() {
// здесь выполняем какие-то действия, например, запрос к серверу
// результат этих действий возвращаем во внешнюю программу
let result = "Модератор";
return result;
}
function showUser(user, role=getRole()) {
// getRole() выполнится только если не передан параметр role
// результат выполнения = значение role
let msg = user + " (" + role + ")";
alert(msg);
}
// первый вызов, 2 аргумента
showUser("Евгений", "Администратор");
// второй вызов, 1 аргумент
// будет выполнена функция getRole()
showUser("Евгений");
</script>
Более широкое применение получил способ передачи в функцию в
качестве аргумента исходного кода другой функции.
ПРИМЕР 15
<script>
// эта функция будет выступать в качестве аргумента
function getRole() {
// здесь выполняем какие-то действия, например, запрос к серверу
// результат отправляем во внешний код
let result = "Модератор";
return result;
}
// функция двух параметров:
// - user - строковый
// - role - исходный код другой функции
function showUser(user, role) {
// исходный код с круглыми скобками запустит функцию-аргумент
if (role){
let msg = user + " (" + role() + ")";
alert(msg);
}
}
// вызов функции, 2 аргумента
317
showUser("Евгений", getRole);
// вызов функции, 1 аргумент
showUser("NoName");
</script>
Передача параметров по значению
Примитивные параметры (число, строка, логическое значение)
передаются в функцию по значению. Параметр передаётся в функцию, но,
если функция меняет значение параметра, это изменение не отразится
глобально в вызывающей функцию программе.
Функция всегда получает только копию значения.
ПРИМЕР 16
<script>
// тестируем параметр по значению
// объявляем функцию - инструкцию
// в функцию передаем параметр-число x
function fnChangeNum(x) {
// изменили переменную x
var x = x + 10;
[Link]("в функции изменили аргумент, x = ", x);
}
// объявили переменную, присвоили значение
var n = 10;
[Link]("-> переменная n ДО вызова функции: n = ", n); // 10
// вызываем функцию
fnChangeNum(n); // 20
[Link]("-> переменная n ПОСЛЕ вызова функции: n = ", n); // 10
</script>
При вызове функции fnChangeNum параметром передаем число n.
Функция получает параметр и прибавляет к нему число 10. Однако, после
вызова функции число n не изменилось, хотя в самой функции произошло
увеличение значения параметра.
Это произошло потому, что при вызове функция fnChangeNum
получает копию значения переменной n. И любые изменения с этой копией
никак не затрагивают саму переменную n.
Передача параметров по ссылке
В отличие от примитивных параметров объекты и массивы
передаются по ссылке. То есть функция получает сам объект или массив, а
не их копию.
ПРИМЕР 17
<script>
// тестируем параметр по ссылке
// объявляем функцию - выражение
// в функцию передаем параметр-массив arr
fnChangeArr = function (arr) {
// меняем первый элемент массива
318
arr[0] = "javaScript";
}
// инициируем массив исходными данными
var numbers = [1, 2, 3];
[Link]("исходный массив: ", numbers); // [1, 2, 3]
// вызываем функцию
fnChangeArr (numbers);
[Link]("массив после вызова функции: ", numbers); // ["javascript", 2, 3]
</script>
Возврат значения
Функция может вернуть результат, который будет передан в
вызвавший её код (внешний код).
Директива return может находиться в любом месте тела функции. Как
только выполнение доходит до этого места, функция останавливается, и
значение возвращается в вызвавший её код. Директиву return можно
использовать без значения. Это приведёт к немедленному выходу из
функции.
Вызовов return может быть несколько.
ПРИМЕР 18
<script>
// объявляем анонимную функцию
let checkUser = function() {
// получение данных от пользователя
let login = prompt('Введите логин: ');
let pwd = prompt('Введите пароль: ');
// анализ данных
if (login == "admin" && pwd == "12345") {
return true;
}
else {
return false;
}
}
// принятие решения о доступе
if (checkUser()) {
[Link] ('<h1>Добро пожаловать на сайт!</h1>');
} else {
alert('Пользователь с такими данными в системе не обнаружен.');
[Link] ('<h1>Доступ к ресурсу закрыт :(</h1>');
}
</script>
Функция может возвращать любой из типов данных, например массив.
ПРИМЕР 19
<script>
// объявляем стрелочную функцию
let fnReturnArray = () => {
// функция возвращает массив
319
return ["балалайка", "медведь", "матрешка"];
}
// вызов функции
let arr = fnReturnArray();
// вывод массива в консоль
[Link](arr);
</script>
В следующем примере функция возвратит во внешний код
сформированный объект.
ПРИМЕР 20
<script>
// объявляем функцию-выражение
let fnReturnObj = function (...params) {
// формируем объект
let obj = {
name: params[0],
login: params[1]
};
// функция возвращает объект
return obj;
}
// получение данных от пользователя
let name = prompt('Введите Имя: ');
let login = prompt('Введите Логин: ');
// вызов функции
let obj = fnReturnObj(name, login);
// вывод объекта в консоль
[Link](obj);
</script>
Во внешний код можно возвратить коллекцию.
ПРИМЕР 21
<h2>Дама сдавала в багаж</h2> <script>
<ul> // объявляем функцию-инструкцию
<li>Диван,</li> function fnReturnCollection () {
<li>Чемодан,</li> // получаем коллекцию узлов DOM
<li>Саквояж,</li> let coll = [Link]("ul li");
<li>Картину,</li> // функция возвращает коллекцию
<li>Корзину,</li> return coll;
<li>Картонку</li> }
<li>И маленькую собачонку.</li> // вызов функции
</ul> let coll = fnReturnCollection();
// вывод коллекции в консоль
[Link](coll);
</script>
320
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №31 - Задание
№1» вам предложен файл [Link] – шаблон сценария основного файла.
Напишите функции:
1. поиска информации согласного установленного критерия;
2. вывода найденной информации в браузер.
Пусть функция поиска выполняет следующие действия:
выбор блока div, отмеченного идентификатором cur (div#cur);
сохранение атрибута title выбранного блока;
выбор и сохранение текста цитат блока div#cur.
Сохранить атрибут и цитаты можно в следующую структуру:
var data = {
title: "",
citate: []
};
Структуру для передачи данных между функциями можно
использовать свою. Функция вывода выполняет вывод форматированных
данных в браузер.
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №31 - Задание
№2» вам предложены файлы:
[Link] – основной файл приложения, содержащий функции поиска
(fnGetCourse) и вывода (fnOutCourse) информации о курсе с
идентификатором = 2.
[Link] – внешний файл данных.
Ревьюируйте приложение таким образом, чтобы логика работы
выполнялась с помощью трех функций:
fnGetCourse – функция поиска курса по идентификатору;
fnFormatCourse – функция форматирования данных о курсе;
fnOutCourse – функция вывода данных. В функции отдельным
параметром предусмотрите возможность указания места вставки
сформированного контента.
Созданные функции сохраните во внешнем файле. Используя основной
файл приложения [Link] выведите результат работы скрипта.
321
Отчет по практической работе
Продемонстрировать работы преподавателю.
322
Практическая работа 3 2
ПОДРОБНЕЕ О ФУНКЦИЯХ
Содержание
Стань 1. Поднятие
профессионалом! 2. Переопределение функций
3. Цепочка вызовов
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Поднятие (hoisting)
Поднятие (hoisting) представляет процесс доступа к переменным до их
определения.
Данная концепция связана с работой компилятора JavaScript.
Компиляция кода происходит в два прохода:
При первом проходе компилятор получает все объявления
переменных, все идентификаторы. При этом никакой код не выполняется,
методы не вызываются.
При втором проходе, собственно, происходит выполнение. И даже
если переменная определена после непосредственного использования,
ошибки не возникнет, так как при первом проходе компилятору уже
известны все переменные.
То есть, как будто происходит поднятие кода с определением
переменных и функций вверх до их непосредственного использования.
Переменные var
var-переменные, которые попадают под hoisting, по умолчанию
получают значение undefined.
ПРИМЕР 1
<script>
// вывод переменной var
[Link](val); // undefined
// определение переменной var
var val = "Oops...";
</script>
Переменные let, const
Процесс hoisting для let-переменных и констант будет отличаться: в
отличие от var-переменных константам и let-переменным при первом
проходе не присваивается начальное значение.
323
ПРИМЕР 2
<script>
// Uncaught ReferenceError: Cannot access 'val' before initialization
[Link](val);
let val = "Hi!";
[Link](val);
</script>
Функция инструкция
Все то же самое относится и к использованию функций. Мы можем
сначала вызвать функцию, а потом уже ее определить.
ПРИМЕР 3
<script>
// вызов функции
sayHello();
// определение функции
function sayHello(){
[Link]("Hello Hoisting!");
}
</script>
Функциональное выражение
По-другому ведут себя функции, когда они определяются в виде
переменной – функциональные выражения.
ПРИМЕР 4
<script>
// вызов функции
sayHello();
// определение функции
var sayHello = function () {
[Link]("Hello Hoisting!");
}
</script>
В данном случае мы получим ошибку Uncaught TypeError: sayHello is
not a function.
При первом проходе компилятор также получит переменную sayHello
и присвоит ей значение undefined. При втором проходе, когда надо будет
вызывать функцию, на которую будет ссылаться эта переменная, компилятор
увидит, что вызывать нечего: переменная sayHello пока еще равна undefined.
И будет выброшена ошибка.
Чтобы избежать возможных ошибок, всегда объявляйте все
переменные в начале каждой области видимости. Это всегда хорошее
правило, поскольку именно так JavaScript интерпретирует код.
324
Строгий режим
Строгий режим (strict mode) — это важная часть современного
JavaScript. Именно этот режим позволяет разработчикам пользоваться более
ограниченным, чем стандартный, синтаксисом.
Семантика строгого режима отличается от традиционного нестрогого
режима, который иногда называют грязным (sloppy mode). В таком режиме
синтаксические правила языка не так строги, а когда происходят некоторые
ошибки, система никак не оповещает о них пользователя.
Строгий режим вносит в семантику JavaScript некоторые изменения.
Он не даёт системе закрывать глаза на ошибки, выдавая соответствующие
исключения. Это приводит к остановке выполнения программ.
Особенности применения строгого режима:
Можно применять к отдельным функциям или к целому скрипту.
Нельзя применить только к отдельным инструкциям или к блокам
кода, заключённым в фигурные скобки.
Для того чтобы использовать строгий режим на уровне целого скрипта,
в самое начало файла, до любых других команд, нужно поместить
конструкцию "use strict" или 'use strict'.
Если в проекте имеются некоторые скрипты, в которых не
используется строгий режим, и другие, в которых этот режим используется,
тогда может случиться так, что эти скрипты окажутся объединены.
Это приведёт к тому, что код, который не предназначен для
выполнения в строгом режиме, окажется в таком состоянии, когда система
попытается выполнить его в строгом режиме. Возможно и обратное — код,
написанный для строгого режима, попадёт в нестрогий режим. Поэтому
лучше всего не смешивать строгие и нестрогие скрипты.
Функции и строгий режим
Для того, чтобы применить строгий режим к отдельным функциям –
конструкцию "use strict" или 'use strict' надо поместить в верхнюю часть
тела функции, до любых других команд.
Строгий режим при таком подходе применяется ко всему, что
размещено в теле функции, включая вложенные функции.
var strictFunction = () => {
'use strict'; // включаем строгий режим для функции
const nestedFunction = () => {
// эта функция тоже использует строгий режим
}
325
Ключевое слово this
Ключевое слово this — это ссылка на некий объект, к свойствам
которого можно получить доступ. This называют контекстом выполнения.
Контекст выполнения бывает:
Глобальный.
Локальный.
Глобальный контекст
В глобальном контексте выполнения (за пределами каких-либо
функций) this ссылается на глобальный объект window вне зависимости от
режима (строгий или нестрогий).
ПРИМЕР 5
<script>
// глобальный контекст
[Link]("this === window: ", this === window); // true
// числовая переменная станет глобальным свойством объекта window
aNum = 55;
// строковая переменная станет глобальным свойством объекта window
[Link] = "Hello User!";
// логическая переменная станет глобальным свойством объекта window
[Link] = true;
[Link](this);
// [Link](aNum);
// [Link]([Link]);
// [Link]([Link]);
</script>
Функциональный контекст
В пределах функции значение this зависит от того, в каким режиме
вызвана функция:
грязный режим sloppy mode (по умолчанию);
строгий режим strict mode.
Грязный режим (sloppy mode)
Когда мы вызываем функцию, значением this может быть:
глобальный объект, по умолчанию;
undefined, при использовании конструкции use strict.
При отсутствии конструкции use strict скрипт автоматически
используется в нестрогом (грязном) режиме.
ПРИМЕР 6
<script>
// нестрогий режим / sloppy mode
function fnSloppy() {
// числовая переменная станет глобальным свойством объекта window
aSloppy = 99;
326
return this;
}
[Link]("НЕстрогий режим ->");
// this ссылается на глобальный window
[Link](fnSloppy() === window); // true
[Link](this); // глобальный объект window
// глобальный window содержит свойство aSloppy
[Link]([Link]); // 99
</script>
Строгий режим (strict mode)
Чтобы включить строгий режим необходимо использовать
конструкцию use strict.
ПРИМЕР 7
<script>
// строгий режим / strict mode
function fnStrict() {
"use strict"; // включаем strict mode
// пытаемся переменную сделать глобальным свойством объекта window
aStrict = 99;
return this;
}
[Link]("Строгий режим ->");
// this НЕ ссылается на глобальный window
[Link](fnStrict() === window); // false
// this ссылается на undefined
[Link](fnStrict() === undefined); // true
[Link](this);
</script>
Код примера выше завершился с ошибкой из-за желания создать
глобальную переменную aStrict на объекте undefined. В примере ниже
рассмотрим варианты восстановления работоспособности скрипта.
ПРИМЕР 8
<script>
function fnStrict() {
"use strict";
// пытаемся переменную сделать глобальным свойством объекта window
aStrict = 99;
/*
код далее выполняться не будет
для выполнения необходимо:
либо:
закомментировать - use strict;
либо:
закомментировать - aStrict = 99;
либо:
объявить переменную - var aStrict = 99; || let aStrict = 99;
*/
return this;
}
327
fnStrict();
[Link](this);
</script>
Попробуем отловить ошибку программно.
ПРИМЕР 9
<script>
function fnStrict() {
"use strict";
// поместим код в блок обработки ошибок
try {
// пытаемся переменную сделать глобальным свойством объекта window
aStrict = 99;
[Link](this);
} catch(err){
// вывод информации об ошибке
[Link] ("Ошибка (" + [Link] + "): " + [Link]);
}
return this;
}
fnStrict();
</script>
Переопределение функций
Функции обладают возможностью для переопределения поведения.
Переопределение происходит с помощью присвоения анонимной функции
переменной, которая называется так же, как и переопределяемая функция.
В примере ниже продемонстрировано переопределение функции
message().
ПРИМЕР 10
<h2>Переопределение функций</h2>
<script>
function message(){
[Link]("Здравствуйте!");
// переписываем значение глобальной переменной message
message = function(){
[Link]("До свидания!");
}
}
// первый вызов функции
/*
во время первого вызова в теле функции произошло
переопределение исходного кода вызываемой функции
*/
message();
// второй вызов функции (функция переопределена)
message();
</script>
При первом вызове функции действует основной блок операторов
функции, в данном случае:
328
1. выводится сообщение "Здравствуйте!";
2. происходит переопределение тела функции message.
Таким образом, при всех последующих вызовах функции срабатывает
ее переопределенная версия, а на консоль будет выводиться сообщение "До
свидания!".
При переопределении функции надо учитывать некоторые нюансы. В
частности, попробуем присвоить ссылку на функцию переменной и через эту
переменную вызвать функцию.
ПРИМЕР 11
<script>
function message() {
[Link]("Здравствуйте!");
message = function() {
[Link]("До свидания!");
}
}
// присвоение переменной displayMessage исходного кода функции message
var displayMessage = message;
/*
теперь переменная displayMessage содержит следующее значение:
{
[Link]("Здравствуйте!");
message = function() {
[Link]("До свидания!");
}
*/
// [Link](displayMessage);
/*
- вызываем функцию displayMessage()
- при этом перепишем переменную message
*/
displayMessage();
message();
</script>
329
Этот шаблон настолько в ходу, что существует термин для его
обозначения: IIFE (Immediately Invoked Function Expression - немедленно
вызываемое функциональное выражение).
IIFE не обязательно нужны имена, самая распространенная форма IIFE
— использование анонимного функционального выражения. Несмотря на
это, например, именование IIFE (как именование функции) имеет все
вышеперечисленные преимущества над анонимными функциональными
выражениями, поэтому взять его на вооружение — хорошая практика.
Функция IIFE легко работает с внешними данными любых типов.
ПРИМЕР 12
<script>
// определение/вызов функции по месту
( function fnSetData(login, pwd, email) {
// инициируем объект
let data = {
login : login,
pwd : pwd,
email: email
};
// вывод объекта в консоль браузера
[Link]("вызов функции по месту:");
[Link](data);
} ) ("Мастер", "12345", "master@[Link]");
</script>
В предыдущем варианте функция использовала данные, объявленные
внутри себя, теперь поработаем с данными, инициализированными во
внешнем коде.
ПРИМЕР 13
<script>
// определение объекта
let person = {
surname: "Строганова",
name: "Ксения",
post: "Преподаватель",
email: "strog-x@[Link]",
phone: "2-12-85-06",
experience: 14.5,
img: "[Link]"
};
// определение/вызов функции по месту
( function ouDataPerson (data) {
// интерполируем свойства объекта в строку
with (data){
html = `
<img src="${img}"> <br>
Фамилия: <b> ${surname} </b><br>
Имя: <b> ${name} </b><br>
Должность: <b> ${post} </b><br>
330
E-mail: <b> ${email} </b><br>
Телефон: <b> ${phone} </b><br>
Cтаж: <b> ${experience} </b><br>
`;
}
// вывод html-строки в документ браузера
[Link](html);
} ) (person);
</script>
Другой вариант синтаксиса традиционной формы IIFE:
Синтаксис:
( function ( )
{ .. }
() );
Эти две формы идентичны по функциональности. Какую из них
предпочесть — всего лишь ваш стилистический выбор.
ПРИМЕР 14
<h2>Краткость – сестра таланта</h2>
<div>
<h3>Всего, что нам наобещали,<br>никто у нас не отберёт.</h3>
<h3>И у меня есть точка зренья,<br>но только пятая она.</h3>
<h3>А в холодильнике, ночами,<br>еда полезней и вкусней.</h3>
<h3>Есть сотни субъективных мнений<br>и объективное моё.</h3>
</div>
<script>
// сохраняем коллекцию узлов h3
let node = [Link]("div h3");
// определение/вызов функции по месту
( function getNode() {
let couplets = new Array();
// сохраняем текстовое содержимое узлов в массив
for(let elem of node) {
[Link]([Link]);
}
// вывод массива в консоль браузера
[Link]("вызов функции по месту:");
[Link](couplets);
} (node) );
</script>
Цепочка вызовов
Цепочка функций — это стиль программирования, при котором
методы объекта (или функции) вызываются последовательно. Это
возможно, потому что каждый метод возвращает объект, и следовательно,
можно вызывать другие методы на этом объекте. Это обычно используется
для создания интерфейса, который легко читается и понимается.
Рассмотрим, каким образом можно создать цепочку из вызовов
пользовательских функций.
331
Цепочка, построенная не на объектах, а на пользовательских
функциях – это программный костыль.
ПРИМЕР 15
<script>
// функция инициализации объекта данных
function setData(login, pwd, email) {
// в глобальный window запишем объект данных data
data = {
login : login,
pwd : pwd,
email: email
};
}
// функция получения данных
// получаемые данные зависят от входного параметра val
function getData (val) {
// данные data берутся из глобального window
if (val == "login") return [Link];
if (val == "pwd") return [Link];
if (val == "email") return [Link];
}
// вызов функции инициализации данных
setData("Админ", "12345", "master@[Link]");
// получение данных email
let email = getData("email");
// вывод полученных данных в консоль браузера
[Link](email);
</script>
Для организации цепочки, вызывающая функция должна вернуть
объект this.
ПРИМЕР 16
<script>
// функция инициализации объекта данных
function setData(login, pwd, email) {
// в глобальный window запишем объект данных data
data = {
login : login,
pwd : pwd,
email: email
};
return this;
}
// функция получения данных
// получаемые данные зависят от входного параметра val
function getData (val) {
// данные data берутся из глобального window
if (val == "login") return [Link];
if (val == "pwd") return [Link];
if (val == "email") return [Link];
}
// получение данных через цепочку вызовов
332
let value = setData("Мастер", "12345", "master@[Link]").getData("login");
[Link](value);
</script>
Закрепим материал созданием нескольких функций, объединенных в
цепочку, для работы с внешним файлом данных.
ПРИМЕР 17
teams = [ <div id="console"></div>
{ <script>
id: 1, // поиск данных в подключаемом массиве
name: "Aerosmith", function fnSearchData(name) {
alias: "aerosmith", // проходим по объектам массива
country: "США", for(let team of teams) {
content: "Группа Aerosmith ...", if ([Link] == name) {
date: 1970, // если текущий объект искомый -
style: "хард-рок", // - сохраняем объект в переменную
link: teamData
"[Link] // - прерываем итерации
albums: [ teamData = team;
['Aerosmith', 8, 1973], /*Название, break;
количество композиций, дата*/ }
['Rocks', 9, 1976], }
['Toys in the Attic', 9, 1975] return this;
] }
}, // форматируем объект данных для вывода
{ function fnFormatData() {
id: 2, with(teamData) {
name: "Pink Floyd", teamOut = `
alias: "pink-floyd", <h3><a
country: "Великобритания", href='?id=${id}'>${name}</a></h3>
content: "Группа Pink Floyd ...", Страна: <b>${country}</b><br>
date: 1965, О группе: <b>${content}</b><br>
style: "психоделический-рок", Дата основания: <b>${date}</b><br>
link: Стиль исполнения: <b>${style}</b><br>
"[Link] <a href='${link}'>Смотреть в
, Википедии</a><br>
albums: [ `;
['The Dark Side of the Moon', 10, }
1973], teamOut += "<h3>Альбомы:</h3><ol>";
['The Wall', 26, 1979], // проходим по массиву альбомов
['Wish You Were Here', 5, 1975], for (team of [Link]) {
] teamOut += `<li>${team}</li>`;
}, }
{ teamOut += "</ol>";
id: 3, return this;
name: "The Beatles", }
alias: "the-beatles", // вставляем форматную строку в документ
country: "Великобритания", function fnOutData(target) {
content: "Группа The Beatles ...", // выбор элемента по его id и вставка
date: 1960, контента
style: "рок-н-ролл", [Link](target).innerHT
link: ML = teamOut;
"[Link] }
", // формируем цепочку вызовов
albums: [ fnSearchData("Pink
['Abbey Road', 17, 1969], Floyd").fnFormatData().fnOutData("console");
['Rubber Soul', 14, 1965], </script>
['Revolver', 14, 1966],
]
333
}
]
ПРИМЕР 18
teams = [ <div id="console"></div>
{ <script>
id: 1, // определение объекта со свойствами-
name: "Aerosmith", функциями (методами)
alias: "aerosmith", let obj = {
country: "США", // поиск данных в подключаемом массиве
content: "Группа Aerosmith ...", searchData: function(name) {
334
date: 1970, // проходим по объектам массива
style: "хард-рок", for(let team of teams) {
link: if ([Link] == name) {
"[Link] // если текущий объект искомый
" return team;
}, }
{ }
id: 2, },
name: "Pink Floyd", // форматирование объекта данных для
alias: "pink-floyd", вывода
country: "Великобритания", formatData: function (data) {
content: "Группа Pink Floyd ...", with(data) {
date: 1965, formatTeam = `
style: "психоделический-рок", <h3><a href='?id=${id}'>${name}</a></h3>
link: Страна: <b>${country}</b><br>
"[Link] О группе: <b>${content}</b><br>
d" Дата основания: <b>${date}</b><br>
}, Стиль исполнения: <b>${style}</b><br>
{ <a href='${link}' target='_blank'>Смотреть в
id: 3, Википедии</a><br>
name: "The Beatles", `;
alias: "the-beatles", }
country: "Великобритания", return formatTeam;
content: "Группа The Beatles ...", },
date: 1960, // вставка форматной строки в документ
style: "рок-н-ролл", outData: function (data) {
link: // выбор элемента по его id и вставка
"[Link] контента
es" [Link]("console").innerHT
} ML = data;
] }
}
// последовательный вызов функций-
методов
// поиск
let team = [Link]("Pink Floyd");
// форматирование
team = [Link](team);
// вставка
[Link](team);
</script>
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №32 - Задание
№1» вам предложены файлы:
[Link] – шаблон сценария основного файла.
[Link] – внешний файл данных приложения.
В сценарии основного файла написаны функции, которые можно
объединить в цепочку вызовов.
// формируем цепочку вызовов
fnSearchData("Pink Floyd").fnFormatData().fnOutData("console");
335
Ревьюируйте код функции fnFormatData() таким образом, чтобы при ее
вызове можно было указать следующие аргументы:
team;
album;
undefined.
Пример цепочки вызовов. Функция fnFormatData() вызывается с
аргументом team:
// вызов fnFormatData с аргументом "team"
fnSearchData("Pink Floyd")
.fnFormatData("team")
.fnOutData("console");
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №32 - Задание
№2» вам предложены файлы:
[Link] – шаблон сценария основного файла.
[Link] – внешний файл определения кода функций;
images – директория хранения изображений товаров;
[Link] – файл данных о заказах приложения.
В сценарии основного файла находится вызов функций получения и
вывода в браузер данных о заказе.
// получение данных о заказе с идентификатором = 1337424
let order = fnGetOrderData("1337424");
// вывод форматированных данных о заказе
fnOutOrder (order);
Ревьюируйте (переопределите) код функций таким образом, чтобы
алгоритм вызовов основного сценария выглядел следующим образом:
// первый вызов
// получение данных о заказе с идентификатором = 1337424
fnOutOrder("1337424");
// после первого вызова переопределили функцию fnOutOrder()
// второй вызов
// вывод форматированных данных о заказе
fnOutOrder();
Внешний вид приложения должен остаться без изменений
336
Практическая работа 3 3
CALLBACK ФУНКЦИИ
Содержание
Стань 1. API интерфейсы
2. Что такое callback
профессионалом! 3. Варианты callback
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
API интерфейсы
Интерфейсы прикладного программирования, или API — это
способ взаимодействия компьютерных программ или служб друг с другом.
Это взаимодействие обычно происходит через конечную точку API,
предоставляемую программой, которую использует клиент.
Что такое REST API
REST API — это архитектурный подход, который устанавливает
ограничения для API: как они должны быть устроены и какие функции
поддерживать. Это позволяет стандартизировать работу программных
интерфейсов, сделать их более удобными и производительными.
На сегодняшний день это самые популярные и гибкие API- интерфейсы
в Интернете. Клиент отправляет запросы на сервер в виде данных. Сервер
использует этот клиентский ввод для запуска внутренних функций и
возвращает выходные данные обратно клиенту. Изучение REST API одна из
основных задач курса.
Что такое Web API
Веб API — это просто интерфейс для доступа к ресурсам сервера по
протоколу HTTP. Термин относится к концепции, а не к какой—либо
конкретной технологии – веб API может быть создан с использованием
различных технологий, таких как Java и [Link]. Веб API используют
интерфейс с открытым исходным кодом и используют множество клиентских
объектов, таких как браузеры, смартфоны, планшеты и ноутбуки.
Простыми словами. Веб API – набор методов / функций (одним
словом - интерфейс) для доступа к ресурсам сервера по протоколу HTTP.
Таким образом:
Веб API – способ взаимодействия с сервером.
REST API – правила взаимодействия с сервером.
337
Что такое callback
Callback (коллбэк) — это функция, которая должна быть выполнена
после того, как другая функция завершила выполнение (отсюда
название: callback — функция обратного вызова).
Если чуть сложнее, в JavaScript функции — это объекты. Поэтому
функции могут принимать другие функции в качестве аргументов, а
также возвращать функции в качестве результата (как любые объекты).
Функции, которые это умеют, называются функциями высшего
порядка. А любая функция, которая передается как аргумент, называется
callback- функцией.
JavaScript — это событийно-ориентированный язык. Поэтому вместо
того, чтобы ждать ответа для дальнейшего выполнения программы,
JavaScript продолжит выполнение кода, одновременно ожидая других
событий.
Подойдем к понятию функции обратного вызова на цепочке простых
примеров.
ПРИМЕР 1
<script>
// определяем первую функцию
function first() {
[Link]("The first function is completed");
}
// определяем вторую функцию
function second() {
[Link]("The second function is completed");
}
// вызываем функции
first();
second();
// поведение функций предсказуемо
</script>
Как мы и ожидали, функция first выполнится первой, а функция second
уже после нее.
Но что, если функция first содержит некий код, который не может
выполниться немедленно? К примеру, работа с API, где мы отправляем
запрос к внешнему ресурсу и должны ждать ответа.
Чтобы смоделировать такую ситуацию, мы используем функцию
setTimeout, которая вызывает пользовательский код (функцию) после
заданного временного промежутка.
setTimeout
Синтаксис:
setTimeout(func|code, [delay], [arg1], [arg2], ...);
338
Параметры:
func|code – функция или строка кода для выполнения. Обычно это
функция. По историческим причинам можно передать и строку кода, но это
не рекомендуется.
delay – задержка перед запуском в миллисекундах (1000 мс = 1 с).
Значение по умолчанию – 0.
arg1, arg2 – аргументы, передаваемые в функцию.
ПРИМЕР 2
<script>
// определяем отложенную функцию
// функция имеет параметры
function sayHi(name, login) {
alert( "Привет, " + name + " (" + login + ")!" );
}
// запускаем функцию на выполнение
setTimeout(sayHi, 1000, "Евгений", "master");
</script>
В коде примера ниже, используем функцию setTimeout, которая
вызывает стрелочную функцию с отложенным выполнением на 500
миллисекунд, как будто бы это запрос к некому API.
ПРИМЕР 3
<script>
// в этом скрипте начинаются проблемы
// определяем первую функцию
function first() {
// моделируем запрос к API (на внешние ресурсы)
// откладываем выполнение на 500 мсек.
setTimeout(() => {[Link]("The first function is completed")}, 500);
};
// определяем вторую функцию
function second() {
[Link]("The second function is completed");
};
// вызываем функции
first();
second();
// порядок вызова функций не изменился, но
// изменился порядок выполнения функций
// такая ситуация может стать проблемой,
// если вторая функция должна воспользоваться результатами вызова первой
</script>
Порядок вызова функций не изменился, но, если посмотреть в
консоль, увидим, изменился порядок их выполнения. Такая ситуация может
стать проблемой при работе с данными.
Основная идея заключается в следующем — мы отложили исполнение
команды [Link]("The first function is completed") на 500 миллисекунд. Во
339
время выполнения JavaScript находит функцию first и исполняет ее с
отложенным выводом. Затем, без всяких пауз, он переходит на вторую
функцию и тоже запускает ее. JavaScript никогда не останавливается и ищет,
что ему еще выполнить. Именно поэтому в современных браузерах он так
быстро работает.
Изменился и изменился. Если мы выводим изображения котиков и
собачек в статичный HTML-блок, то можно даже и не подозревать о
существующей проблеме. Но такая ситуация недопустима, если вторая
функция должна воспользоваться результатами вызова первой.
ПРИМЕР 4
<div id="data"></div>
<script>
// возвращаемся к проблеме запроса API
// вторая функция должна воспользоваться результатами вызова первой
// функция получения данных
function getData() {
// моделируем запрос к API (на внешние ресурсы)
setTimeout(() => {
// определение данных
user = {name:"John", login:"master"}
}, 500);
};
// функция вывода данных
function outData() {
// интерполируем переменные в строку
html = `
<h2>Здравствуйте, вы вошли в приложение как:</h2>
Имя: <b>${[Link]}</b> <br>
Логин: <b>${[Link]}</b> <br>
`;
// вывод данных в браузер
[Link]("data").innerHTML = html;
};
// получаем проблему работы приложения
getData();
outData();
</script>
Получаем вполне предполагаемую ошибку. Переменная user не
определена, на момент вызова функции-потребителя outData() данные
внешнего источника еще не получены.
340
функции getData, а сразу двигается дальше — к функции outData.
Устраним причины остановки скрипта.
ПРИМЕР 5
<div id="data"></div>
<script>
// функция получения данных
function getData() {
// моделируем запрос к API (на внешние ресурсы)
setTimeout(() => {
// определение данных
user = { name: "John", login: "master" }
}, 500);
};
// функция вывода данных
function outData() {
// если данные не определены
if ([Link] == undefined || [Link] == undefined)
// формируем предупреждение
html = `
<h2>Сбой авторизации в системе</h2>
`
else
// иначе интерполируем переменные в строку
html = `
<h2>Здравствуйте, вы вошли в приложение как:</h2>
Имя: <b>${[Link]}</b> <br>
Логин: <b>${[Link]}</b> <br>
`;
// вывод данных в браузер
[Link]("data").innerHTML = html;
};
// инициируем пустой объект
user = {};
// проблема решена лишь отчасти
// внешние данные пришли, но мы их не видим
getData();
outData();
</script>
Проблема падающего скрипта решена лишь отчасти. Данные внешнего
ресурса пришли, но мы их не видим.
Таким образом, нельзя просто вызывать функции в нужном порядке и
надеяться, что они в любом случае выполнятся в том же порядке. Коллбэки
же позволяют нам быть уверенными в том, что определенный код не
выполнится до того момента, пока другой код не завершит своё
исполнение.
Создаем callback
Итак, анализ кода примера 5, говорит о том, что вставка данных
должна быть выполнена внутри функции, вызываемой стандартной
341
функцией setTimeout, т.е. тогда, когда внешние данные уже получены.
Вставим код вывода полученных данных внутрь функции setTimeout().
ПРИМЕР 6
<div id="data"></div>
<script>
// делаем первый шаг в грамотном решении проблемы
// функция получения данных
function getData() {
// моделируем запрос к API (на внешние ресурсы)
setTimeout(() => {
// определение данных
user = {name:"John", login:"master"};
// вызов функции getOut по месту (IIFE)
(function outData() {
html = `
<h2>Здравствуйте, вы вошли в приложение как:</h2>
Имя: <b>${[Link]}</b> <br>
Логин: <b>${[Link]}</b> <br>
`;
// вывод данных в браузер
[Link]("data").innerHTML = html;
}) ();
}, 500);
};
// вызов функции получения данных
getData();
</script>
Работает прекрасно, а выглядит не очень, ненужный, громоздкий
HTML- код вывода в секции поставщика данных. Вернем функцию outData
в глобальную область видимости, а в качестве аргумента функции getData
передадим описание (код) функции outData.
Таким образом, становится понятен сакральный смысл обратного
вызова (callback), это некий код (код функции), который передается в
качестве аргумента на вход другой функции для выполнения в
определенный момент времени. Выполнение достигается вызовом
функции-аргумента с использованием круглых скобок - callback().
ПРИМЕР 7
<div id="data"></div>
<script>
// передаем код другой функции в качестве аргумента
// такой аргумент и называется коллбэком
function getData(collback) {
// моделируем запрос
setTimeout(() => {
// получаем данные, в реальном приложении это результат внешнего
запроса
user = {name:"John", login:"master"};
// аргумент функции - функция коллбэк
// добавлая скобки коду коллбэка - вызываем функцию
342
collback();
}, 500);
};
// функция вывода данных
function outData() {
// интерполируем данные в строку
html = `
<h2>Здравствуйте, вы вошли в приложение как:</h2>
Имя: <b>${[Link]}</b> <br>
Логин: <b>${[Link]}</b> <br>
`;
// вывод данных в браузер
[Link]("data").innerHTML = html;
};
// вызов функции получения данных
// вызываем функцию getData
// функция outData - аргумент-коллбэк
getData(outData);
</script>
Работает прекрасно, а выглядит не очень, ненужный, громоздкий
HTML- код вывода в секции поставщика данных. Вернем функцию outData
в глобальную область видимости, а в качестве аргумента функции getData
передадим описание (код) функции outData.
Таким образом, становится понятен сакральный смысл обратного
вызова (callback), это некий код (код функции), который передается в
качестве аргумента на вход другой функции для выполнения в
определенный момент времени. Выполнение достигается вызовом
функции-аргумента с использованием круглых скобок - callback().
ПРИМЕР 8
<div id="data"></div>
<script>
// передаем код другой функции в качестве аргумента
// такой аргумент и называется коллбэком
function getData(collback) {
// моделируем запрос
setTimeout(() => {
// получаем данные, в реальном приложении это результат внешнего
запроса
user = {name:"John", login:"master"};
// аргумент функции - функция коллбэк
// добавлая скобки коду коллбэка - вызываем функцию
collback();
}, 500);
};
// функция вывода данных
function outData() {
// интерполируем данные в строку
html = `
<h2>Здравствуйте, вы вошли в приложение как:</h2>
Имя: <b>${[Link]}</b> <br>
Логин: <b>${[Link]}</b> <br>
343
`;
// вывод данных в браузер
[Link]("data").innerHTML = html;
};
// вызов функции получения данных
// вызываем функцию getData
// функция outData - аргумент-коллбэк
getData(outData);
</script>
Варианты callback
Callback – это не только работа с API, это гораздо больше. Возможны и
другие варианты использования.
В следующих примерах представлены функции, которые получают на
вход итерируемый набор, и для каждого элемента набора вызывают
функцию обратного вызова callback.
Функция и коллбэк для простого массива строк.
ПРИМЕР 9
<script>
// определяем функцию
// 1 параметр - массив
// 2 параметр - коллбэк (код функции)
function fnArgArr(list, callback) {
// инициируем результирующий массив
let result = [];
// выполняем перебор элементов входного массива
for (let elem of list) {
// для каждого элемента вызываем функцию-коллбэк
// результат записываем в массив
[Link]( callback(elem) );
}
// возвращаем результирующий массив
return result;
}
// исходный массив
arr = ["PHP", "JavaScript", "jQuery", "Bootstrap", "SQL"];
// функция коллбэк
let callback = elem => {
return "#" + [Link]();
}
// получаем преобразованный массив
let tags = fnArgArr(arr, callback);
let line = [Link](" ");
// вывод преобразованного массива в документ
[Link](line);
// вывод преобразованного массива в консоль
[Link](tags);
</script>
344
Функция и коллбэк для коллекции HTML-элементов.
ПРИМЕР 10
<h2>Минутка психоанализа</h2>
<div style="display:none">
<p>Масштаб вашей личности определяется величиной проблемы, которая
способна вас вывести из себя.</p>
<p>Единственный человек, с которым вы должны сравнивать себя – это вы в
прошлом. И единственный человек, лучше которого вы должны быть – это вы
сейчас.</p>
<p>Мы выбираем не случайно друг друга... Мы встречаем только тех, кто уже
существует в нашем подсознании.</p>
</div>
<script>
// определяем функцию
// 1 параметр - итерируемый набор - коллекция элементов
// 2 параметр - коллбэк (код функции)
function fnArgNode(collection, callback) {
let result = [];
// выполняем перебор элементов коллекции
for (let elem of collection) {
// для каждого элемента вызываем функцию-коллбэк
// результат записываем в массив
[Link](callback(elem) );
}
// возвращаем массив
return result;
}
// коллекция элементов p
nodes = [Link]("div p");
// функция коллбэк
let callback = elem => {
// вывод в браузер
[Link]( "<h3>" + [Link] + "</h3>");
// возврат в вызывающую функцию
return [Link];
}
[Link](fnArgNode(nodes, callback));
</script>
Функция и коллбэк для внешнего массива данных.
ПРИМЕР 11
let cars = [ <div id="app"></div>
{ <script>
id: 1, // определяем функцию
name: "Mitsubishi // 1 параметр - массив объектов
Outlander", // 2 параметр - коллбэк (код функции)
brand: "Mitsubishi", function fnArgData(data, callback) {
dvs_type: "Бензиновый", // моделируем запрос к API (на внешние ресурсы)
power_hp: "146", setTimeout(() => {
cylinders_num: "4", let line;
max_speed: "193", // цикл поиска объекта по id
image: "images/mitsubishi- for(item of data) {
[Link]" line += callback(item);
}, }
345
{ [Link]("app").innerHTML =
id: 2, line;;
name: "Skoda Octavia", }, 1000);
brand: "Skoda", }
dvs_type: "Бензиновый", // функция-коллбэк
power_hp: "110", let callback = (elem) => {
cylinders_num: "4", return `
max_speed: "203", <b><a
image: "images/skoda- href='?id=${[Link]}'>${[Link]}</a></b><br>
[Link]" Бренд: <b>${[Link]}</b><br>
}, Тип двигателя: <b>${elem.dvs_type}</b><br>
{ Мошность: <b>${elem.power_hp}</b> (л.с.)<br>
id: 3, Количество цилиндров:
name: "Toyota Corolla", <b>${elem.cylinders_num}</b><br>
brand: "Toyota", Макс. скорость: <b>${elem.max_speed}</b><br>
dvs_type: "Бензиновый", <img src='${[Link]}'><br>
power_hp: "122", `;
cylinders_num: "4", };
max_speed: "185", fnArgData(cars, callback);
image: "images/toyota- </script>
[Link]"
}
]
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Вам предложена функция auyh() со следующими аргументами:
message – текстовое сообщение;
ok – функция-коллбэк выполняемая при успешной аутификации;
cancel – функция-коллбэк выполняемая при ошибке аутификации.
<script>
// функция аутентификации
function auth(message, ok, cancel) {
var password = prompt(message);
if (password == "admin")
ok()
else
cancel();
}
// ...
</script>
Напишите функции-коллбэки ok() и cancel().
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №33 - Задание
№2» вам предложены файлы:
[Link] – шаблон основного файла приложения;
[Link] – внешний файл данных.
346
В файле [Link] подключите файл данных.
Запросите у пользователя режим отображения данных внешнего
массива. Предусмотрите два режима отображения:
таблица;
список.
Каждый из выводов выполняет своя функция-коллбэк. Коллбэк
передается в основную функцию вывода контента. Ниже представлен
фрагмент кода основного файла приложения.
// в зависимости от ввода пользователя определяем функцию callback
if (outputType == "t") {
callbackName = callback1;
}
else if (outputType == "l") {
callbackName = callback2;
}
// вызов функции вывода контента в документ
outData(callbackName);
Восстановите скрипт. Выведите результат работы.
347
Практическая работа 34
CALLBACK ФУНКЦИИ
Содержание
Стань 1.
2.
Сallback и setInterval
Сallback в методах массива
профессионалом! 3. Сallback в объекте JSON
4. Сallback в объекте RegExp
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Callback-функции чрезвычайно важны в языке JavaScript. Они есть
практически повсюду. Чтобы понимать callback-функции, нужно понимать
обычные функции ().
Функции в JavaScript — немного странная конструкция, функции в
Javascript — на самом деле объекты. А именно, объекты класса Function,
создаваемые конструктором Function. В объекте Function содержится строка
с JS-кодом данной функции.
Сallback и setInterval
Метод setInterval() неоднократно вызывает функцию или выполняет
фрагмент кода с фиксированной задержкой между каждым вызовом. Метод
возвращает идентификатор интервала, который однозначно идентифицирует
данный интервал. Используя сохраненный идентификатор, метод
setInterval() можно удалить, вызвав clearInterval(). Теперь подробнее и в
примерах.
Синтаксис:
setInterval(code);
setInterval(code, delay);
setInterval(func);
setInterval(func, delay);
setInterval(func, delay, [arg1], [arg2], ...);
Параметры:
code | func – строка кода или функция для выполнения. По
историческим причинам рекомендуется передавать фкнуцию.
delay – время в миллисекундах (тысячные доли секунды), в течение,
которого таймер должен задерживать выполнение указанной функции или
кода. Значение по умолчанию – 0 (1000 мс = 1 с).
arg1, arg2 – дополнительные аргументы, которые передаются функции,
указанной в func, по истечении времени таймера.
348
Возвращаемое значение intervalID— числовое, ненулевое значение,
которое идентифицирует таймер, созданный вызовом setInterval(), это
значение можно передать clearInterval() для отмены интервала выполнения.
Полезно знать, что setInterval() и setTimeout() используют один и тот
же пул идентификаторов и что технически clearInterval() и clearTimeout()
можно использовать как взаимозаменяемые.
ПРИМЕР 1
// определяем отложенную функцию
function sayHi() {
// вывод в консоль браузера
[Link]('Привет!');
}
// запускаем функцию на выполнение с интервалом 1 сек.
setInterval(sayHi, 1000);
clearInterval
Синтаксис:
clearInterval(intervalID);
Параметры:
intervalID – идентификатор повторяющегося действия, которое вы
хотите отменить. Этот идентификатор был возвращен соответствующим
вызовом setInterval().
ПРИМЕР 2
<head>
<style>
.show { color: black; }
.blur { color: red; }
</style>
</head>
<body>
<div id="att"> <h1>Attention!</h1> </div>
<div id="msg"> <h3>Время изучать JavaScript пришло!</h3> </div>
<script>
// функция setInterval возвращает идентификатор таймера
let intervalId = setInterval(() => {
// получаем ссылки на узлы
const attElem = [Link]("att");
const msgElem = [Link]("msg");
// управляем классом блока
[Link] = [Link] === "blur" ? "show" : "blur";
// управляем видимостью блока
[Link] = [Link] === "hidden" ? "visible" : "hidden";
}, 1000);
[Link]("идентификатор setInterval: ", intervalId);
</script>
Строго говоря, мы можем эмулировать setInterval() с помощью
рекурсивного вызова функции setTimeout().
349
ПРИМЕР 3
<head>
<style>
.show { color: black; }
.blur { color: red; }
</style>
</head>
<body>
<div id="att"> <h1>Attention!</h1> </div>
<div id="msg"> <h3>Изучайте JavaScript!</h3> </div>
<script>
// метод setTimeout с рекурсией подобен setInterval
setTimeout(callback, 1000);
// определение функции обратного вызова
function callback() {
// получаем ссылки на узлы
const attElem = [Link]("att");
const msgElem = [Link]("msg");
// управляем классом блока
[Link] = [Link] === "blur" ? "show" : "blur";
// управляем видимостью блока
[Link] = [Link] === "hidden" ? "visible" :
"hidden";
// рекурсивно запускаем функцию callback
setTimeout(callback, 1000)
}
</script>
Немного об асинхронности JS
В следующем примере функция getData() определит данные объекта
user через 5 секунд. В свою очередь, функция outData() каждые полсекунды
будет проверять наличие данных и остановит вызовы, если данные
получены.
ПРИМЕР 4
<div id="data"></div> // вывод номера запроса
<script> [Link](`Запрос ${k++}. Нет данных`);
// функция получения данных }
function getData() { else {
// моделируем запрос на внешний // иначе интерполируем переменные в строку
ресурс html = `
setTimeout(() => { <h2>Сервер вернул следующие данные:</h2>
// определяем данные объекта user Имя: <b>${[Link]}</b> <br>
user = { name: "John", login: "master" } Логин: <b>${[Link]}</b> <br>
}, 5000); `;
}; // если данные пришли, останавливаем вызовы
// функция вывода данных clearInterval(intervalId);
function outData() { }
// функция setInterval возвращает // вывод данных в браузер
идентификатор таймера [Link]("data").innerHTML =
intervalId = setInterval(() => { html;
// если данные не определены }, 500)
if ([Link] == undefined || };
[Link] == undefined) { // инициируем пустой объект
350
// формируем предупреждение user = {};
html = '<h2>Нет данных</h2>'; // счетчик количества запросов
k = 1;
// вызов функции получения данных
getData();
// вызов функции выода данных
outData();
</script>
ПРИМЕР 5
let persons = new Array ( {
{ 'id_personnel' : 5,
'id_personnel' : 1, 'name' : 'Виталина',
'surname' : 'Бородина', 'patronymic' : 'Георгиевна',
'name' : 'Ксения', 'post' : 'Преподаватель',
'patronymic' : 'Алексеевна', 'category' : 'Высшая',
'post' : 'Преподаватель', 'level_edu' : 'Высшее профессиональное ',
'category' : 'Соответствие занимаемой 'experience_total' : 36.1,
должности', 'experience_college' : 19,
'level_edu' : 'Высшее профессиональное ', 'email' : 'il4uk.v@[Link]',
'experience_total' : 21.3, 'site' : '[Link]'
'experience_college' : 14.5, } );
'email' : '', <div id="data"></div>
'site' : '' <script>
}, // функция получения данных
{ function getData() {
'id_personnel' : 2, // моделируем запрос на внешний ресурс
'surname' : 'Кошкина', setInterval(() => {
'name' : 'Вера', // генерируем случайное число
'patronymic' : 'Николаевна', i = [Link]([Link]() * 5);
'post' : 'Преподаватель', // определение данных
'category' : 'Соответствие занимаемой // используем переменную i как индекс
должности', массива
'level_edu' : 'Высшее профессиональное ', user = persons[i];
'experience_total' : 29.1, }, 5000); };
'experience_college' : 29.1, // функция вывода данных
'email' : 'koshkova_v_n@[Link]', function outData() {
'site' : '' intervalId = setInterval(() => {
}, // если данные не определены
{ if ([Link] == undefined || [Link] ==
'id_personnel' : 3, undefined)
'surname' : 'Рыбкина', // формируем предупреждение
'name' : 'Ольга', html = '<h2>Нет данных</h2>'
'patronymic' : 'Витальевна', else {
'post' : 'Преподаватель', // иначе интерполируем переменные в строку
'category' : 'Соответствие занимаемой html = `
должности', <h2>Сервер вернул следующие
'level_edu' : 'Высшее профессиональное ', данные:</h2>
'experience_total' : 21.3, Имя: <b>${[Link]}</b> <br>
'experience_college' : 14.5, Логин: <b>${[Link]}</b> <br>
'email' : 'RubkinaOlga1234@[Link]', `;
'site' : '' [Link](html);
}, }
{ // вывод данных в браузер
'id_personnel' : 4, [Link]("data").innerHTML =
'surname' : 'Маркова', html;
351
'name' : 'Елизавета', }, 500)
'patronymic' : 'Андреевна', };
'post' : 'Преподаватель', // инициируем пустой объект
'category' : 'Первая', user = {};
'level_edu' : 'Высшее профессиональное ', // вызов функции получения данных
'experience_total' : 19.11, getData();
'experience_college' : 16.5, // вызов функции выода данных
'email' : '[Link]@[Link]', outData();
'site' : '' </script>
},
ПРИМЕР 6
<script>
// инициализируем массив
var course = [
"Дизайнер интерьеров",
"Веб-дизайнер",
"Notion-дизайнер",
"UX/UI-дизайнер",
"Ландшафтный дизайнер",
"Fashion-дизайнер"
];
// перебираем элементы массива в функции коллбэк
[Link](function(el, i, course) {
[Link](++i + ". " + el);
});
</script>
ПРИМЕР 7
<h2>Многим нулям кажется, что они — орбита, по которой вращается мир</h2>
<script>
// исходный массив объектов
let teams = new Array(
{id:1, name:"Aerosmith", style:["хард-рок", "блюз-рок", "рок-н-ролл", "глэм-
метал"]},
{id:2, name:"Pink Floyd", style:["психоделический-рок", "арт-рок", "эйсид-рок",
"прогрессивный-рок"]},
{id:3, name:"The Beatles", style:["рок", "рок-н-ролл", "поп", "хард-рок"]},
{id:4, name:"AC/DC", style:["хард-рок", "блюз-рок", "рок-н-ролл"]},
{id:5, name:"Scorpions", style:["хард-рок", "глэм-метал", "хеви-метал"]},
{id:6, name:"Ленинград", style:["рок", "ска", "фолк", "панк", "панк-рок"]}
);
// определение функции выносим за цикл forEach
352
// стрелочная функция должна быть определена до вызова
let callback = item => {
// сериализуем в строку свойство объекта style
[Link] = [Link]([Link]);
};
// исходный код функции
// [Link](callback);
// перебираем элементы массива
[Link] (callback);
// вывод результата
[Link](teams);
</script>
Метод forEach ничего не возвращает, его используют только для
перебора, как более элегантный вариант, чем обычный цикл for.
filter
Метод filter(callback) используется для фильтрации массива через
функцию обратного вызова. Создаёт новый массив, в который войдут
только те элементы исходного массива, для которых вызов callback(item, i,
arr) возвратит true (конструкция return функции коллбэк).
ПРИМЕР 8
<script>
// массив скалярных значений
var course = [
"Дизайнер визуальных коммуникаций",
"Ювелирный 3D-модельер",
"Fashion-стилист",
"Fashion-фотограф",
"BIM-координатор с нуля",
"Маркетинг для fashion-брендов",
"Продюсер в Fashion"
];
// создаем новый массив
var fashionCourse = [Link](callback);
// определение функции обратного вызова
// определение функции-инструкции можно выполнить после вызова
function callback(el) {
// проверяем наличие в элементе массива вхождения подстроки
reg = RegExp(/fashion/, "i");
return [Link](el);
}
// проверяем элементы нового массива
[Link](fashionCourse);
</script>
Обратите внимание, метод forEach() просто перебирает исходный
массив, тогда как filter() формирует новый массив, но структура массива при
этом остается прежней. Метод filter() возвращает или нет текущий элемент
исходного массива в зависимости от значения конструкции return.
В коде примера ниже тернарный оператор возвращает true и тогда
текущий элемент попадает в новый массив, или false.
353
ПРИМЕР 9
<script>
// исходный массив
let courses = [
{id: 1, name: "JavaScript разработчик с нуля", time: "7 месяцев", shedule: "По
будним дням 13:00-15:00", level: "Junior", teacher: "Данилов В.Е.", price: 40000},
{id: 2, name: "Python-рузработчик", time: "12 месяцев", shedule: "По будним
дням 12:00-15:00", level: "Middle", teacher: "Ливанов Б.В.", price: 55000},
{id: 3, name: "Data Scientist", time: "10 месяцев", shedule: "По выходным
18:00-20:00", level: "Junior", teacher: "Вавилов Н.И.", price: 48000},
{id: 4, name:"Фронтенд-разработчик на JavaScript", time: "3 месяца", shedule:
"По будним дням, по согласованию", level: "Middle", teacher: "Карасев Ю.И.", price:
65000},
];
// функция коллбэк
let fnCallback = (item) => {
// элемент массива возвращается при предикате равном true
return [Link](criterion) ? true : false;
}
// критерий фильтрации
const criterion = "JavaScript";
// находит вхождения
// или возвращает пустой массив - []
let courseJS = [Link] (fnCallback);
[Link]("Исходный массив:");
[Link](courses);
[Link]("Результат фильтрации:");
[Link](courseJS);
</script>
Для трансформации массива используйте цикл map.
map
Метод map(callback) используется для трансформации массива.
Создаёт новый массив, который будет состоять из результатов вызова
callback(item, i, arr) для каждого элемента arr.
ПРИМЕР 10
cars = [
['1', 'Toyota', 'Toyota Land Cruiser', 'Дизельный', '249', 'V-образный', '4461', '8',
'images/[Link]'],
['2', 'Toyota', 'Toyota Land Cruiser Prado', 'Бензиновый', '163', 'Рядный', '2694', '4',
'images/[Link]'],
['3', 'Toyota', 'Toyota Camry', 'Бензиновый', '150', 'Рядный', '1998', '4',
'images/[Link]'],
['4', 'BMW', 'BMW 3', 'Дизельный', '190', 'Рядный', '1995', '4', 'images/[Link]'],
]
<script>
// преобразуем массив cars
var dieselCars = [Link](callback);
// функцию инструкцию можно объявить после вызова
function callback(item, i, cars) {
// критерий поиска - дизельный двигатель
reg = RegExp(/дизель/, "i");
354
// если предикат true - возвращаем название
// иначе - null
if ([Link](item[3])) return item[2];
else return null;
}
// вывод исходного массива
[Link](cars);
// вывод дизельных авто из массива
[Link](dieselCars);
</script>
every/some
Эти методы используются для проверки массива.
Метод every(callback) возвращает true, если вызов callback вернёт true
для каждого элемента arr.
Метод some(callback) возвращает true, если вызов callback вернёт true
для какого-нибудь элемента arr.
Тестируем метод every.
ПРИМЕР 11
let televisions = [
["24", "LED", "60 Гц", "DEXP", "H24F7000E", "HD", "80.499 ₽",
"img/[Link]", `Телевизор LED DEXP H24F7000E отличается компактными
размерами.`],
["24", "LED", "60 Гц", "Telefunken", "TF-LED24S19T2", "HD", "70.990 ₽", "img/TF-
[Link]", `Телевизор Telefunken оснащен экраном с диагональю 60 см.`],
["24", "LED", "50 Гц", "Harper", "24R470T", "HD", "100.000 ₽", "img/[Link]",
`Телевизор LED Harper 24R470T – это небольшое устройство с диагональю экрана
24" (61 см) в черном корпусе.`],
["55", "OLED", "120 Гц", "Sony", "XR55A90JCEP", "4K UltraHD", "120.999 ₽",
"img/[Link]", `Телевизор OLED Sony XR55A90JCEP выполнен по
технологии OLED.`],
];
<script>
// определяем коллбэк функции
// все ли телевизоры имеют частоту более 60 Гц
function checkFreq(item, i, televisions) {
if (parseInt(item[2]) >= 60)
return true;
}
// все ли телевизоры имеют LED Матрицу
function checkMatrix(item, i) {
if ( /led|LED/.test(item[1]))
return true;
}
// есть ли телевизоры дороже 200.000
function checkPrice(item) {
if (parseFloat(item[6]) > 70)
return true;
}
[Link]("Тестируем -Every");
[Link]("-> все ли телевизоры имеют частоту более 60 Гц ?");
355
[Link]([Link](checkFreq));
[Link]("-> все ли телевизоры имеют LED Матрицу ?");
[Link]([Link](checkMatrix));
[Link]("-> есть ли телевизоры дороже 200.000 ?");
[Link]([Link](checkPrice));
</script>
Тестируем метод some.
ПРИМЕР 12
let televisions = [
["24", "LED", "60 Гц", "DEXP", "H24F7000E", "HD", "80.499 ₽",
"img/[Link]", `Телевизор LED DEXP H24F7000E отличается компактными
размерами.`],
["24", "LED", "60 Гц", "Telefunken", "TF-LED24S19T2", "HD", "70.990 ₽", "img/TF-
[Link]", `Телевизор Telefunken оснащен экраном с диагональю 60 см.`],
["24", "LED", "50 Гц", "Harper", "24R470T", "HD", "100.000 ₽", "img/[Link]",
`Телевизор LED Harper 24R470T – это небольшое устройство с диагональю экрана
24" (61 см) в черном корпусе.`],
["55", "OLED", "120 Гц", "Sony", "XR55A90JCEP", "4K UltraHD", "120.999 ₽",
"img/[Link]", `Телевизор OLED Sony XR55A90JCEP выполнен по
технологии OLED.`],
];
<script>
// определяем коллбэк функции
// все ли телевизоры имеют частоту более 60 Гц
function checkFreq(item) {
if (parseInt(item[2]) >= 60)
return true;
}
// все ли телевизоры имеют LED Матрицу
function checkMatrix(item, i) {
if (/led|LED/.test(item[1]))
return true;
}
// есть ли телевизоры дороже 200.000
function checkPrice(item, i, televisions) {
if (parseFloat(item[6]) > 70)
return true;
}
[Link]("Тестируем -Some");
[Link]("-> все ли телевизоры имеют частоту более 60 Гц ?");
[Link]([Link](checkFreq));
[Link]("-> все ли телевизоры имеют LED Матрицу ?");
[Link]([Link](checkMatrix));
[Link]("-> есть ли телевизоры дороже 200.000 ?");
[Link]([Link](checkPrice));
</script>
356
Синтаксис:
let json = [Link](value, [replacer, space]);
Параметры:
value – значение для кодирования.
replacer – массив свойств для кодирования или функция
соответствия, которая будет вызываться для каждой пары (key, value).
space – дополнительное пространство (отступы), используемое для
форматирования.
В большинстве случаев stringify используется только с первым
аргументом. Но если нужно настроить процесс преобразования, то можно
использовать второй аргумент. Второй аргумент либо массив свойств для
кодирования, либо функция соответствия.
ПРИМЕР 13
<script>
// определение исходного JS-объекта
let person = {
surname : "Бородина",
name : "Ксения",
patronymic : "Алексеевна",
category : "Соответствие занимаемой должности",
post : "Преподаватель",
level_edu : "Высшее профессиональное",
email : "borodina-x@[Link]",
phone : "2-12-85-0A",
experience_college : 14.5
};
// сериализуем JSON с дополнительной функцией
personJSON = [Link](person, fnCollback);
// вывод сериализованного JSON
[Link](personJSON);
// функция преобразования
function fnCollback (key, value) {
if (key == "experience_college") return undefined;
if (key == "email" ) return "metodic@[Link]";
if (key == "phone") return "Скрыто пользователем";
// по умолчанию возвращаем исходное значение - value
return value;
}
</script>
[Link]
Чтобы декодировать JSON-строку нужен метод parse(). Метод
преобразует строку JSON в соответствующее значение JavaScript.
Если во время преобразования в строке JSON встретится значение
undefined, то оно будет опущено (не будет включено в результат).
Синтаксис:
let value = [Link](str, [reviver]);
357
Параметры:
str - JSON для преобразования в объект.
reviver - необязательная функция, которая будет вызываться для
каждой пары (key, value) и может преобразовывать значение.
ПРИМЕР 14
<script>
// определение JSON-строки
let personJSON = `{
"surname" : "Бородина",
"name" : "Ксения",
"post" : "Преподаватель",
"email" : "borodina-x@[Link]",
"phone" : "2-12-85-0A",
"experience_college" : 14.5
}`;
// парсим JSON с дополнительной функцией
// коллбэк встроен в метод parse
let person = [Link](personJSON, function (key, value) {
if (key == "experience_college") return undefined;
if (key=="phone") return "*****";
if (key == "email" ) return "metodic@[Link]";
// по умолчанию возвращаем исходное значение - value
return value;
});
// вывод в консоль результата преобразования
[Link](person);
</script>
В примере правило сериализации определим через функцию
соответствия function(key, value). Эта функция вызывается для каждой пары
key, value и может менять правила преобразования.
Callback в объекте RegExp
Коллбэк (callback) в регулярных выражениях (RegExp) дает
неограниченные возможности управления DOM-документа. Но есть важный
момент.
Первый пример преобразования с дополнительной функцией
достаточно простой. Функция callback получает на вход результат поиска с
использованием шаблона.
// глобальный шаблон поиска
let reg = new RegExp("[a-z]{3,}", "ig");
// метод replace вызовет callback для каждой найденной с помощью шаблона
строки
let edit_text = [Link](reg, callback); // вызов callback
ПРИМЕР 15
<h2>Исходный текст</h2>
<div id="text">
358
<p> JavaScript — мультипарадигменный язык программирования. Поддерживает
объектно-ориентированный, императивный и функциональный стили. Является
реализацией спецификации ECMAScript. </p>
<p> JavaScript обычно используется как встраиваемый язык для программного доступа
к объектам приложений. Наиболее широкое применение находит в браузерах как язык
сценариев для придания интерактивности веб-страницам. </p>
<p> Основные архитектурные черты JavaScript: динамическая типизация, слабая
типизация, автоматическое управление памятью, прототипное программирование,
функции как объекты первого класса. </p>
<p> На JavaScript оказали влияние многие языки, при разработке была цель сделать
язык похожим на Java. Языком JavaScript не владеет какая-либо компания или
организация, что отличает его от ряда языков программирования, используемых в веб-
разработке. </p>
</div>
<h2>Редактированный текст</h2>
<div id="edit"></div>
<script>
// строка в которой будем искать совпадение с шаблоном
let text = [Link]("div#text").innerHTML;
callback = (elem) => {
elem = "<b>" + elem + "</b>";
// возвращаем преобразованный элемент
return elem;
}
// глобальный шаблон поиска
let reg = new RegExp("[a-z]{3,}", "ig");
// поиск и замена
let edit_text = [Link](reg, callback);
// вставляем в документ измененный текст
[Link]("div#edit").innerHTML = edit_text;
</script>
ПРИМЕР 16
<div>
<p>1. <b>Я спокоен</b> <img src='….jpg' width='150px'> </p>
<p>2. <b>Я открыт к позитивным изменениям</b> <img src='….jpg' width='150px'> </p>
<p>3. <b>Из тела уходит напряжение</b> <img src='….jpg' width='150px'> </p>
<p>4. <b>Я хорошо справляюсь с любыми трудностями</b> <img src=....jpg'
width='150px'> </p>
<p>5. <b>Мне хорошо и уютно</b> <img src='....jpg' width='150px'> </p>
</div>
<script>
// функция коллбэк
fnCallback = (el) => {
// [Link](el);
// match с флагом -g и без него дадут разный результат
let info = [Link](/pict[1-5]\.jpg/);
// [Link](info);
return `<img src="[Link]" title="Исходное изображение: ${info[0]}"
width="200px">`;
}
// забираем из документа HTML-содержимое блока div
var str = [Link]("div").innerHTML;
// получаем обновленый текстовый контент
var newstr = [Link](/<img .*>/g, fnCallback);
// замещаем блок div новым контентом
[Link]("div").innerHTML = newstr;
</script>
359
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №34 - Задание
№1» вам предложены файлы:
[Link] – основной файл приложения.
[Link] – внешний файл данных приложения.
Основной файл приложения содержит код асинхронного перебора
объектов массива persons.
Ревьюируйте код таким образом, чтобы при выводе объекта с
id_personnel = 4 функции setInterval прерывали свой вызов. Удалите
последующий вызов обеих функций.
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №34 - Задание
№2» вам предложен шаблон сценария файла приложения [Link].
Напишите программу для преобразования текстовых данных в ссылку
или изображение. Фамилию, имя, отчество автора выделите жирным.
Протестируйте работоспособность ссылок.
360
Практическая работа 35
Содержание
Стань 1. Контекст и ключевое слово this
2. Явная привязка контекста
профессионалом! 3. Контекст и модули
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Контекст – это то, на что указывает ключевое слово this. По сути this –
ссылка на объект, которому принадлежит выполняемый в данный момент
код. Ключевое свойство this – это свойство объекта лексического окружения
(Environment Record).
Поведение ключевого слова this зависит от контекста, в котором оно
используется, и от того, в каком режиме оно используется - строгом или
нестрогом.
Глобальный контекст
В глобальном контексте this ссылается на глобальный объект.
Глобальным объектом веб-браузера является объект Window (глобальный
объект, который представляет окно браузера).
Консольный вывод глобального объекта можно получить при
выполнении следующего кода:
// в глобальном контексте this ссылается на глобальный объект window
[Link]('this:');
[Link](this);
Когда мы создаем глобальные переменные, то они автоматически
начинают принадлежать глобальному объекту Window – самому главному
объекту в браузере.
Например, стандартные методы, которыми мы часто пользуемся,
находятся внутри объекта Window и являются его методами:
[Link](),
alert,
prompt и т.д.
Это легко проверить. Достаточно вызвать эти методы следующим
образом:
[Link]('Привет');
361
[Link]('Привет');
[Link]('Как тебя зовут?');
Ссылка this – это не всегда глобальный объект. Во вложенном
(локальном) лексическом окружении, this это ссылка на родительское
лексическое окружение. Или, другими словами, ссылка на объект,
которому принадлежат переменные и функции текущей области видимости.
Глобальный контекст globalThis
Так как в локальном контексте this не всегда глобальный объект
Window, в стандарт ES2020 было добавлено определение объекта globalThis.
Объект globalThis позволяет ссылаться на глобальный контекст вне
зависимости, в какой среде и в какой ситуации выполняется код:
// globalThis всегда глобальный объект
[Link]('globalThis:');
[Link](globalThis);
В примере ниже приведен набор переменных и функций,
принадлежащих глобальному контексту.
ПРИМЕР 1
<script>
// набор глобальных переменных
var aVar = "I am a VAR variable";
let aLet = "I am a LET variable";
const aCONST = 'I am a CONST';
aWithOut = "I am a WITHOUT variable";
// функция инструкция
function aFnStatement() {
[Link]('I am a FUNCTION STATEMENT');
}
// функция выражение
var aFnExpression = function () {
[Link]("I'm a FUNCTION EXPRESSION");
}
// функция стрелка
var aFnArrow = () => {
[Link]("I'm a FUNCTION ARROW");
}
// объект
var aMyObj = {
name: "master",
login: "qwerty",
fn: function() {
[Link]("I am a FUNCTION METHOD");
}
};
[Link]([Link]); // I am a VAR variable
[Link]([Link]); // undefined
[Link]([Link]); // undefined
[Link]([Link]); // I am a WITHOUT variable
[Link]([Link]); // function aFnStatement()
362
[Link]([Link]); // function aFnExpression()
[Link]([Link]); // function aFnArrow()
[Link]([Link]); // Object
</script>
ПРИМЕР 2
<script>
// функция инструкция
function aFnStatement() {
[Link]('I am a FUNCTION STATEMENT');
[Link](this);
}
// функция выражение
var aFnExpression = function () {
[Link]("I'm a FUNCTION EXPRESSION");
[Link](this);
}
// функция стрелка
var aFnArrow = () => {
[Link]("I'm a FUNCTION ARROW");
[Link](this);
}
// объект
var aMyObj = {
methodExpr: function() {
[Link]("I'm a METHOD Expression Object");
[Link](this);
363
},
methodArrow: () => {
[Link]("I'm a METHOD Arrow Object");
[Link](this);
}
};
// глобальный объект window
[Link](this);
aFnStatement(); // window
aFnExpression(); // window
aFnArrow(); // window
[Link](); // Object
[Link](); // window
</script>
Контекст функции инструкции
В пределах функции инструкции ссылки this и globalThis ссылаются на
внешний контекст. Для функций, определенных в глобальном контексте —
это объект Window.
ПРИМЕР 3
<script>
// функция инструкция
function fnStatement() {
// локальная переменная name
let name = "I'm Silvija";
[Link](name); // I'm Silvija
[Link]([Link]); // My name is Bond. James Bond
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
fnStatement();
</script>
В примере далее рассмотрим контекст вложенных функций.
ПРИМЕР 4
<script>
// внешняя функция инструкция
function fnOuterStatement() {
// локальная переменная name
let name = "I'm Silvija";
// вложенная функция инструкция
function fnInnerStatement() {
// локальная переменная name
let name = 'Who am I?';
[Link](name); // Who am I?
[Link]([Link]); // My name is Bond. James Bond
}
// вызов вложенной функции
fnInnerStatement();
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
364
// вызов внешней функции
fnOuterStatement();
</script>
Если использовать строгий режим - strict mode, то в этом случае this
имеет значение undefined. GlobalThis значение не меняет.
ПРИМЕР 5
<script>
// внешняя функция инструкция
function fnOuterStatement() {
// включаем строгий режим
"use strict";
// локальная переменная name
let name = "I'm Silvija";
// вложенная функция инструкция
function fnInnerStatement() {
// локальная переменная name
let name = 'Who am I?';
[Link](name); // Who am I?
[Link](this); // undefined
[Link](globalThis); // window
}
// вызов вложенной функции
fnInnerStatement();
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
// вызов внешней функции
fnOuterStatement();
</script>
Таким образом. Контекст (this) – функции инструкции всегда
глобальный window. В режиме strict mode – undefined.
Контекст функции выражения
Поведение функций выражений похоже на поведение функций
инструкций.
ПРИМЕР 6
<script>
// внешняя функция выражение
fnOuterExpression = function () {
// локальная переменная name
let name = "I'm Silvija";
// вложенная функция выражение
fnInnerExpression = function() {
// локальная переменная name
var name = "Who am I?";
[Link](name); // Who am I?
[Link]([Link]); // My name is Bond. James Bond
}
// вызов вложенной функции
fnInnerExpression();
365
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
// вызов внешней функции
fnOuterExpression();
</script>
Если использовать строгий режим - strict mode, то this имеет значение
undefined. GlobalThis значение не меняет.
ПРИМЕР 7
<script>
// внешняя функция выражение
fnOuterExpression = function () {
// включаем строгий режим
'use strict';
// локальная переменная name
var name = "I'm Silvija";
// вложенная функция выражение
let fnInnerExpression = function() {
[Link](name); // I'm Silvija
[Link](this); // undefined
[Link](globalThis); // window
}
// вызов вложенной функции
fnInnerExpression();
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
// вызов внешней функции
fnOuterExpression();
</script>
Таким образом. Контекст (this) – функции выражения всегда
глобальный window. В режиме strict mode – undefined.
Контекст стрелочной функции
Поведение стрелочных функций на первых порах может преподносить
некоторые сюрпризы.
ПРИМЕР 8
<script>
// внешняя функция стрелка
fnOuterArrow = () => {
// локальная переменная name
let name = "I'm Silvija";
// вложенная функция стрелка
let fnInnerArrow = () => {
[Link](name); // I'm Silvija
[Link]([Link]); // My name is Bond. James Bond
}
// вызов вложенной функции
fnInnerArrow();
};
366
// глобальная переменная name
var name = "My name is Bond. James Bond";
// вызов внешней функции
fnOuterArrow();
</script>
В строгом режиме стрелочная функция контекст не меняет.
ПРИМЕР 9
<script>
// внешняя функция стрелка
fnOuterArrow = () => {
// включаем строгий режим
// 'use strict';
// локальная переменная name
let name = "I'm Silvija";
// вложенная функция стрелка
let fnInnerArrow = () => {
[Link](name); // I'm Silvija
[Link]([Link]); // My name is Bond. James Bond
}
// вызов вложенной функции
fnInnerArrow();
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
// вызов внешней функции
fnOuterArrow();
</script>
Таким образом. Контекст (this) – функции стрелки всегда глобальный
window. В режиме strict mode – стрелочная функция контекст не меняет.
Важно!
Контекст (this) – функции инструкции и функции выражение –
глобальный window. В режиме strict mode – undefined.
Контекст стрелочной функции всегда window.
Контекст объекта
В контексте объекта, в том числе в его методах, ключевое слово this
ссылается на этот же объект.
ПРИМЕР 10
<script>
// определене объекта
let obj = {
mtdStatement: function () {
[Link]('Метод-выражение');
[Link](this);
},
mtdArrow: () => {
[Link]('Метод-стрелка');
367
[Link](this);
}
};
// вызов методов объекта
[Link](); // Object
[Link](); // window
</script>
ПРИМЕР 11
<script>
myFn = function () {
// локальная переменная name
var name = "I'm Silvija";
[Link](name); // I'm Silvija
[Link]([Link]); // No Name
[Link]([Link]); // My name is Bond. James Bond
}
// определене объекта
let obj = {
// name - свойство объекта
name: "No Name",
mtdStatement: myFn,
mtdArrow: () => {
// локальная переменная name
[Link](name); // My name is Bond. James Bond
[Link]([Link]); // My name is Bond. James Bond
[Link]([Link]); // My name is Bond. James Bond
}
};
// глобальная переменная name
var name = "My name is Bond. James Bond";
// вызов методов объекта
[Link]();
// [Link]();
</script>
Важно!
Контекст метода (функции) выражения ссылается на сам объект.
Контекст метода (функции) стрелки – глобальный window.
ПРИМЕР 12
<script>
// глобальные переменые
var login = "Login is not defined";
var pwd = "Password is not defined";
var email = "Email is not defined";
// объект user
var user = {
// свойства объекта
login: "Den",
pwd: "SuperAdmin",
email: "denis@[Link]"
}
// определение функции вывода привязанных к контексту данных
function fnOutData() {
[Link]([Link]);
[Link]([Link]);
[Link]([Link]);
}
// вызов функции в контексте глобального объекта
[Link]();
// вызов функции в контексте глобального объекта
// альтернативный вариант
// [Link](this);
// вызоа функции в контексте объекта 'user'
// [Link](user);
</script>
Любая функция может в своём коде использовать контекст this, каким
будет это значение – выяснится в момент запуска функции.
ПРИМЕР 13
<script>
// дефолтные переменные глобального window
var id = 13;
var name = "LADA Kalina";
369
var brand = "АвтоВАЗ";
var type = "Бензиновый";
var power = "90";
var image = "[Link]";
// переменные можно сохранить в объекте
var lada = {
id: 13,
name: "LADA Kalina",
brand: "АвтоВАЗ",
type: "Бензиновый",
power: "90",
image: "[Link]"
}
// объект toyota
const toyota = {
id: 2,
name: "Toyota Land Cruiser",
brand: "Toyota",
type: "Дизельный",
power: "249",
image: "[Link]"
}
// объект kia
const kia = {
id: 7,
name: "Kia Sorento Prime",
brand: "Kia",
type: "Дизельный",
power: "200",
image: "[Link]"
}
// объявление функции outData
const fnOutData = function(msg) {
// контекст this будет определен во время вызова
let html = `
<h2>${msg}</h2>
<h3>${[Link]}</h3>
Бренд: <b> ${[Link]} </b><br>
Тип двигателя: <b> ${[Link]} </b><br>
Мощность (л.с): <b> ${[Link]} </b><br>
<img src="images/${[Link]}" width='250px'> <br>
`;
return html;
}
// в каждый из вызовов добавим дополнительный параметр
// функция в контексте объекта
[Link]([Link](kia, "Корейский автопром рулит?"));
// функция в контексте объекта
// [Link]([Link](toyota, "Япония, вперед!"));
// функция в контексте глобального window
// [Link]([Link](this, "Упс... Это вам )"));
// функция в контексте объекта глобального window
// [Link]([Link]([Link], "Можно оформить объектом... )"));
</script>
370
ПРИМЕР 14
<script>
let fnDeclare = {
// объявление метода объекта
mtdOutData: function(msg) {
// контекст this будет определен во время вызова
let html = `
<h2>${msg}</h2>
<h3>${[Link]}</h3>
Бренд: <b> ${[Link]} </b><br>
Тип двигателя: <b> ${[Link]} </b><br>
Мощность (л.с): <b> ${[Link]} </b><br>
<img src="images/${[Link]}" width='250px'> <br>
`;
return html;
}
}
// объект lada
let lada = {
id: 13,
name: "LADA Kalina",
brand: "АвтоВАЗ",
type: "Бензиновый",
power: "90",
image: "[Link]"
}
// объект toyota
let toyota = {
id: 2,
name: "Toyota Land Cruiser",
brand: "Toyota",
type: "Дизельный",
power: "249",
image: "[Link]"
}
// объект kia
let kia = {
id: 7,
name: "Kia Sorento Prime",
brand: "Kia",
type: "Дизельный",
power: "200",
image: "[Link]"
}
// в каждый из вызовов добавим дополнительный параметр
// функция в контексте объекта
[Link]([Link](kia, "Корейский автопром рулит?"));
// функция в контексте объекта
// [Link]([Link](toyota, "Япония, вперед!"));
// функция в контексте глобального window
// [Link]([Link](lada, "Владейте на здоровье :("));
</script>
Если заранее неизвестно, с каким количеством аргументов понадобится
вызвать функцию, можно использовать более мощный метод: apply().
371
apply
Метод apply() аналогичен методу call(). Единственное отличие в том,
что аргументы в apply передаются в виде массива.
Синтаксис:
[Link](thisArg, argsArray);
Если в call() параметры функции передаются через запятую, то метод
apply() должен передавать параметры функции в массиве.
Параметры:
thisArg – Значение this, предоставленное для вызова функции myFunc.
argsArray – Необязательный. Объект, определяющий аргументы, с
которыми следует вызывать функцию, или null если функции не следует
предоставлять аргументы.
Возвращаемое значение: результат вызова функции с указанным this
значением и аргументами.
Обратите внимание, вызов: [Link] (context, array); – эквивалентен
обычному вызову функции: func (...rest); но с явно указанным контекстом this
(context).
ПРИМЕР 15
<script>
// массив для передачи в функцию
let block = Array(
`<header>
<h1 align="center">Лексическое окружение и контекст</h1>
</header>`,
`<footer align="center">
<h3>Верстка | Дизайн | Программирование</h3>
</footer>`
);
/*
block[0] - header
block[1] - footer
*/
// набор глобальных переменных
var name = "No name";
var login = "undefined";
var email = "hidden";
var role = "lamer";
var image = "[Link]";
// объект
var user = {
name: "Злой Бармалей",
login: "SuperAdmin",
email: "super-admin@[Link]",
role: "administrator",
image: "[Link]"
}
// параметр - массив
372
function outUserInfo(...rest) {
// формирование блока для вывода
let html = `
${rest[0]}
${[Link]} <br>
${[Link]} <br>
${[Link]} <br>
<img src="${[Link]}" width="250px"> <br>
${rest[1]}
`;
// возвращаем блок вывода
return html;
}
// параметр - массив block
[Link]([Link](this, block));
// [Link]([Link](user, block));
</script>
ПРИМЕР 16
var orders = [ <script>
{ bill: "N-2201/11-5", // номер счета
vendor: { var bill = "N-1103/12-1";
date: "15.01.2023", // функция поиска заказа по номеру
name: "Иоганн Кристоф Фридрих фон счета
Шиллер", orderSearch = function () {
discount: 0, let obj = [Link] ( obj => {
payment: "Нет" }, return [Link] == bill;
product: [ });
{ id: 2, //
title: 'Ультрабук HUAWEI MateBook D 15 return {
BoM-WFQ9', vendor: [Link],
gpu: 'AMD Radeon Graphics', product: [Link]
cpu: 'AMD Ryzen 5 5500U', };
cpu_cores: 6, }
ram: '16 ГБ', // функция вывода заказа
diagonal: "15.6'", function outProduct(name, date, payment) {
price: 62.999, [Link] (`
img: "[Link]" <h3>${[Link]}</h3>
} ] }, Заказчик: <b>${name}</b> <br>
{ bill: "N-1103/12-1", CPU / ${[Link]} <br>
vendor: { GPU / ${[Link]} <br>
date: "12.01.2023", <img src='images/${[Link]}'> <br>
name: "Гегель Георг Вильгельм Фридрих", Счет: от ${date}. Оплачено: ${payment}
discount: 15, <hr>
payment: "Нет" }, `);
product: [ { }
id: 1, // поиск счета
title: 'Ноутбук HUAWEI MateBook D16 RLEF- let order = orderSearch();
X', /*
gpu: 'Intel Iris Xe Graphics', структура возвращаемого объекта
cpu: 'Intel Core i5-12500H', order = {}
cpu_cores: 12, [Link]
ram: '16 ГБ', [Link]
diagonal: "16'", */
price: 76.299, // для каждого товара счета вызываем
img: "[Link]" }, outProduct для вывода
{ id: 3, for (product of [Link]){
title: 'Ноутбук MSI GF76 Katana 11SC- // вызываем функцию outProduct в
483XRU', контексте объекта product
373
gpu: 'GeForce GTX 1650', [Link](product,
cpu: 'Intel Core i5-11400H', [[Link], [Link],
cpu_cores: 6, [Link]]);
ram: '8 ГБ', }
diagonal: "17.3'", </script>
price: 59.399,
img: "[Link]"
}] }]
bind
Метод bind() создает новую функцию, с указанным значением this и
индивидуально предоставленными аргументами.
Синтаксис:
fun = [Link](thisArg, argsArray);
Функция bind() создает новую связанную функцию. Вызов связанной
функции обычно приводит к выполнению функции, которую она обертывает,
которая также называется целевой функцией. Связанная функция сохранит
переданные параметры, включая значение this как свое внутреннее
состояние.
Возвращаемое значение: Копия данной функции с указанным this
значением и начальными аргументами (если они предусмотрены).
Обратите внимание, вызов: fn = [Link] (context, a, b, с); – эквивалентен
обычному вызову функции: fn = func (a, b, с); но с явно указанным контекстом
this (context).
ПРИМЕР 17
<script>
// набор глобальных переменных
var title = "Not defined";
var brand = "Not defined";
var color = "Not defined";
var country = "Not defined";
var img = "[Link]";
// массив объектов
var clothes = [
{
id: 1,
title: 'Утепленная стеганая куртка',
brand: 'MARCO DI RADI',
color: 'Синий',
country: 'Китай',
img: '[Link]'
},
{
id: 2,
title: 'Пальто',
brand: 'Allsaints',
color: 'Коричневый',
country: 'Китай',
img: '[Link]'
374
}
];
// объект c функцией-методом для вывода
var order = {
outOrder: function () {
[Link] (`
Название: ${[Link]} <br>
Бренд: ${[Link]} <br>
Цвет: ${[Link]} <br>
Страна: ${[Link]} <br>
<img src='images/${[Link]}' width='200px'>
<hr>
`);
}
}
// метод call сравним с методом bind
[Link](clothes[0]);
// метод bind в контексте this
fn1 = [Link]();
// метод bind в контексте объекта
fn2 = [Link](clothes[1]);
// вызов результата
fn1();
// fn2();
</script>
Контекст и модули
При работе с модулями обратите внимание:
Каждый модуль имеет свою собственную область видимости.
Таким образом:
переменные и функции, объявленные в модуле, не видны в других
скриптах.
Модули всегда выполняются в отложенном (deferred) режиме точно так
же, как скрипты с атрибутом defer. Это верно и для внешних и встроенных
скриптов-модулей.
Таким образом:
загрузка внешних модулей не блокирует обработку HTML;
модули, даже если загрузились быстро, ожидают полной загрузки
HTML документа, и только затем выполняются;
сохраняется относительный порядок скриптов: скрипты, которые идут
раньше в документе, выполняются раньше;
модули всегда видят полностью загруженную HTML-страницу,
включая элементы под ними.
При необходимости передачи данных между модулями можно
воспользоваться глобальным объектом window (что допустимо, но не очень
желательно). Или воспользоваться объектом веб-хранилища, например:
localStorage.
375
При работе с объектами хранилища помните, что ключ и значение
объекта должны быть строками. Если мы используем любой другой тип,
например число, массив или объект, то он автоматически преобразуется в
строку.
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
В папке «Раздаточный материал - Практическая работа №35 - Задание
№1» вам предложен файл [Link].
1. Подключите массив объектов cars в сценарии файла [Link].
2. Напишите функцию для поиска объекта в подключенном массиве по
случайно сгенерированному индентификатору.
let maxCount = [Link];
let id = [Link]([Link]() * (maxCount - 1) + 1);
3. Используйте написанную функцию в определении контекста метода
call. Выведите в браузер найденный объект массива cars.
// вызов функции в контексте объекта
[Link]([Link](getCar(id)));
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №35 - Задание
№2» вам предложены следующие файлы:
[Link] – основной сценарий, вход в приложение.
[Link] – массив объектов товаров.
images – директория хранения изображений.
Используя файлы раздаточного материала, выполните следующие
задания:
подключите массив товаров к основному сценарию;
напишите функцию отбора товаров с категорией category="laptop";
используя шаблон, напишите функцию вывода в браузер отобранных
товаров.
376
Практическая работа 36
ЗАМЫКАНИЕ
Содержание
Стань 1. Что такое замыкание
2. Практика применений замыканий
профессионалом! 3. Приватные переменные
ТЕОРЕТИЧЕСКИЙ МАТЕРИАЛ
Потеря контекста
В этом разделе делаем упор на разбор ситуаций, при которых может
теряться контекст метода (функции) объекта. Как только метод передаётся
отдельно от объекта – this используемый в функции-методе объекта теряется.
Прежде, чем приступить к изучению причин потери контекста,
разберем вводный пример.
ПРИМЕР 1
<script>
// определение объекта
let user = {
login: "DenisDream",
// метод объекта
welcome: function() {
return `Привет, ${[Link]}!`;
}
};
// вывод определения метода объекта в консоль
[Link]([Link]);
/*
консоль:
ƒ () {
return `Привет, ${[Link]}!`;
}
*/
// [Link] <> [Link]()
// запуск метода в контексте объекта
[Link]([Link]());
/*
консоль:
Привет, DenisDream!
*/
</script>
377
В данном примере особое внимание обратите на следующие строки
кода:
// вывод определения метода объекта в консоль
[Link]([Link]);
/*
консоль:
ƒ () {
return `Привет, ${[Link]}!`;
}
*/
Именно на понимании семантики данной синтаксической
конструкции будет построен весь урок. К этой конструкции в той или иной
степени мы будем обращаться на протяжении всего урока.
Потеря контекста в глобальном объекте window
ПРИМЕР 2
<script>
// глобальная переменная
var login = "GlobalLogin";
// объект
let user = {
login: "DenisDream",
// метод объекта
welcome: function () {
return `Привет, ${[Link]}!`;
}
};
let msg = [Link];
// просмотр содержимого переменной msg
[Link] (msg);
/*
консоль:
ƒ () {
return `Привет, ${[Link]}!`;
}
*/
// потеря контекста в глобальном объекте window
[Link] (msg()); // Привет, GlobalLogin!
// запуск метода в контексте объекта
[Link]([Link]()); // Привет, DenisDream!
</script>
Потеря контекста в функции с аргументом callback
ПРИМЕР 3
<script>
// глобальная переменная
var login = "GlobalLogin";
// объект
let user = {
login: "DenisDream",
// метод объекта
378
welcome: function() {
return `Привет, ${[Link]}!`;
}
};
// описание функции
function fnTestCallback (callback) {
// login = "None";
[Link](callback);
/*
консоль:
ƒ () {
return `Привет, ${[Link]}!`;
}
*/
// вызов функции callback
// callback = welcome()
// callback() = welcome()()
[Link](callback()); // Привет, GlobalLogin!
}
// потеря контекста в функции c аргументом callback
fnTestCallback([Link]);
// запуск метода в контексте объекта
[Link]([Link]()); // Привет, DenisDream!
</script>
Потеря контекста в асинхронном вызове
ПРИМЕР 4
<script>
// глобальная переменная
var login = "GlobalLogin";
// объект
let user = {
login: "DenisDream",
// метод
welcome: function() {
alert (`Привет, ${[Link]}!`);
}
};
// потеря контекста в асинхронном вызове
setTimeout([Link], 3000); // Привет, GlobalLogin!
// запуск метода в контексте объекта
[Link](); // Привет, DenisDream!
</script>
Решить проблему потери контекста можно с помощью функции
обертки или с помощью методов call, bind, apply (в зависимости от цели).
Поиск контекста
В этом разделе делаем упор на восстановление контекста.
ПРИМЕР 5
<script>
// глобальная переменная
379
login = "JimMorrison";
// объект
var user = {
login: "DenisDream",
pwd: "12345",
role: "admin",
// метод объекта
welcome: function() {
alert(`Привет, ${[Link]}!`);
}
};
// сработает через 2 сек.
// потеря контекста
setTimeout ([Link], 2000);
// сработает сразу
// это вообще не то ...
setTimeout ([Link](), 2000);
</script>
Восстановление контекста функцией-обёрткой
ПРИМЕР 6
<script>
// глобальная переменная
login = "JimMorrison";
// объект
var user = {
login: "DenisDream",
pwd: "12345",
role: "admin",
// метод объекта
welcome: function() {
alert(`Привет, ${[Link]}!`);
}
};
// обернем вызов [Link]() в функцию
setTimeout( () => {[Link]()}, 2000);
</script>
Восстановление контекста методом bind
Обратите внимание на консольный вывод.
ПРИМЕР 7
<script>
// глобальная переменная
login = "JimMorrison";
// объект user
var user = {
login: "DenisDream",
pwd: "12345",
role: "admin",
welcome: function() {
alert(`Привет, ${[Link]}!`);
}
380
};
// сохраним контекст с помощью метода bind
let welcome = [Link](user);
[Link](welcome);
/*
консоль:
ƒ () {
alert(`Привет, ${[Link]}!`);
}
*/
// переопределили объект user
var user = {
login: "ZyZyOnly",
pwd: "qwerty",
role: "moderator",
welcome: function() {
alert(`Привет, ${[Link]}!`);
}
};
// вызов welcome() с привязкой к объекту user
setTimeout( () => {welcome()}, 2000);
</script>
Обратите внимание на сохранение в массив и последующий вызов
функций, созданных методом bind.
ПРИМЕР 8
<script>
// массив для хранения функций, созданных методом bind
let welcome = new Array();
// объект user
var user = {
login: "DenisDream",
pwd: "12345",
role: "admin",
welcome: function() {
alert(`Привет, ${[Link]}!`);
}
};
// сохраним вызов метода с привязкой к объекту
[Link]([Link](user));
// переопределили объект user
var user = {
login: "ZyZyOnly",
pwd: "qwerty",
role: "moderator",
welcome: function() {
alert(`Привет, ${[Link]}!`);
}
};
// сохраним вызов метода с привязкой к объекту
[Link]([Link](user));
// через 3 сек. выполним вызов сохраненных функций
setTimeout( () => {
for (var i=0; i<[Link]; i++) {
381
welcome[i]();
}
}, 3000);
</script>
Контекст и callback
В этом разделе делаем упор на восстановление контекста в callback
функциях.
Потеря контекста в callback
ПРИМЕР 9
<script>
// глобальная переменная
name = "GlobalName";
// объект
let user = {
// свойство объекта
name: "Дениc",
// метод объекта
userInfo: function() {
[Link](`Привет, ${[Link]}!`);
}
}
// вызов метода объекта
[Link](); // Привет, Дениc!
// вызов функции с аргументом - callback
outUser([Link]); // Привет, GlobalName!
// аргумент функции - callback (метод объекта)
function outUser(callback) {
// вызов функции вне контекста объекта
callback();
}
</script>
Восстановление контекста методом call
ПРИМЕР 10
<script>
// глобальные переменные
name = "Anonymous";
login = "Unknown";
email = "Unknown";
role = "user";
// объект
let user = {
name: "Дениc",
login: "DenisDream",
email: "denis-dream@[Link]",
role: "superAdmin",
userInfo: function() {
let str = `<h2>Информация о пользователе</h2>
Имя: ${[Link]} <br>
Логин: ${[Link]} <br>
382
E-mail: ${[Link]} <br>
Роль: ${[Link]} <br>`;
[Link](str);
}
}
// аргумент функции - callback (метод объекта)
function outUser(callback) {
// callback();
[Link](user);
}
// вызов функции с callback
outUser([Link]);
// вызов метода объекта
[Link]();
</script>
Восстановление контекста функцией-обёрткой
ПРИМЕР 11
<script>
// глобальные переменные
name = "Anonymous";
login = "Unknown";
email = "Unknown";
role = "user";
// объект
let user = {
name: "Дениc",
login: "DenisDream",
email: "denis-dream@[Link]",
role: "superAdmin",
userInfo: function() {
let str = `<h2>Информация о пользователе</h2>
Имя: ${[Link]} <br>
Логин: ${[Link]} <br>
E-mail: ${[Link]} <br>
Роль: ${[Link]} <br>`;
[Link](str);
}
}
// передача кода метода (callback)
setTimeout( () => {[Link]()}, 1000);
// вызов метода объекта
[Link]();
</script>
383
Рассмотрим суть возникновения замыкания в нескольких
взаимосвязанных примерах.
ПРИМЕР 12
<script>
// внешняя функция
function outer() {
// внутренняя функция
function inner() {
[Link]('Привет!');
}
// инструкции return нет
}
// вызов внешней функции outer
[Link](outer());
/*
консоль:
undefined (неявный)
*/
</script>
Хорошим примером использования замыкания является возврат
ссылки на функцию. Мы можем возвращать наружу разные ссылки,
которые делают возможным доступ к тому, что было определено внутри.
ПРИМЕР 13
<script>
// внешняя функция
function outer() {
// возвращаем определение функции inner
return function inner() {
[Link]('Привет!');
}
}
// вывод в консоль определения вложенной функции
[Link](outer());
/*
консоль:
ƒ inner () {
[Link]('Привет!');
}
*/
// вызов вложенной функции
// такие вызовы и есть замыкания
outer()();
</script>
Чтобы вывести на экран текст, недостаточно просто вызвать функцию
outer().
Функция возвращает функцию, поэтому возвращаемое значение
надо еще раз вызвать, например так:
// вызов вложенной функции
384
// такие вызовы и есть замыкания
outer()();
Такие вызовы и есть замыкания. Замыкание можно вызвать напрямую,
а можно вызвать через присваивание переменной, например так:
// сохранение состояния (лексического окружения)
// создание замыкания
let hi = outer();
// вызов замыкания
hi();
ПРИМЕР 14
<script>
// внешняя функция
function outer() {
// возвращаем определение безымянной функции
return function () {
[Link]('Привет!');
}
}
// сохранение состояния (лексического окружения)
// создание замыкания
let hi = outer();
// вывод замыкания
[Link](hi);
/*
консоль:
ƒ () {
[Link]('Привет!');
}
*/
// вызов замыкания
hi();
</script>
Важно. Чтобы быть замыканием функции не обязательно что-то
возвращать. Любой доступ к переменным извне текущей области видимости
создаёт замыкание.
Но гораздо интереснее следующий пример, когда происходит
сохранение переменных лексического окружения.
ПРИМЕР 15
<script>
// внешняя функция
function outer(name) {
let email = "denis-dream@[Link]";
let role = "admin";
/*
локальные переменные функции outer:
- name
- email
- role
*/
385
// возвращаем определение безымянной функции
return function() {
// вложенная функция имеет доступ к лексическому окружению родителя
[Link](`
<h3>Привет, ${name}!</h3>
Вы зашли с ролью <b>${role}</b><br>
Ваш e-mail: <b>${email}</b>
`);
}
}
/*
сохранение состояния лексического окружения
- name
- email
- role
*/
// создание замыкания
let hi = outer('Денис');
// переменные глобального контекста
var name = "Anonymous";
var email = "Unknown";
var role = "user";
// вызов замыкания
hi();
</script>
ПРИМЕР 16
let courses = [
{"id": 1, "name": "JavaScript разработчик с нуля" , "time": "7 месяцев", "shedule":"По будним
дням 13:00-15:00", "level": "Junior", "teacher":"Данилов В.Е.", "price":40000},
{"id": 2, "name": "Python-рузработчик" , "time": "12 месяцев", "shedule":"По будним дням
12:00-15:00", "level": "Middle", "teacher":"Ливанов Б.В.", "price":55000},
{"id": 3, "name": "Data Scientist" , "time": "10 месяцев", "shedule":"По выходным 18:00-20:00",
"level": "Junior", "teacher":"Вавилов Н.И.", "price":48000},
{"id": 4, "name": "Фронтенд-разработчик" , "time": "5 месяцев", "shedule":"По выходным дням
10:00-12:00", "level": "Middle", "teacher":"Татарский А.М.", "price":78000},
{"id": 5, "name": "Тестирование веб-приложений на Python" , "time": "2 месяцев",
"shedule":"По выходным дням 15:00-18:00", "level": "Middle", "teacher":"Горшенёв М.Ю.",
"price":40000},
{"id": 6, "name": "Разработчик C++" , "time": "9 месяцев", "shedule":"Индивидуально", "level":
"Middle", "teacher":"Князев А.С.", "price":126000},
{"id": 7, "name": "Android-разработчик" , "time": "12 месяцев", "shedule":"Индвивидуально",
"level": "junior", "teacher":"Маяковский В.В.", "price":168000}
]
386
<script>
// функция поиска курса
function outCourse(id) {
let course = [Link] ( (rec) => {
return [Link] == id;
})
// возвращаем функцию вывода курса
return function () {
with (course) {
[Link](`
<i>Название:</i> <b>${name} </b><br>
<i>Продолжительность:</i> ${time} <br>
<i>Расписание:</i> ${shedule}
`); }
}
}
// идентификаторы интересующих нас курсов
let setId = [4, 7, 2];
// создание замыканий
cur = [Link]( (id) => {
return outCourse(id);
})
// массив функций
[Link](cur);
// пример вывода
cur[2]();
</script>
Во всех предыдущих случаях мы сохраняли состояния лексического
окружения, но не использовали эти состояния от вызова к вызову.
В примере ниже рассмотрим код часто используемого в глобальной
сети примера использования счетчика.
ПРИМЕР 17
<script>
// внешняя функция счетчика
function createCounter() {
let count = 0;
// вложенная функция счетчика
function increment() {
count += 1;
return count;
}
// возврат текущего значения
return increment;
}
// создаем замыкание
const counter = createCounter();
// [Link](counter);
// вызов замыкания
[Link](counter()); // 1
[Link](counter()); // 2
[Link](counter()); // 3
</script>
387
Контроль побочных эффектов
Побочный эффект – это изменение состояния программ вне функции.
Например, когда функция изменяет значение переменной вне её области
видимости, это будет побочным эффектом. Контроль побочных эффектов
подразумевает, что функции не должны изменять состояние программы
вне области своей видимости.
Функции должны возвращать значения, которые могут понадобиться в
других частях программы.
В примере выше createCounter() возвращает вложенную функцию
increment(), которая изменяет count внутри своей области видимости. После
того, как createCounter() была вызвана, создается замыкание, которое
сохраняет count в памяти и возвращает ссылку на increment(). Таким
образом, только во время вызова counter(), изменяется значение count и
возвращается новое значение.
Приватные переменные
Замыкания также используются в целях создания приватных
переменных и методов.
Приватные переменные — это переменные, которые доступны только
внутри функции.
Это может быть полезно, когда нужно скрыть какую-то информацию
или защитить ее от изменений.
В примере из прошлого раздела была объявлена переменная count,
которая является приватной, так как она недоступна извне и не может
изменяться напрямую.
ПРАКТИЧЕСКИЕ ЗАДАНИЯ
ЗАДАНИЕ 1
Используя замыкание напишите функцию, генерирующую и
запоминающую случайоное число в диапазоне 1-100. Используя замыкание
вызовите функцию несколько раз, запомните максимальное из случайно
сгенерированных чисел для нескольких вызовов.
Примерный алгоритм работы функции представлен в следующем
шаблоне кода:
<script>
// внешняя функция
function createNum() {
// ...
}
// инициализация замыкания
const num = createNum();
388
[Link]('Функция случайного числа вернула значение:');
[Link](num());
[Link](num());
[Link](num());
[Link](num());
[Link]('----------');
[Link]('Наибольшее из выпавших чисел:', digit);
</script>
Случайное число диапазона можно получить по следующей формуле:
// случайное число 1 .. 100
let k = [Link]([Link]() * 100 + 1);
Примерный формат вывода:
ЗАДАНИЕ 2
В папке «Раздаточный материал - Практическая работа №36 - Задание
№2» вам предложен шаблон сценария. Реализуйте сценарий таким образом,
что бы функция searchCourse() создавала замыкание и в обновляющемся
массиве данных находила курс с самой низкой ценой, сохраняя при этом
следующую информацию о курсе:
function searchCourse() {
// информация о курсе
var current = {
teacher: "",
name: "",
price: null
}
// ...
}
389