1268 lines
66 KiB
Markdown
1268 lines
66 KiB
Markdown
# Теоретические вопросы к лабораторной работе №1
|
||
|
||
Ответы на контрольные вопросы. Примеры по возможности взяты из собственной работы
|
||
(`index.html`, `script.js`) — так проще отвечать на защите.
|
||
|
||
---
|
||
|
||
## 1. Протокол HTTP
|
||
|
||
**HTTP** (HyperText Transfer Protocol) — прикладной текстовый протокол
|
||
клиент-серверного взаимодействия, работающий поверх TCP (порт 80) или TLS/TCP
|
||
(HTTPS, порт 443). Работает по схеме «запрос — ответ»: клиент всегда инициирует
|
||
обмен, сервер отвечает.
|
||
|
||
Ключевое свойство — **отсутствие состояния** (stateless). Сервер не обязан
|
||
помнить предыдущие запросы клиента; каждый запрос самодостаточен. Состояние
|
||
надстраивается сверху: cookies, сессии, токены, а на клиенте — `localStorage`
|
||
(как в этой работе).
|
||
|
||
Версии: HTTP/1.1 (текстовый, keep-alive соединения), HTTP/2 (бинарные кадры,
|
||
мультиплексирование нескольких запросов в одном соединении, сжатие заголовков
|
||
HPACK), HTTP/3 (поверх QUIC/UDP).
|
||
|
||
### Структура запроса
|
||
|
||
```
|
||
МЕТОД URI ВЕРСИЯ ← строка запроса (start line)
|
||
Заголовок: значение ← заголовки, по одному на строку
|
||
Заголовок: значение
|
||
← ПУСТАЯ строка — обязательный разделитель
|
||
тело запроса ← необязательно (есть у POST/PUT/PATCH)
|
||
```
|
||
|
||
Пример:
|
||
|
||
```http
|
||
POST /check-point HTTP/1.1
|
||
Host: se.ifmo.ru
|
||
Content-Type: application/x-www-form-urlencoded
|
||
Content-Length: 24
|
||
User-Agent: Mozilla/5.0
|
||
|
||
xval=1&yval=2.5&rval=3
|
||
```
|
||
|
||
### Структура ответа
|
||
|
||
```
|
||
ВЕРСИЯ КОД ПОЯСНЕНИЕ ← строка статуса
|
||
Заголовок: значение
|
||
← пустая строка
|
||
тело ответа
|
||
```
|
||
|
||
Пример:
|
||
|
||
```http
|
||
HTTP/1.1 200 OK
|
||
Content-Type: text/html; charset=UTF-8
|
||
Content-Length: 1024
|
||
|
||
```
|
||
|
||
### Методы запросов
|
||
|
||
| Метод | Назначение | Безопасный | Идемпотентный | Тело |
|
||
|---|---|---|---|---|
|
||
| `GET` | Получить ресурс | да | да | нет |
|
||
| `POST` | Отправить данные, создать ресурс | нет | **нет** | да |
|
||
| `PUT` | Полностью заменить ресурс | нет | да | да |
|
||
| `PATCH` | Частично изменить ресурс | нет | нет | да |
|
||
| `DELETE` | Удалить ресурс | нет | да | необяз. |
|
||
| `HEAD` | Как GET, но только заголовки | да | да | нет |
|
||
| `OPTIONS` | Узнать поддерживаемые методы (CORS preflight) | да | да | нет |
|
||
| `TRACE` | Диагностика — вернуть запрос как есть | да | да | нет |
|
||
|
||
Два свойства, которые обязательно спросят:
|
||
|
||
- **Безопасный** (safe) — не изменяет состояние сервера, только читает.
|
||
- **Идемпотентный** — повторный одинаковый запрос даёт тот же результат.
|
||
`DELETE /point/5` можно послать трижды — точка всё равно одна удалённая.
|
||
А три `POST` создадут три записи, поэтому POST не идемпотентен — отсюда
|
||
предупреждение браузера «повторить отправку формы?» при обновлении страницы.
|
||
|
||
### Коды ответов сервера
|
||
|
||
Пять классов по первой цифре:
|
||
|
||
| Класс | Смысл |
|
||
|---|---|
|
||
| **1xx** | Информационные — запрос принят, обработка продолжается |
|
||
| **2xx** | Успех |
|
||
| **3xx** | Перенаправление |
|
||
| **4xx** | Ошибка клиента |
|
||
| **5xx** | Ошибка сервера |
|
||
|
||
Конкретные коды, которые нужно знать:
|
||
|
||
| Код | Название | Когда |
|
||
|---|---|---|
|
||
| 100 | Continue | Сервер готов принять тело |
|
||
| 101 | Switching Protocols | Переход на WebSocket |
|
||
| **200** | OK | Успех, тело содержит результат |
|
||
| 201 | Created | Ресурс создан (ответ на POST/PUT) |
|
||
| 204 | No Content | Успех, тела нет |
|
||
| 301 | Moved Permanently | Переехало навсегда, обновите ссылки |
|
||
| 302 | Found | Временное перенаправление |
|
||
| **304** | Not Modified | Ресурс не изменился, берите из кэша |
|
||
| 400 | Bad Request | Синтаксически некорректный запрос |
|
||
| **401** | Unauthorized | Не аутентифицирован (нужно войти) |
|
||
| **403** | Forbidden | Аутентифицирован, но нет прав |
|
||
| **404** | Not Found | Ресурс не найден |
|
||
| 405 | Method Not Allowed | Метод не поддерживается этим URI |
|
||
| 409 | Conflict | Конфликт состояния |
|
||
| 418 | I'm a teapot | Шутка из RFC 2324 |
|
||
| 422 | Unprocessable Entity | Синтаксис верен, но данные не прошли валидацию |
|
||
| 429 | Too Many Requests | Превышен лимит частоты |
|
||
| **500** | Internal Server Error | Необработанное исключение на сервере |
|
||
| 501 | Not Implemented | Метод не реализован |
|
||
| 502 | Bad Gateway | Прокси получил некорректный ответ от бэкенда |
|
||
| 503 | Service Unavailable | Сервер перегружен или на обслуживании |
|
||
| 504 | Gateway Timeout | Прокси не дождался ответа |
|
||
|
||
Разница 401 и 403 — частый вопрос: 401 «я тебя не знаю, представься»,
|
||
403 «я тебя знаю, но тебе сюда нельзя».
|
||
|
||
### Заголовки
|
||
|
||
Заголовки — это метаданные в формате `Имя: значение`. Имена
|
||
регистронезависимы. Делятся на четыре группы: общие, запроса, ответа и
|
||
сущности (описывающие тело).
|
||
|
||
**Заголовки запроса:**
|
||
|
||
| Заголовок | Смысл |
|
||
|---|---|
|
||
| `Host` | Домен — обязателен в HTTP/1.1, позволяет виртуальный хостинг |
|
||
| `User-Agent` | Клиент: браузер, ОС, версия |
|
||
| `Accept` | Какие MIME-типы клиент готов принять |
|
||
| `Accept-Language` | Предпочитаемые языки (`ru-RU,ru;q=0.9`) |
|
||
| `Accept-Encoding` | Поддерживаемое сжатие (`gzip, br`) |
|
||
| `Cookie` | Cookies, ранее установленные сервером |
|
||
| `Authorization` | Данные аутентификации (`Bearer <token>`) |
|
||
| `Referer` | Страница, с которой пришёл запрос |
|
||
| `If-Modified-Since` | Условный запрос — отдай, только если изменилось |
|
||
| `Content-Type` | Тип тела запроса |
|
||
| `Content-Length` | Длина тела в байтах |
|
||
| `Connection` | `keep-alive` / `close` |
|
||
| `Origin` | Источник запроса, используется в CORS |
|
||
|
||
**Заголовки ответа:**
|
||
|
||
| Заголовок | Смысл |
|
||
|---|---|
|
||
| `Content-Type` | MIME-тип и кодировка тела (`text/html; charset=UTF-8`) |
|
||
| `Content-Length` | Длина тела |
|
||
| `Content-Encoding` | Применённое сжатие |
|
||
| `Server` | ПО сервера (`nginx/1.24`) |
|
||
| `Set-Cookie` | Установить cookie у клиента |
|
||
| `Location` | Куда перенаправить (с кодами 3xx) |
|
||
| `Cache-Control` | Правила кэширования (`no-cache`, `max-age=3600`) |
|
||
| `ETag` | Версия-отпечаток ресурса для условных запросов |
|
||
| `Last-Modified` | Дата последнего изменения |
|
||
| `Access-Control-Allow-Origin` | CORS: кому разрешён кросс-доменный доступ |
|
||
| `Content-Disposition` | `attachment; filename="f.pdf"` — скачать как файл |
|
||
| `WWW-Authenticate` | Метод аутентификации (вместе с 401) |
|
||
|
||
> В данной работе HTTP-обмена фактически нет: страница статическая, а отправка
|
||
> формы перехватывается `e.preventDefault()`, и всё считается на клиенте.
|
||
> Браузер делает лишь GET-запросы за `index.html`, `script.js` и `assets/oscar.png`.
|
||
|
||
---
|
||
|
||
## 2. Язык разметки HTML
|
||
|
||
**HTML** (HyperText Markup Language) — язык **разметки**, а не
|
||
программирования: он описывает структуру и смысл документа, но не содержит
|
||
алгоритмов. Актуальная версия — HTML5 (living standard WHATWG).
|
||
|
||
### Особенности
|
||
|
||
- **Декларативность** — описывается *что* это, а не *как это сделать*.
|
||
- **Теговая структура** — элементы образуют дерево вложенности.
|
||
- **Устойчивость к ошибкам** — браузер не падает на некорректной разметке,
|
||
а исправляет её по стандартным правилам восстановления. В отличие от XHTML,
|
||
который требовал строгой валидности.
|
||
- **Семантичность** — HTML5 ввёл теги со смыслом (`<header>`, `<article>`,
|
||
`<nav>`), важные для SEO и программ чтения с экрана.
|
||
- **Регистронезависимость** имён тегов и атрибутов.
|
||
- **Разделение ответственности** — структура в HTML, оформление в CSS,
|
||
поведение в JS.
|
||
|
||
### Синтаксис элемента
|
||
|
||
```html
|
||
<тег атрибут="значение">содержимое</тег>
|
||
<img src="x.png" alt="описание"> <!-- одиночный (void) элемент -->
|
||
<!-- комментарий -->
|
||
```
|
||
|
||
Элементы делятся на **блочные** (`div`, `p`, `table` — занимают всю ширину,
|
||
начинаются с новой строки) и **строчные** (`span`, `a`, `b` — только по
|
||
содержимому). Это поведение по умолчанию, в CSS меняется через `display`.
|
||
|
||
### Основные теги
|
||
|
||
**Структура документа:**
|
||
|
||
| Тег | Назначение |
|
||
|---|---|
|
||
| `<!DOCTYPE html>` | Объявление типа документа, включает стандартный режим |
|
||
| `<html>` | Корневой элемент |
|
||
| `<head>` | Метаданные, не отображаются |
|
||
| `<body>` | Видимое содержимое |
|
||
| `<meta>` | Кодировка, viewport, описание |
|
||
| `<title>` | Заголовок окна/вкладки |
|
||
| `<link>` | Подключение внешних ресурсов (CSS, favicon) |
|
||
| `<style>` | Встроенные стили |
|
||
| `<script>` | JavaScript |
|
||
|
||
**Текст и блоки:** `<h1>`–`<h6>` (заголовки), `<p>`, `<br>`, `<hr>`,
|
||
`<b>`/`<strong>`, `<i>`/`<em>`, `<span>`, `<div>`, `<pre>`, `<code>`.
|
||
|
||
> `<b>` и `<i>` задают только начертание, `<strong>` и `<em>` несут смысл
|
||
> важности и акцента — их озвучивают скринридеры.
|
||
|
||
**Списки:** `<ul>` (маркированный), `<ol>` (нумерованный), `<li>` (элемент),
|
||
`<dl>`/`<dt>`/`<dd>` (список определений).
|
||
|
||
**Ссылки и медиа:** `<a>`, `<img>`, `<video>`, `<audio>`, `<canvas>`, `<svg>`,
|
||
`<iframe>`.
|
||
|
||
**Таблицы:** `<table>`, `<caption>`, `<thead>`, `<tbody>`, `<tfoot>`, `<tr>`,
|
||
`<th>` (ячейка-заголовок), `<td>` (ячейка данных).
|
||
|
||
**Формы:** `<form>`, `<input>`, `<textarea>`, `<select>`/`<option>`, `<button>`,
|
||
`<label>`, `<fieldset>`/`<legend>`.
|
||
|
||
**Семантические теги HTML5:** `<header>`, `<footer>`, `<nav>`, `<main>`,
|
||
`<section>`, `<article>`, `<aside>`, `<figure>`/`<figcaption>`.
|
||
|
||
### Атрибуты
|
||
|
||
**Глобальные** — применимы к любому тегу:
|
||
|
||
| Атрибут | Назначение |
|
||
|---|---|
|
||
| `id` | Уникальный идентификатор элемента на странице |
|
||
| `class` | Список классов через пробел, для CSS и JS |
|
||
| `style` | Инлайновые стили (нежелательно) |
|
||
| `title` | Всплывающая подсказка |
|
||
| `lang` | Язык содержимого |
|
||
| `hidden` | Скрыть элемент |
|
||
| `data-*` | Произвольные пользовательские данные |
|
||
| `tabindex` | Порядок обхода по Tab |
|
||
|
||
**Специфичные для тегов:**
|
||
|
||
- `<a href target rel>` — адрес, окно открытия, отношение
|
||
- `<img src alt width height>` — `alt` обязателен для доступности
|
||
- `<input type name value placeholder required disabled checked>`
|
||
- `<form action method enctype>`
|
||
- `<td colspan rowspan>`
|
||
- `<canvas width height>`
|
||
- `<script src defer async>`
|
||
|
||
**Пример из работы** — атрибут `data-val` на кнопках выбора R:
|
||
|
||
```html
|
||
<button type="button" class="r-button" data-val="3">3</button>
|
||
```
|
||
|
||
Читается из JS: `btn.getAttribute('data-val')`. Это стандартный способ привязать
|
||
данные к элементу, не нарушая валидность разметки.
|
||
|
||
---
|
||
|
||
## 3. Структура HTML-страницы и DOM
|
||
|
||
### Структура страницы
|
||
|
||
```html
|
||
<!DOCTYPE html> <!-- тип документа -->
|
||
<html lang="ru"> <!-- корень, язык -->
|
||
<head>
|
||
<meta charset="UTF-8"> <!-- кодировка — первой! -->
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>Лабораторная работа №1</title>
|
||
<style> /* ... */ </style>
|
||
</head>
|
||
<body>
|
||
<!-- видимое содержимое -->
|
||
<script src="script.js"></script>
|
||
</body>
|
||
</html>
|
||
```
|
||
|
||
Почему именно так:
|
||
|
||
- `<!DOCTYPE html>` включает **стандартный режим** отображения. Без него
|
||
браузер уходит в quirks mode и имитирует баги старого IE.
|
||
- `<meta charset>` должен идти в первых 1024 байтах, иначе браузер начнёт
|
||
разбирать страницу в неверной кодировке и русский текст превратится в мусор.
|
||
- `<meta viewport>` обязателен для адаптивности на мобильных устройствах.
|
||
- `<script>` в конце `<body>` — чтобы к моменту выполнения весь DOM уже
|
||
существовал. Альтернатива — `<script defer>` в `<head>`.
|
||
|
||
### DOM (Document Object Model)
|
||
|
||
**DOM** — программный интерфейс документа: браузер разбирает (парсит) HTML и
|
||
строит в памяти **дерево объектов**, где каждый тег, текст, атрибут и
|
||
комментарий становится **узлом** (Node). Это дерево доступно из JavaScript для
|
||
чтения и изменения, причём изменения немедленно отражаются на экране.
|
||
|
||
Важно: DOM строится из HTML, но **не равен** ему. Браузер исправляет ошибки
|
||
разметки, достраивает пропущенные `<tbody>`, а JS может добавить узлы, которых
|
||
в исходном файле не было вовсе.
|
||
|
||
**Типы узлов:** `Document` (корень), `Element` (тег), `Text` (текст),
|
||
`Comment`, `Attr`, `DocumentFragment`.
|
||
|
||
Фрагмент дерева этой работы:
|
||
|
||
```
|
||
document
|
||
└── html
|
||
├── head
|
||
│ ├── meta, title
|
||
│ └── style
|
||
└── body
|
||
├── table#layout-table
|
||
│ └── tbody
|
||
│ ├── tr → td#header
|
||
│ ├── tr → td.canvas-cell → canvas#graphCanvas
|
||
│ │ td.content-cell → form#point-form → table → ...
|
||
│ └── tr → td.content-cell → table#results-table → tbody#results-body
|
||
├── img#oscar-easter-egg
|
||
└── script
|
||
```
|
||
|
||
### Работа с DOM из JavaScript
|
||
|
||
**Поиск узлов:**
|
||
|
||
```js
|
||
document.getElementById('graphCanvas'); // по id, один элемент
|
||
document.querySelector('.r-button'); // первый по CSS-селектору
|
||
document.querySelectorAll('input[name="xval"]'); // все по селектору
|
||
document.getElementsByClassName('r-button'); // живая коллекция
|
||
document.getElementsByTagName('td');
|
||
```
|
||
|
||
`querySelectorAll` возвращает **статический** `NodeList` — снимок на момент
|
||
вызова. `getElementsBy*` возвращают **живые** коллекции, которые сами
|
||
обновляются при изменении DOM.
|
||
|
||
**Навигация:** `parentNode`, `children`, `firstElementChild`,
|
||
`nextElementSibling`.
|
||
|
||
**Изменение:**
|
||
|
||
```js
|
||
el.textContent = 'текст'; // текст, безопасно
|
||
el.innerHTML = '<td>1</td>'; // парсится как HTML — риск XSS
|
||
el.setAttribute('data-x', '1');
|
||
el.classList.add('active');
|
||
el.style.color = 'red';
|
||
|
||
const tr = document.createElement('tr'); // создать узел
|
||
parent.appendChild(tr); // вставить
|
||
el.remove(); // удалить
|
||
```
|
||
|
||
**События** — третья функция DOM помимо структуры и изменения:
|
||
|
||
```js
|
||
el.addEventListener('click', (e) => { /* ... */ });
|
||
```
|
||
|
||
Событие проходит три фазы: **погружение** (capturing) от `document` к цели,
|
||
**цель** (target), **всплытие** (bubbling) обратно наверх. По умолчанию
|
||
обработчики срабатывают на всплытии. Отсюда приём **делегирования**: один
|
||
обработчик на родителе обслуживает все дочерние элементы, включая добавленные
|
||
позже.
|
||
|
||
**Пример из работы** — построение строк таблицы истории:
|
||
|
||
```js
|
||
function renderHistory() {
|
||
resultsBody.innerHTML = ''; // очистить поддерево
|
||
[...history].reverse().forEach(rec => {
|
||
const tr = document.createElement('tr'); // создать узел
|
||
tr.innerHTML = `<td>${rec.x}</td>...`; // заполнить
|
||
resultsBody.appendChild(tr); // вставить в дерево
|
||
});
|
||
}
|
||
```
|
||
|
||
Событие `DOMContentLoaded` означает «HTML разобран, дерево DOM построено»
|
||
(в отличие от `load`, который ждёт ещё и картинки со стилями). В работе на нём
|
||
выполняется первичная отрисовка:
|
||
|
||
```js
|
||
window.addEventListener('DOMContentLoaded', () => {
|
||
renderHistory();
|
||
drawGraph();
|
||
validateForm();
|
||
});
|
||
```
|
||
|
||
---
|
||
|
||
## 4. HTML-формы
|
||
|
||
**Форма** — набор элементов ввода, предназначенный для сбора данных
|
||
пользователя и их передачи обработчику (серверу или клиентскому скрипту).
|
||
|
||
### Тег `<form>` и его атрибуты
|
||
|
||
```html
|
||
<form action="/submit" method="post" enctype="multipart/form-data">
|
||
```
|
||
|
||
| Атрибут | Назначение |
|
||
|---|---|
|
||
| `action` | URL обработчика. Пустой или отсутствует — текущая страница |
|
||
| `method` | HTTP-метод: `get` (по умолчанию) или `post` |
|
||
| `enctype` | Кодирование тела при POST |
|
||
| `name` | Имя формы |
|
||
| `target` | Где открыть ответ (`_blank`, `_self`) |
|
||
| `novalidate` | Отключить встроенную браузерную валидацию |
|
||
| `autocomplete` | `on`/`off` — автозаполнение |
|
||
|
||
### Задание метода HTTP-запроса
|
||
|
||
Метод задаётся атрибутом `method`:
|
||
|
||
```html
|
||
<form method="get"> <!-- данные в URL -->
|
||
<form method="post"> <!-- данные в теле запроса -->
|
||
```
|
||
|
||
**`method="get"`** — данные формы кодируются в строку запроса URL:
|
||
|
||
```
|
||
GET /search?xval=1&yval=2.5&rval=3 HTTP/1.1
|
||
```
|
||
|
||
- Запрос виден в адресной строке, попадает в историю браузера и логи прокси.
|
||
- Длина URL ограничена (практически ~2000 символов).
|
||
- Можно сохранить в закладки и переслать ссылкой.
|
||
- Кэшируется, идемпотентен.
|
||
- **Применение:** поиск, фильтры, пагинация — всё, что только читает.
|
||
|
||
**`method="post"`** — данные передаются в теле запроса:
|
||
|
||
```
|
||
POST /submit HTTP/1.1
|
||
Content-Type: application/x-www-form-urlencoded
|
||
|
||
xval=1&yval=2.5&rval=3
|
||
```
|
||
|
||
- Данных может быть сколько угодно, включая файлы.
|
||
- В URL не видны (но **не зашифрованы** — защищает только HTTPS).
|
||
- Не кэшируется, не идемпотентен — обновление страницы вызывает
|
||
предупреждение о повторной отправке.
|
||
- **Применение:** регистрация, авторизация, создание и изменение данных.
|
||
|
||
Значения `enctype` для POST:
|
||
|
||
| Значение | Когда |
|
||
|---|---|
|
||
| `application/x-www-form-urlencoded` | По умолчанию, `key=value&key=value` |
|
||
| `multipart/form-data` | **Обязательно** при загрузке файлов |
|
||
| `text/plain` | Только для отладки |
|
||
|
||
Методы `PUT`/`DELETE` HTML-формами не поддерживаются — только через
|
||
JavaScript (`fetch`, `XMLHttpRequest`).
|
||
|
||
### Правила размещения форм на страницах
|
||
|
||
1. **Формы нельзя вкладывать друг в друга** — `<form>` внутри `<form>`
|
||
недопустим, браузер проигнорирует внутреннюю.
|
||
2. Форм на странице может быть несколько, но они независимы: отправляется
|
||
только та, в которой произошёл submit.
|
||
3. **Поля должны находиться внутри `<form>`**, иначе не попадут в отправку.
|
||
Исключение HTML5 — атрибут `form="id-формы"` позволяет связать поле,
|
||
лежащее вне формы.
|
||
4. **Передаются только поля с атрибутом `name`.** Поле без `name`
|
||
не отправляется, даже если заполнено. `id` для отправки не используется —
|
||
он нужен CSS и JS.
|
||
5. Поля с `disabled` не отправляются; с `readonly` — отправляются.
|
||
6. Невыбранные чекбоксы и радиокнопки не отправляются вообще (а не как пустое
|
||
значение) — обработчик должен считать отсутствие ключа ответом «нет».
|
||
7. Радиокнопки одной группы обязаны иметь **одинаковый `name`** — именно это
|
||
делает выбор взаимоисключающим.
|
||
8. `<form>` — блочный элемент; внутри таблицы его следует размещать целиком
|
||
внутри `<td>`, а не между `<tr>`, иначе разметка невалидна.
|
||
9. Каждое поле должно иметь `<label for="id">` — это и доступность
|
||
(скринридеры), и удобство (клик по подписи активирует поле).
|
||
10. Кнопка `<button>` внутри формы по умолчанию имеет `type="submit"`.
|
||
Чтобы кнопка не отправляла форму, нужен явный `type="button"`.
|
||
11. Клиентская валидация **не отменяет серверную**: любые проверки в браузере
|
||
обходятся через DevTools или прямым HTTP-запросом.
|
||
|
||
### Виды полей ввода
|
||
|
||
`<input>` различается атрибутом `type`:
|
||
|
||
| `type` | Описание |
|
||
|---|---|
|
||
| `text` | Однострочный текст |
|
||
| `password` | Текст со скрытыми символами |
|
||
| `number` | Число со счётчиком, атрибуты `min`, `max`, `step` |
|
||
| `email` | С встроенной проверкой формата |
|
||
| `tel`, `url` | Телефон, адрес |
|
||
| `search` | Поле поиска |
|
||
| `checkbox` | Флажок — независимый множественный выбор |
|
||
| `radio` | Радиокнопка — выбор одного из группы с общим `name` |
|
||
| `file` | Выбор файла, требует `enctype="multipart/form-data"` |
|
||
| `date`, `time`, `datetime-local`, `month`, `week` | Выбор даты и времени |
|
||
| `range` | Ползунок |
|
||
| `color` | Выбор цвета |
|
||
| `hidden` | Скрытое поле — не видно, но отправляется |
|
||
| `submit` | Кнопка отправки |
|
||
| `reset` | Кнопка сброса значений |
|
||
| `button` | Кнопка без действия по умолчанию |
|
||
| `image` | Кнопка-картинка |
|
||
|
||
Другие элементы ввода:
|
||
|
||
- `<textarea rows cols>` — многострочный текст
|
||
- `<select>` + `<option>` — выпадающий список; с `multiple` — множественный
|
||
выбор; `<optgroup>` группирует варианты
|
||
- `<button>` — кнопка с произвольным HTML внутри
|
||
- `<datalist>` — список подсказок для `input`
|
||
- `<output>`, `<progress>`, `<meter>` — вывод значений
|
||
|
||
**Атрибуты валидации HTML5:** `required`, `min`/`max`, `minlength`/`maxlength`,
|
||
`pattern` (регулярное выражение), `step`.
|
||
|
||
### Форма в данной работе
|
||
|
||
```html
|
||
<form id="point-form">
|
||
<!-- X: чекбоксы — множественный выбор -->
|
||
<input type="checkbox" name="xval" value="-2"> -2
|
||
...
|
||
<!-- Y: текстовое поле -->
|
||
<input type="text" id="y-input" name="yval" placeholder="-3 ... 5">
|
||
<!-- R: кнопки + скрытое поле -->
|
||
<button type="button" class="r-button" data-val="1">1</button>
|
||
<input type="hidden" id="r-hidden" name="rval" value="">
|
||
<button type="submit" id="submit-btn" disabled>Проверить попадание</button>
|
||
</form>
|
||
```
|
||
|
||
Разбор решений:
|
||
|
||
- Типы полей заданы вариантом: X — checkbox, Y — text, R — button.
|
||
- У `<form>` нет `action` и `method`, потому что отправка перехватывается
|
||
и обрабатывается на клиенте:
|
||
|
||
```js
|
||
form.addEventListener('submit', (e) => {
|
||
e.preventDefault(); // отменить стандартную отправку и перезагрузку
|
||
...
|
||
});
|
||
```
|
||
|
||
Без `preventDefault()` браузер выполнил бы GET на ту же страницу, и всё
|
||
состояние было бы потеряно.
|
||
- Кнопки R имеют `type="button"` — иначе каждое нажатие отправляло бы форму.
|
||
- Выбранный R хранится в `<input type="hidden">`: кнопки сами по себе значение
|
||
не хранят, а скрытое поле — штатный способ держать его в форме.
|
||
- Чекбоксы X дают **множественный выбор**, поэтому один submit порождает
|
||
столько записей, сколько галочек поставлено:
|
||
|
||
```js
|
||
checkboxes.forEach(cb => {
|
||
if (cb.checked) { history.push({...}); }
|
||
});
|
||
```
|
||
|
||
- `submitBtn.disabled = !isValid` — кнопка заблокирована, пока данные
|
||
некорректны, а сообщения выводятся в `<span class="error">` рядом с полем,
|
||
а не через `alert` (это прямо указано в списке частых ошибок).
|
||
|
||
---
|
||
|
||
## 5. Каскадные таблицы стилей (CSS)
|
||
|
||
**CSS** (Cascading Style Sheets) — язык описания внешнего вида документа.
|
||
Отделяет оформление от структуры: HTML отвечает за смысл, CSS — за вид.
|
||
|
||
### Способы подключения
|
||
|
||
1. **Внешний файл** — `<link rel="stylesheet" href="style.css">`;
|
||
кэшируется, переиспользуется между страницами.
|
||
2. **Встроенная таблица** — `<style>` в `<head>`. Используется в этой работе,
|
||
так как требование п.2 задания — «таблицы стилей должны располагаться
|
||
в самом веб-документе».
|
||
3. **Инлайновый стиль** — атрибут `style="..."` у тега. Нежелателен.
|
||
|
||
### Структура правила
|
||
|
||
```css
|
||
селектор {
|
||
свойство: значение; /* это объявление */
|
||
свойство: значение;
|
||
}
|
||
```
|
||
|
||
Селектор + блок объявлений = **правило**. Пример из работы:
|
||
|
||
```css
|
||
#header {
|
||
background-color: #eeeeee;
|
||
color: #000000;
|
||
padding: 10px;
|
||
text-align: center;
|
||
font-family: monospace;
|
||
font-size: 16px;
|
||
}
|
||
```
|
||
|
||
### Виды селекторов
|
||
|
||
| Вид | Синтаксис | Что выбирает |
|
||
|---|---|---|
|
||
| Универсальный | `*` | Все элементы |
|
||
| **Элемента (тега)** | `td` | Все `<td>` |
|
||
| **Класса** | `.r-button` | Все с `class="r-button"` |
|
||
| **Идентификатора** | `#header` | Элемент с `id="header"` |
|
||
| Атрибута | `input[type="text"]` | По наличию/значению атрибута |
|
||
| Группировка | `table, th, td` | Каждый из перечисленных |
|
||
|
||
**Комбинаторы** (отношения между элементами):
|
||
|
||
| Комбинатор | Синтаксис | Что выбирает |
|
||
|---|---|---|
|
||
| Вложенный (потомка) | `A B` | Все `B` внутри `A` на любой глубине |
|
||
| **Дочерний** | `A > B` | Только непосредственных детей `A` |
|
||
| Соседний | `A + B` | Первый `B` сразу после `A` |
|
||
| Последующий | `A ~ B` | Все `B` после `A` на том же уровне |
|
||
|
||
Разница потомка и дочернего — обязательный вопрос:
|
||
`#point-form td` выберет и `<td>` во вложенной таблице подсказок, а
|
||
`#point-form > table > tbody > tr > td` — только ячейки верхнего уровня.
|
||
|
||
**Псевдоклассы** — состояние элемента: `:hover`, `:focus`, `:active`,
|
||
`:visited`, `:checked`, `:disabled`, `:first-child`, `:last-child`,
|
||
`:nth-child(2n)`, `:not(.x)`.
|
||
|
||
**Псевдоэлементы** — виртуальные части: `::before`, `::after`,
|
||
`::first-line`, `::placeholder`.
|
||
|
||
### Особенности применения
|
||
|
||
- Классы — для стилей, повторяющихся у многих элементов. Основной рабочий
|
||
инструмент.
|
||
- Идентификаторы — для уникальных элементов. Злоупотреблять не стоит: высокая
|
||
специфичность мешает переопределению.
|
||
- Селекторы тегов — для базовых правил на весь документ (`body`, сброс
|
||
отступов).
|
||
- Чем короче и менее специфичен селектор, тем легче поддерживать код. Длинные
|
||
цепочки вроде `div#main table.data tbody tr td span` делают стили хрупкими.
|
||
- Браузер читает селекторы **справа налево**, поэтому последняя часть должна
|
||
быть как можно более конкретной.
|
||
|
||
Все четыре требуемых видов селекторов в работе присутствуют:
|
||
|
||
```css
|
||
body { ... } /* селектор элемента */
|
||
.content-cell { ... } /* селектор класса */
|
||
#layout-table { ... } /* селектор идентификатора */
|
||
#point-form label { ... } /* потомка */
|
||
td.canvas-cell > * { ... } /* дочерних элементов */
|
||
.content-cell[colspan="2"] > h3 { } /* атрибута + дочерний */
|
||
#point-form input[type="text"] { } /* тег + атрибут */
|
||
.r-button.active { ... } /* два класса на одном элементе */
|
||
```
|
||
|
||
### Приоритеты правил
|
||
|
||
Когда к одному элементу применимы несколько правил, конфликт решается
|
||
**каскадом** — по шагам, в строгом порядке:
|
||
|
||
**1. Происхождение и важность** (от низшего к высшему):
|
||
|
||
1. Стили браузера по умолчанию
|
||
2. Стили пользователя
|
||
3. Стили автора (`<style>`, `<link>`, `style=""`)
|
||
4. Стили автора с `!important`
|
||
5. Стили пользователя с `!important`
|
||
|
||
**2. Специфичность** — считается как тройка `(A, B, C)`:
|
||
|
||
| Разряд | Что считается | Вес |
|
||
|---|---|---|
|
||
| A | Идентификаторы `#id` | 100 |
|
||
| B | Классы, атрибуты, псевдоклассы | 10 |
|
||
| C | Теги и псевдоэлементы | 1 |
|
||
|
||
Инлайновый `style=""` стоит выше любого селектора (условно 1000),
|
||
`!important` — выше всего, кроме пользовательского `!important`.
|
||
Универсальный селектор `*` и `:not()` сами по себе веса не добавляют.
|
||
|
||
Примеры подсчёта:
|
||
|
||
| Селектор | Специфичность | Вес |
|
||
|---|---|---|
|
||
| `td` | 0,0,1 | 1 |
|
||
| `.content-cell` | 0,1,0 | 10 |
|
||
| `td.canvas-cell` | 0,1,1 | 11 |
|
||
| `.r-button.active` | 0,2,0 | 20 |
|
||
| `#point-form td` | 1,0,1 | 101 |
|
||
| `style="..."` | — | 1000 |
|
||
|
||
**3. Порядок следования** — при равной специфичности побеждает правило,
|
||
объявленное **позже**. Именно поэтому `.r-button.active` в работе написано
|
||
после `.r-button` — хотя здесь и специфичность выше.
|
||
|
||
### Наследование
|
||
|
||
Часть свойств передаётся от родителя к детям автоматически: `color`,
|
||
`font-family`, `font-size`, `font-weight`, `line-height`, `text-align`,
|
||
`visibility`. Не наследуются свойства блочной модели: `margin`, `padding`,
|
||
`border`, `background`, `width`, `height`.
|
||
|
||
Пример из работы — наследование и каскадирование:
|
||
|
||
```css
|
||
body {
|
||
font-family: Arial, sans-serif; /* наследуется всеми потомками */
|
||
color: #000000;
|
||
}
|
||
#header {
|
||
color: #000000; /* комментарий в коде: «Каскадирование» */
|
||
font-family: monospace; /* переопределяет унаследованный Arial */
|
||
}
|
||
#header span.variant {
|
||
color: #cc0000; /* переопределяет на уровень глубже */
|
||
}
|
||
```
|
||
|
||
`<b>` внутри `#header` получает monospace по наследству, а `span.variant`
|
||
перебивает цвет более специфичным правилом.
|
||
|
||
### Преимущества CSS перед атрибутом `style`
|
||
|
||
1. **Разделение ответственности** — структура отдельно, оформление отдельно.
|
||
HTML остаётся читаемым и семантичным.
|
||
2. **Переиспользование** — одно правило `.r-button` оформляет все пять кнопок.
|
||
С `style` пришлось бы дублировать код пять раз.
|
||
3. **Поддерживаемость** — чтобы изменить вид всех кнопок, правится одна строка,
|
||
а не N тегов. Меньше кода — меньше шансов пропустить место.
|
||
4. **Размер и кэширование** — внешний CSS-файл загружается один раз и
|
||
кэшируется для всех страниц сайта; инлайновые стили заново передаются
|
||
с каждой страницей.
|
||
5. **Каскад и наследование работают** — инлайновый стиль их фактически
|
||
отключает, он всегда главнее и не переопределяется ничем, кроме
|
||
`!important`.
|
||
6. **Полная функциональность** — через `style` невозможны псевдоклассы
|
||
(`:hover`, `:focus`), псевдоэлементы (`::before`), медиазапросы
|
||
(`@media`), анимации (`@keyframes`).
|
||
7. **Адаптивность** — медиазапросы для разных размеров экрана доступны только
|
||
в таблицах стилей.
|
||
8. **Доступность** — пользователь может подключить свою таблицу стилей
|
||
(крупный шрифт, высокий контраст); инлайновые стили её перебьют.
|
||
9. **Отладка** — DevTools показывает всю цепочку правил и причину победы
|
||
одного над другим.
|
||
|
||
---
|
||
|
||
## 6. LESS, Sass, SCSS
|
||
|
||
**Препроцессоры CSS** — надстройки над CSS, добавляющие возможности,
|
||
которых в самом CSS нет или не было: переменные, вложенность, миксины,
|
||
функции, арифметику. Код на препроцессоре **транслируется (компилируется)
|
||
в обычный CSS**.
|
||
|
||
### Зачем они появились
|
||
|
||
Чистый CSS долго не имел переменных, средств повторного использования и
|
||
структурирования. В больших проектах это приводило к дублированию, длинным
|
||
повторяющимся селекторам и трудно поддерживаемым файлам.
|
||
|
||
### Ключевые особенности (общие)
|
||
|
||
| Возможность | Описание |
|
||
|---|---|
|
||
| **Переменные** | Именованные значения: цвета, размеры, шрифты в одном месте |
|
||
| **Вложенность** | Селекторы внутри селекторов повторяют структуру HTML |
|
||
| **Миксины** | Переиспользуемые блоки объявлений, в т.ч. с параметрами |
|
||
| **Наследование** | `@extend` — один селектор перенимает правила другого |
|
||
| **Операции** | Арифметика: `10px * 2`, работа с цветами |
|
||
| **Функции** | Встроенные (`darken`, `lighten`) и свои |
|
||
| **Импорт** | Разбиение на файлы, объединяемые при компиляции без лишних HTTP-запросов |
|
||
| **Условия и циклы** | `@if`, `@for`, `@each` — у Sass/SCSS развиты сильнее |
|
||
|
||
### Sass и SCSS
|
||
|
||
**Sass** (Syntactically Awesome Style Sheets, 2006) — написан на Ruby,
|
||
сейчас реализация Dart Sass. Имеет **два синтаксиса**:
|
||
|
||
**Sass (indented, `.sass`)** — отступы вместо фигурных скобок, без точек
|
||
с запятой:
|
||
|
||
```sass
|
||
$primary: #3399FF
|
||
.button
|
||
background: $primary
|
||
padding: 5px 10px
|
||
```
|
||
|
||
**SCSS (Sassy CSS, `.scss`)** — синтаксис, надмножество CSS: любой валидный
|
||
CSS является валидным SCSS. Сейчас основной вариант.
|
||
|
||
```scss
|
||
$primary: #3399FF;
|
||
$padding: 5px;
|
||
|
||
@mixin button-base($bg) {
|
||
background-color: $bg;
|
||
padding: $padding ($padding * 2);
|
||
cursor: pointer;
|
||
}
|
||
|
||
.r-button {
|
||
@include button-base(#dddddd);
|
||
border: 1px solid #888888;
|
||
|
||
&.active { // & — ссылка на родительский селектор
|
||
@include button-base(#888888);
|
||
color: #ffffff;
|
||
}
|
||
|
||
&:hover { background-color: darken(#dddddd, 10%); }
|
||
}
|
||
```
|
||
|
||
Компилируется в:
|
||
|
||
```css
|
||
.r-button { background-color: #dddddd; padding: 5px 10px; cursor: pointer;
|
||
border: 1px solid #888888; }
|
||
.r-button.active { background-color: #888888; padding: 5px 10px;
|
||
cursor: pointer; color: #fff; }
|
||
.r-button:hover { background-color: #c4c4c4; }
|
||
```
|
||
|
||
**LESS** (Leaner Style Sheets, 2009) — написан на JavaScript, работает под
|
||
Node.js, может выполняться и в браузере. Синтаксис ближе к CSS; переменные
|
||
через `@`:
|
||
|
||
```less
|
||
@primary: #3399FF;
|
||
@padding: 5px;
|
||
|
||
.button-base(@bg) {
|
||
background-color: @bg;
|
||
padding: @padding (@padding * 2);
|
||
}
|
||
|
||
.r-button {
|
||
.button-base(#dddddd);
|
||
&.active { .button-base(#888888); color: #ffffff; }
|
||
}
|
||
```
|
||
|
||
### Сравнительная характеристика
|
||
|
||
| Критерий | Sass/SCSS | LESS |
|
||
|---|---|---|
|
||
| Год | 2006 | 2009 |
|
||
| Реализация | Dart (ранее Ruby) | JavaScript (Node.js) |
|
||
| Синтаксис переменных | `$var` | `@var` |
|
||
| Синтаксисы | Два: `.sass` и `.scss` | Один: `.less` |
|
||
| Миксины | `@mixin` / `@include` — явные | Любой класс может быть миксином |
|
||
| Логика | Полноценные `@if`, `@for`, `@each`, `@while`, свои функции | Ограниченная: guard-выражения, рекурсия |
|
||
| Модульность | `@use` / `@forward` — пространства имён | `@import` |
|
||
| Выполнение в браузере | Нет | Да (less.js, только для разработки) |
|
||
| Экосистема | Крупнее: Bootstrap 4+, Foundation | Bootstrap 3, Semantic UI |
|
||
| Порог входа | Чуть выше | Ниже |
|
||
|
||
**Коротко:** SCSS мощнее и является отраслевым стандартом; LESS проще и ближе
|
||
к чистому CSS. Конфликт `@` в LESS с директивами CSS (`@media`, `@import`) —
|
||
известное неудобство.
|
||
|
||
Существует также **Stylus** (гибкий синтаксис, необязательные скобки и
|
||
двоеточия) и **PostCSS** — не препроцессор, а инструмент преобразования CSS
|
||
плагинами (`autoprefixer`, `postcss-preset-env`).
|
||
|
||
### Совместимость с браузерами и трансляция
|
||
|
||
Это ключевой момент: **браузеры не понимают LESS, Sass и SCSS вообще**.
|
||
Браузер умеет только CSS. Поэтому исходники компилируются в обычный CSS
|
||
**до** отправки клиенту:
|
||
|
||
```
|
||
style.scss ──[компилятор]──► style.css ──► <link rel="stylesheet">
|
||
```
|
||
|
||
Отсюда следствия:
|
||
|
||
- **Совместимость с браузерами — стопроцентная**, потому что на выходе
|
||
получается обычный CSS. Препроцессор не создаёт проблем поддержки сам по
|
||
себе; ограничения задают только те CSS-свойства, которые вы используете.
|
||
- Вся обработка происходит на этапе сборки — **во время выполнения накладных
|
||
расходов нет**.
|
||
- Для отладки генерируются **source maps**: DevTools показывает строку
|
||
исходного `.scss`, а не скомпилированного `.css`.
|
||
|
||
Способы трансляции:
|
||
|
||
```bash
|
||
sass style.scss style.css # Dart Sass, разово
|
||
sass --watch src:dist # автоматически при изменениях
|
||
lessc style.less style.css # LESS
|
||
```
|
||
|
||
Также: сборщики (Webpack с `sass-loader`, Vite, Gulp), встроенная поддержка
|
||
в IDE, плагины фреймворков.
|
||
|
||
> **Современная оговорка.** Часть возможностей препроцессоров уже появилась
|
||
> в самом CSS: **кастомные свойства** (`--main-color: #333; color:
|
||
> var(--main-color)`) — они, в отличие от переменных препроцессора, живут во
|
||
> время выполнения и меняются из JS; функция `calc()`; **встроенная
|
||
> вложенность** селекторов (поддерживается современными браузерами с 2023 г.).
|
||
> Поэтому необходимость в препроцессорах снизилась, но миксины, циклы,
|
||
> модульность и функции по-прежнему остаются их преимуществом.
|
||
|
||
В данной работе препроцессоры не применяются: по заданию стили должны быть
|
||
в самом документе внутри `<style>`, объём невелик, и подключение сборки стало
|
||
бы «использованием микроскопа для забивания гвоздей».
|
||
|
||
---
|
||
|
||
## 7. Клиентские сценарии
|
||
|
||
**Клиентский сценарий** (client-side script) — программный код, который
|
||
передаётся вместе со страницей и выполняется **в браузере пользователя**, а не
|
||
на сервере. Противоположность — серверные сценарии (PHP, Java, Python),
|
||
исполняемые до отправки ответа.
|
||
|
||
### Особенности
|
||
|
||
**Сильные стороны:**
|
||
|
||
- **Мгновенная реакция** без обращения к серверу — нет задержки сети.
|
||
- **Снижение нагрузки на сервер и трафика** — вычисления переносятся на
|
||
устройство клиента.
|
||
- **Полный доступ к DOM и браузерным API** — можно менять страницу без
|
||
перезагрузки, рисовать на Canvas, читать геолокацию, хранить данные.
|
||
- **Интерактивность** — анимации, drag&drop, динамические интерфейсы, SPA.
|
||
|
||
**Ограничения и риски:**
|
||
|
||
- **Код полностью открыт пользователю.** Исходник виден в DevTools; минификация
|
||
лишь затрудняет чтение. Никаких секретов, ключей и паролей в клиентском коде
|
||
быть не может.
|
||
- **Клиентскую валидацию невозможно считать защитой.** Пользователь может
|
||
отключить JS, изменить код в DevTools или послать запрос напрямую через
|
||
`curl`. Поэтому **серверная валидация обязательна всегда** — клиентская нужна
|
||
лишь для удобства и скорости отклика.
|
||
- **Зависимость от среды** — разные браузеры, версии, устройства; нужны
|
||
полифиллы и транспиляция.
|
||
- **JS может быть отключён** — отсюда принцип постепенного улучшения
|
||
(progressive enhancement): базовая функциональность должна работать без JS.
|
||
- **Производительность ограничена устройством** клиента; тяжёлые вычисления
|
||
блокируют единственный поток и «подвешивают» интерфейс.
|
||
- **Безопасность** — уязвимости XSS, когда чужой скрипт исполняется в контексте
|
||
страницы.
|
||
|
||
### Сферы применения
|
||
|
||
| Сфера | Примеры |
|
||
|---|---|
|
||
| Валидация форм | Проверка значений до отправки |
|
||
| Динамический интерфейс | Табы, модальные окна, аккордеоны, подсказки |
|
||
| Асинхронный обмен данными | AJAX, `fetch` — обновление части страницы |
|
||
| Графика и визуализация | Canvas, SVG, WebGL, графики и диаграммы |
|
||
| Анимация | Переходы, эффекты, параллакс |
|
||
| Локальное хранение | `localStorage`, `sessionStorage`, IndexedDB |
|
||
| SPA и фреймворки | React, Vue, Angular |
|
||
| Работа с медиа | Плееры, обработка изображений |
|
||
| Реальное время | WebSocket, чаты, уведомления |
|
||
| Устройство пользователя | Геолокация, камера, датчики, уведомления |
|
||
| Офлайн-режим | Service Workers, PWA |
|
||
| Аналитика | Сбор поведенческих метрик |
|
||
|
||
### Язык JavaScript
|
||
|
||
**JavaScript** — высокоуровневый, динамический, интерпретируемый язык
|
||
программирования. Создан Бренданом Айком в Netscape в 1995 году за десять
|
||
дней; изначально назывался Mocha, затем LiveScript. Имя «JavaScript» —
|
||
маркетинговый ход: **к языку Java отношения не имеет**.
|
||
|
||
Стандартизован как **ECMAScript** (ECMA-262). JavaScript — его наиболее
|
||
известная реализация.
|
||
|
||
**Характеристики языка:**
|
||
|
||
| Свойство | Пояснение |
|
||
|---|---|
|
||
| Динамическая типизация | Тип определяется во время выполнения, переменная может менять тип |
|
||
| Слабая типизация | Автоматическое приведение типов (`'2' == 2` → `true`) |
|
||
| Интерпретируемый + JIT | Движки (V8, SpiderMonkey, JavaScriptCore) компилируют «на лету» |
|
||
| Многопарадигменный | Императивный, объектно-ориентированный, функциональный |
|
||
| Прототипное наследование | Объекты наследуют от объектов, а не от классов; `class` — синтаксический сахар |
|
||
| Функции — объекты первого класса | Передаются как аргументы, возвращаются, замыкания |
|
||
| Однопоточность | Один поток выполнения, event loop, асинхронность без блокировки |
|
||
| Автоматическая сборка мусора | Память освобождается автоматически |
|
||
|
||
**Где исполняется:** браузер (основная среда), сервер (Node.js, Deno, Bun),
|
||
мобильные приложения (React Native), десктоп (Electron), встраиваемые системы.
|
||
|
||
**Пример из данной работы.** Все три характерные сферы клиентских сценариев
|
||
задействованы:
|
||
|
||
```js
|
||
// 1. Валидация ввода без обращения к серверу
|
||
function validateY(showErrors = false) {
|
||
const valStr = yInput.value.trim().replace(',', '.');
|
||
if (valStr === '') { /* сообщение об ошибке */ return false; }
|
||
const y = Number(valStr);
|
||
if (isNaN(y)) { return false; }
|
||
if (y < -3 || y > 5) { return false; }
|
||
return true;
|
||
}
|
||
|
||
// 2. Графика на Canvas
|
||
ctx.arc(center, center, R_PIXELS, -Math.PI / 2, 0, false);
|
||
|
||
// 3. Локальное хранение между перезагрузками
|
||
localStorage.setItem(STORAGE_KEY, JSON.stringify(history));
|
||
```
|
||
|
||
Показательно, что данные из `localStorage` в работе перепроверяются при
|
||
загрузке:
|
||
|
||
```js
|
||
history = rawData.filter(rec => {
|
||
if (![1, 2, 3, 4, 5].includes(rec.r)) return false;
|
||
...
|
||
});
|
||
```
|
||
|
||
Это иллюстрация главного ограничения клиентских сценариев: всё, что доступно
|
||
клиенту, — недоверенные данные, потому что пользователь может их изменить.
|
||
По той же причине в работе проверяются значения `data-val` у кнопок R и
|
||
`value` у чекбоксов — они редактируются через DevTools.
|
||
|
||
---
|
||
|
||
## 8. Версии ECMAScript. Возможности ES6 и ES7
|
||
|
||
**ECMAScript** — стандарт языка (спецификация ECMA-262), разрабатываемый
|
||
комитетом **TC39** организации ECMA International. JavaScript — реализация
|
||
этого стандарта.
|
||
|
||
### История версий
|
||
|
||
| Версия | Год | Главное |
|
||
|---|---|---|
|
||
| ES1 | 1997 | Первая редакция |
|
||
| ES2 | 1998 | Приведение к стандарту ISO |
|
||
| ES3 | 1999 | Регулярные выражения, `try/catch`, `do-while` |
|
||
| ES4 | — | **Отменена** из-за разногласий, слишком радикальна |
|
||
| ES5 | 2009 | `strict mode`, `JSON`, методы массивов (`forEach`, `map`, `filter`, `reduce`), геттеры/сеттеры, `Object.defineProperty` |
|
||
| ES5.1 | 2011 | Уточнения |
|
||
| **ES6 / ES2015** | 2015 | Крупнейшее обновление языка |
|
||
| **ES7 / ES2016** | 2016 | Маленький релиз, начало ежегодного цикла |
|
||
| ES2017 | 2017 | `async/await` |
|
||
| ES2018 | 2018 | Spread для объектов, `for await`, `Promise.finally` |
|
||
| ES2019 | 2019 | `flat`, `trimStart/End`, необязательный параметр `catch` |
|
||
| ES2020 | 2020 | `?.`, `??`, `BigInt`, `Promise.allSettled`, динамический `import()` |
|
||
| ES2021 | 2021 | `replaceAll`, `??=`, `Promise.any`, числовые разделители |
|
||
| ES2022 | 2022 | Top-level `await`, приватные поля `#`, `at()`, `Object.hasOwn` |
|
||
| ES2023 | 2023 | `findLast`, неразрушающие методы массивов (`toSorted`, `with`) |
|
||
| ES2024–2025 | | `Object.groupBy`, `Promise.withResolvers`, `Array.fromAsync` и др. |
|
||
|
||
С 2015 года версии выпускаются **ежегодно** и называются по году. Отсюда
|
||
практика называть «современный JS» не версией, а годом.
|
||
|
||
### ES6 (ES2015) — ключевые возможности
|
||
|
||
**1. `let` и `const` — блочная область видимости**
|
||
|
||
```js
|
||
let x = 1; // можно переприсвоить
|
||
const y = 2; // нельзя (но содержимое объекта меняется)
|
||
```
|
||
|
||
До ES6 был только `var` с областью видимости на всю функцию и всплытием
|
||
(hoisting), что порождало классический баг с замыканиями в цикле.
|
||
|
||
**2. Стрелочные функции**
|
||
|
||
```js
|
||
const sum = (a, b) => a + b;
|
||
rButtons.forEach(btn => btn.classList.remove('active'));
|
||
```
|
||
|
||
Короткий синтаксис, неявный `return` без фигурных скобок, и главное —
|
||
**не имеют своего `this`**, а берут его из окружающего контекста. Это убрало
|
||
необходимость в `var self = this` и `.bind(this)`.
|
||
|
||
**3. Шаблонные строки (template literals)**
|
||
|
||
```js
|
||
tr.innerHTML = `<td>${rec.x}</td><td>${rec.y}</td>`;
|
||
```
|
||
|
||
Обратные кавычки, подстановка `${выражение}`, многострочность.
|
||
|
||
**4. Деструктуризация**
|
||
|
||
```js
|
||
const { x, y, r } = rec; // из объекта
|
||
const [first, second] = arr; // из массива
|
||
const { x: coordX = 0 } = rec; // переименование и значение по умолчанию
|
||
```
|
||
|
||
**5. Параметры по умолчанию, rest и spread**
|
||
|
||
```js
|
||
function validateY(showErrors = false) { } // default
|
||
function sum(...nums) { } // rest — собрать в массив
|
||
const copy = [...history]; // spread — развернуть
|
||
Math.max(...arr);
|
||
```
|
||
|
||
**6. Классы** — синтаксический сахар над прототипами
|
||
|
||
```js
|
||
class Point {
|
||
constructor(x, y) { this.x = x; this.y = y; }
|
||
hit(r) { return this.x ** 2 + this.y ** 2 <= r ** 2; }
|
||
static zero() { return new Point(0, 0); }
|
||
}
|
||
class Marked extends Point { /* super(), переопределение */ }
|
||
```
|
||
|
||
**7. Промисы** — работа с асинхронностью без «callback hell»
|
||
|
||
```js
|
||
fetch('/api/points')
|
||
.then(res => res.json())
|
||
.then(data => render(data))
|
||
.catch(err => console.error(err));
|
||
```
|
||
|
||
**8. Модули**
|
||
|
||
```js
|
||
export function checkHit(x, y, r) { } // module.js
|
||
import { checkHit } from './module.js';
|
||
```
|
||
|
||
Штатное разделение кода на файлы на уровне языка.
|
||
|
||
**9. Новые структуры данных:** `Map` (ключи любого типа), `Set` (уникальные
|
||
значения), `WeakMap`, `WeakSet`.
|
||
|
||
**10. Итераторы, `for...of` и генераторы**
|
||
|
||
```js
|
||
for (const rec of history) { } // по значениям (vs for...in — по ключам)
|
||
function* gen() { yield 1; yield 2; } // генератор
|
||
```
|
||
|
||
**11. Новые методы:** `Array.from`, `Array.of`, `find`, `findIndex`, `fill`,
|
||
`Object.assign`, `String.prototype.includes`/`startsWith`/`endsWith`/`repeat`,
|
||
`Number.isNaN`, `Number.isInteger`.
|
||
|
||
**12. Прочее:** краткая запись свойств объекта (`{ x, y }` вместо
|
||
`{ x: x, y: y }`), вычисляемые имена свойств (`{ [key]: value }`), символы
|
||
(`Symbol`), `Proxy` и `Reflect`, оператор `**` (возведение в степень —
|
||
формально ES7), хвостовая рекурсия.
|
||
|
||
### ES7 (ES2016) — две возможности
|
||
|
||
ES2016 намеренно сделали маленьким, чтобы перейти к предсказуемому
|
||
ежегодному циклу вместо редких гигантских релизов.
|
||
|
||
**1. Оператор возведения в степень `**`**
|
||
|
||
```js
|
||
2 ** 10 // 1024 — вместо Math.pow(2, 10)
|
||
x ** 2 + y ** 2 <= r ** 2
|
||
```
|
||
|
||
Именно в это преобразуется пользовательский ввод в данной работе:
|
||
|
||
```js
|
||
.replace(/\^/g, '**'); // x^2 → x**2
|
||
```
|
||
|
||
**2. `Array.prototype.includes`**
|
||
|
||
```js
|
||
[1, 2, 3, 4, 5].includes(3); // true
|
||
[NaN].includes(NaN); // true — а indexOf даёт -1!
|
||
```
|
||
|
||
Удобнее и честнее, чем `arr.indexOf(x) !== -1`: возвращает булево значение и
|
||
корректно находит `NaN`. Применяется в работе для проверки допустимых значений:
|
||
|
||
```js
|
||
if (![1, 2, 3, 4, 5].includes(rec.r)) return false;
|
||
if (![-2, -1.5, -1, -0.5, 0, 0.5, 1, 1.5, 2].includes(rec.x)) return false;
|
||
```
|
||
|
||
### Коротко о последующих версиях
|
||
|
||
- **ES2017:** `async/await` — асинхронный код в синхронном стиле;
|
||
`Object.values`, `Object.entries`, `padStart`/`padEnd`.
|
||
- **ES2020:** опциональная цепочка `obj?.a?.b` и нулевое слияние
|
||
`a ?? b` — обе конструкции сильно сократили защитные проверки.
|
||
- **ES2022:** приватные поля классов `#field`, `at(-1)`.
|
||
|
||
### Совместимость и транспиляция
|
||
|
||
Браузеры поддерживают разные версии стандарта. Решения:
|
||
|
||
- **Транспиляция** (Babel, TypeScript, SWC) — современный код
|
||
переписывается в ES5 для старых браузеров.
|
||
- **Полифиллы** (core-js) — реализация отсутствующих методов на старом JS.
|
||
- **Browserslist** — настройка целевых браузеров, по которой сборщик решает,
|
||
что преобразовывать.
|
||
- Таблицы поддержки: caniuse.com, compat-table.
|
||
|
||
В данной работе используются ES6+ конструкции (`const`/`let`, стрелочные
|
||
функции, шаблонные строки, spread, параметры по умолчанию) и ES7
|
||
(`includes`, `**`). Транспиляция не нужна: все современные браузеры
|
||
поддерживают их нативно, а сборка усложнила бы проект без выгоды.
|
||
|
||
---
|
||
|
||
## Краткая шпаргалка для защиты
|
||
|
||
| Вопрос | Ответ одной фразой |
|
||
|---|---|
|
||
| HTTP stateless? | Да, сервер не помнит клиента; состояние — через cookies/сессии/токены |
|
||
| GET vs POST | GET — данные в URL, кэшируется, идемпотентен, для чтения; POST — в теле, для изменений |
|
||
| 401 vs 403 | 401 — не представился; 403 — представился, но нет прав |
|
||
| Идемпотентность | Повтор запроса даёт тот же результат; POST — не идемпотентен |
|
||
| HTML — язык программирования? | Нет, язык разметки: описывает структуру, не алгоритмы |
|
||
| Зачем DOCTYPE | Включает стандартный режим вместо quirks mode |
|
||
| DOM | Дерево объектов документа в памяти браузера, доступное из JS |
|
||
| `textContent` vs `innerHTML` | Первый вставляет текст, второй парсит HTML — риск XSS |
|
||
| Почему `<script>` в конце body | Чтобы DOM был построен; альтернатива — `defer` |
|
||
| Какие поля отправляются | Только с атрибутом `name` и без `disabled` |
|
||
| Можно ли вложить формы | Нет |
|
||
| Приоритет CSS | Важность → специфичность (id=100, класс=10, тег=1) → порядок |
|
||
| `A B` vs `A > B` | Все потомки на любой глубине vs только прямые дети |
|
||
| Что не наследуется | Блочная модель: margin, padding, border, background, width |
|
||
| Зачем CSS вместо style="" | Переиспользование, каскад, псевдоклассы, медиазапросы, кэширование |
|
||
| Понимает ли браузер SCSS | Нет, компилируется в CSS до отправки; совместимость 100% |
|
||
| Sass vs LESS | `$` vs `@`; Dart vs JS; у Sass сильнее логика и модульность |
|
||
| Достаточно ли клиентской валидации | Нет, обходится через DevTools; серверная обязательна |
|
||
| ES6 год и главное | 2015; `let`/`const`, стрелочные, классы, промисы, модули, деструктуризация |
|
||
| ES7 что добавил | `**` и `Array.prototype.includes` |
|