66 KiB
Теоретические вопросы к лабораторной работе №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)
Пример:
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/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 1024
<!DOCTYPE html>...
Методы запросов
| Метод | Назначение | Безопасный | Идемпотентный | Тело |
|---|---|---|---|---|
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.
Синтаксис элемента
<тег атрибут="значение">содержимое</тег>
<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:
<button type="button" class="r-button" data-val="3">3</button>
Читается из JS: btn.getAttribute('data-val'). Это стандартный способ привязать
данные к элементу, не нарушая валидность разметки.
3. Структура HTML-страницы и DOM
Структура страницы
<!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
Поиск узлов:
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.
Изменение:
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 помимо структуры и изменения:
el.addEventListener('click', (e) => { /* ... */ });
Событие проходит три фазы: погружение (capturing) от document к цели,
цель (target), всплытие (bubbling) обратно наверх. По умолчанию
обработчики срабатывают на всплытии. Отсюда приём делегирования: один
обработчик на родителе обслуживает все дочерние элементы, включая добавленные
позже.
Пример из работы — построение строк таблицы истории:
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, который ждёт ещё и картинки со стилями). В работе на нём
выполняется первичная отрисовка:
window.addEventListener('DOMContentLoaded', () => {
renderHistory();
drawGraph();
validateForm();
});
4. HTML-формы
Форма — набор элементов ввода, предназначенный для сбора данных пользователя и их передачи обработчику (серверу или клиентскому скрипту).
Тег <form> и его атрибуты
<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:
<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).
Правила размещения форм на страницах
- Формы нельзя вкладывать друг в друга —
<form>внутри<form>недопустим, браузер проигнорирует внутреннюю. - Форм на странице может быть несколько, но они независимы: отправляется только та, в которой произошёл submit.
- Поля должны находиться внутри
<form>, иначе не попадут в отправку. Исключение HTML5 — атрибутform="id-формы"позволяет связать поле, лежащее вне формы. - Передаются только поля с атрибутом
name. Поле безnameне отправляется, даже если заполнено.idдля отправки не используется — он нужен CSS и JS. - Поля с
disabledне отправляются; сreadonly— отправляются. - Невыбранные чекбоксы и радиокнопки не отправляются вообще (а не как пустое значение) — обработчик должен считать отсутствие ключа ответом «нет».
- Радиокнопки одной группы обязаны иметь одинаковый
name— именно это делает выбор взаимоисключающим. <form>— блочный элемент; внутри таблицы его следует размещать целиком внутри<td>, а не между<tr>, иначе разметка невалидна.- Каждое поле должно иметь
<label for="id">— это и доступность (скринридеры), и удобство (клик по подписи активирует поле). - Кнопка
<button>внутри формы по умолчанию имеетtype="submit". Чтобы кнопка не отправляла форму, нужен явныйtype="button". - Клиентская валидация не отменяет серверную: любые проверки в браузере обходятся через 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.
Форма в данной работе
<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, потому что отправка перехватывается и обрабатывается на клиенте:form.addEventListener('submit', (e) => { e.preventDefault(); // отменить стандартную отправку и перезагрузку ... });Без
preventDefault()браузер выполнил бы GET на ту же страницу, и всё состояние было бы потеряно. -
Кнопки R имеют
type="button"— иначе каждое нажатие отправляло бы форму. -
Выбранный R хранится в
<input type="hidden">: кнопки сами по себе значение не хранят, а скрытое поле — штатный способ держать его в форме. -
Чекбоксы X дают множественный выбор, поэтому один submit порождает столько записей, сколько галочек поставлено:
checkboxes.forEach(cb => { if (cb.checked) { history.push({...}); } }); -
submitBtn.disabled = !isValid— кнопка заблокирована, пока данные некорректны, а сообщения выводятся в<span class="error">рядом с полем, а не черезalert(это прямо указано в списке частых ошибок).
5. Каскадные таблицы стилей (CSS)
CSS (Cascading Style Sheets) — язык описания внешнего вида документа. Отделяет оформление от структуры: HTML отвечает за смысл, CSS — за вид.
Способы подключения
- Внешний файл —
<link rel="stylesheet" href="style.css">; кэшируется, переиспользуется между страницами. - Встроенная таблица —
<style>в<head>. Используется в этой работе, так как требование п.2 задания — «таблицы стилей должны располагаться в самом веб-документе». - Инлайновый стиль — атрибут
style="..."у тега. Нежелателен.
Структура правила
селектор {
свойство: значение; /* это объявление */
свойство: значение;
}
Селектор + блок объявлений = правило. Пример из работы:
#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делают стили хрупкими. - Браузер читает селекторы справа налево, поэтому последняя часть должна быть как можно более конкретной.
Все четыре требуемых видов селекторов в работе присутствуют:
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. Происхождение и важность (от низшего к высшему):
- Стили браузера по умолчанию
- Стили пользователя
- Стили автора (
<style>,<link>,style="") - Стили автора с
!important - Стили пользователя с
!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.
Пример из работы — наследование и каскадирование:
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
- Разделение ответственности — структура отдельно, оформление отдельно. HTML остаётся читаемым и семантичным.
- Переиспользование — одно правило
.r-buttonоформляет все пять кнопок. Сstyleпришлось бы дублировать код пять раз. - Поддерживаемость — чтобы изменить вид всех кнопок, правится одна строка, а не N тегов. Меньше кода — меньше шансов пропустить место.
- Размер и кэширование — внешний CSS-файл загружается один раз и кэшируется для всех страниц сайта; инлайновые стили заново передаются с каждой страницей.
- Каскад и наследование работают — инлайновый стиль их фактически
отключает, он всегда главнее и не переопределяется ничем, кроме
!important. - Полная функциональность — через
styleневозможны псевдоклассы (:hover,:focus), псевдоэлементы (::before), медиазапросы (@media), анимации (@keyframes). - Адаптивность — медиазапросы для разных размеров экрана доступны только в таблицах стилей.
- Доступность — пользователь может подключить свою таблицу стилей (крупный шрифт, высокий контраст); инлайновые стили её перебьют.
- Отладка — 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) — отступы вместо фигурных скобок, без точек
с запятой:
$primary: #3399FF
.button
background: $primary
padding: 5px 10px
SCSS (Sassy CSS, .scss) — синтаксис, надмножество CSS: любой валидный
CSS является валидным 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%); }
}
Компилируется в:
.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; переменные
через @:
@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.
Способы трансляции:
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), встраиваемые системы.
Пример из данной работы. Все три характерные сферы клиентских сценариев задействованы:
// 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 в работе перепроверяются при
загрузке:
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 — блочная область видимости
let x = 1; // можно переприсвоить
const y = 2; // нельзя (но содержимое объекта меняется)
До ES6 был только var с областью видимости на всю функцию и всплытием
(hoisting), что порождало классический баг с замыканиями в цикле.
2. Стрелочные функции
const sum = (a, b) => a + b;
rButtons.forEach(btn => btn.classList.remove('active'));
Короткий синтаксис, неявный return без фигурных скобок, и главное —
не имеют своего this, а берут его из окружающего контекста. Это убрало
необходимость в var self = this и .bind(this).
3. Шаблонные строки (template literals)
tr.innerHTML = `<td>${rec.x}</td><td>${rec.y}</td>`;
Обратные кавычки, подстановка ${выражение}, многострочность.
4. Деструктуризация
const { x, y, r } = rec; // из объекта
const [first, second] = arr; // из массива
const { x: coordX = 0 } = rec; // переименование и значение по умолчанию
5. Параметры по умолчанию, rest и spread
function validateY(showErrors = false) { } // default
function sum(...nums) { } // rest — собрать в массив
const copy = [...history]; // spread — развернуть
Math.max(...arr);
6. Классы — синтаксический сахар над прототипами
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»
fetch('/api/points')
.then(res => res.json())
.then(data => render(data))
.catch(err => console.error(err));
8. Модули
export function checkHit(x, y, r) { } // module.js
import { checkHit } from './module.js';
Штатное разделение кода на файлы на уровне языка.
9. Новые структуры данных: Map (ключи любого типа), Set (уникальные
значения), WeakMap, WeakSet.
10. Итераторы, for...of и генераторы
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. Оператор возведения в степень **
2 ** 10 // 1024 — вместо Math.pow(2, 10)
x ** 2 + y ** 2 <= r ** 2
Именно в это преобразуется пользовательский ввод в данной работе:
.replace(/\^/g, '**'); // x^2 → x**2
2. Array.prototype.includes
[1, 2, 3, 4, 5].includes(3); // true
[NaN].includes(NaN); // true — а indexOf даёт -1!
Удобнее и честнее, чем arr.indexOf(x) !== -1: возвращает булево значение и
корректно находит NaN. Применяется в работе для проверки допустимых значений:
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 |