Функции, условия и циклы
Теперь научимся программировать: принимать решения, повторять действия и собирать логику в функции.
Условия: if / else
Программа принимает решения по условию:
const age = 17;
if (age >= 18) {
console.log("Добро пожаловать!");
} else if (age >= 14) {
console.log("Нужно разрешение родителей");
} else {
console.log("Страница доступна взрослым");
}
=== строгое равенство, !==, >, <, >=, <=. Логические связки — && (и), || (или), ! (не).Тернарный оператор
Короткая запись «если — иначе» за одну строку:
const time = 20;
const greeting = time < 12 ? "Доброе утро" : "Добрый день/вечер";
Циклы
Циклы повторяют код. Считаем от 1 до 5:
for (let i = 1; i <= 5; i++) {
console.log("Раз " + i);
}
let n = 0;
while (n < 3) {
console.log("привет");
n++;
}
Чаще всего цикл нужен, чтобы перебрать массив:
const langs = ["HTML", "CSS", "JS"];
for (const lang of langs) {
console.log("Изучаю: " + lang);
}
for (let i = 0; i < langs.length; i++) {
console.log(i + ": " + langs[i]); // с индексами
}
Функции
Функция — именованный блок кода, который можно вызывать сколько угодно раз.
function add(a, b) {
return a + b;
}
const sum = add(2, 3); // 5
const multiply = (a, b) => a * b; // стрелочная функция
multiply(4, 5); // 20
() => {} — современный стиль короче: без function и return, если тело в одну строку.Методы массивов вместо циклов
Современный код часто использует встроенные методы:
const nums = [1, 2, 3, 4];
const doubled = nums.map(n => n * 2); // [2,4,6,8]
const even = nums.filter(n => n % 2 === 0); // [2,4]
const total = nums.reduce((acc, n) => acc + n, 0); // 10
Живой пример: цикл + условие
Классика: вывести числа от 1 до 15, где кратные 3 — как «Fizz», кратные 5 — как «Buzz»:
switch — выбор из многих вариантов
Когда веток больше двух-трёх и они сравнивают по одному значению, switch читается лучше цепочки if:
const role = "admin";
switch (role) {
case "admin":
console.log("Полный доступ");
break;
case "moderator":
console.log("Права модератора");
break;
default:
console.log("Гость");
}
break выполнение «провалится» в следующий case — это популярный источник скрытых багов.Логические операторы и короткое замыкание
&& и || возвращают не только true/false, а само значение — если результат уже ясен, остальное не вычисляется:
const user = { name: "Аня" };
const name = user.name || "Гость"; // если пусто — подставится "Гость"
const isAdmin = true;
isAdmin && console.log("Кнопка «Удалить» показана"); // выполнится только если true
console.log("" || "текст"); // "текст"
console.log(0 && "никогда"); // 0 (0 — «ложное» значение)
false, 0, "", null, undefined, NaN. Всё остальное — «истинное», включая пустые массивы и объекты.break и continue в циклах
Цикл можно досрочно остановить или пропустить итерацию:
for (let i = 1; i <= 6; i++) {
if (i === 3) continue; // пропустить тройку, цикл идёт дальше
if (i === 5) break; // остановиться на пятёрке
console.log(i); // 1, 2, 4
}
continue — «следующая итерация», break — «хватит». break работает и в switch.Область видимости переменных
let и const живут только внутри своего блока { ... }, а var «вылезает» за его пределы — отсюда баги:
if (true) {
let a = 1; // только внутри условия
var b = 2; // утечёт наружу!
}
console.log(a); // ReferenceError: a is not defined
console.log(b); // 2 — работает, но почему? var не знает блока
var не используют: его «весёлая» область видимости порождает труднонаходимые ошибки. Современный код — только const/let.Объект Math
Стандартный набор математических функций — без подключения библиотек:
Math.round(4.6); // 5 — округление
Math.floor(4.9); // 4 — вниз
Math.ceil(4.1); // 5 — вверх
Math.random(); // число от 0 до 1
Math.max(1, 9, 4); // 9
Math.min(1, 9, 4); // 1
const dice = Math.floor(Math.random() * 6) + 1; // кубик от 1 до 6
A + Math.floor(Math.random() * (B - A + 1)). Выигрывает в лотереях казино и играх на сайтах.Цикл по объекту: for...in и Object.keys
Объекты перебираются иначе, чем массивы. for...in идёт по ключам, а утилиты Object.* отдают ключи, значения или пары массивом:
const config = { theme: "dark", lang: "ru" };
for (const key in config) {
console.log(key, config[key]); // theme dark, lang ru
}
Object.keys(config); // ["theme", "lang"]
Object.values(config); // ["dark", "ru"]
Object.entries(config); // [["theme","dark"],["lang","ru"]]
Object.entries + destructuring — самый элегантный перебор: for (const [key, value] of Object.entries(config)).Параметры по умолчанию и rest
Функции могут подставлять значения, если аргумент не передан, и «собирать» все лишние аргументы в массив:
function greet(name = "Гость") {
return `Привет, ${name}!`;
}
greet(); // "Привет, Гость!"
function sumAll(...nums) { // rest-параметр
return nums.reduce((acc, n) => acc + n, 0);
}
sumAll(1, 2, 3, 4); // 10
const nums = [1, 2, 3];
Math.max(...nums); // 3 — распаковка массива в аргументы
... перед параметром функции — «rest» (собрать), перед массивом в вызове — «spread» (распаковать).Ранний выход (early return)
Стиль «охрана у входа» ускоряет чтение кода: редкие случаи проверяем в начале и выходим, основную логику оставляем без каскада вложенных if:
function moveUser(user, where) {
if (!user) return; // нет пользователя — дальше не идём
if (!where) return "Куда едем?";
// основная логика без лишней вложенности
return `Перемещаем ${user.name} в ${where}`;
}
Замыкания: функция внутри функции
Функция видит переменные, объявленные вокруг неё, даже после выхода из внешней функции. Так рождается «счётчик с памятью»:
function makeCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = makeCounter();
counter(); // 1
counter(); // 2
counter(); // 3 — count жив внутри
Обработка ошибок: try / catch
Код, который может упасть (запрос к сети, работа с файлом), оборачивают в try, а реакцию на падение кладут в catch:
try {
JSON.parse("это не json");
} catch (err) {
console.error("Не удалось разобрать данные:", err.message);
} finally {
console.log("Выполнится в любом случае");
}
forEach: прогулка по массиву
Выполнить функцию для каждого элемента без ручного цикла:
const fruits = ["яблоко", "банан", "киви"];
fruits.forEach(fruit => {
console.log(fruit.toUpperCase());
});
findIndex: позиция первого совпадения
Найти индекс элемента, который удовлетворяет условию:
const users = [{name: "Аня"}, {name: "Боря"}, {name: "Вера"}];
const index = users.findIndex(u => u.name === "Боря");
// index === 1; если не найден, вернётся -1
every и some: все или некоторые
Проверки, распространяющиеся на всю коллекцию:
const scores = [8, 9, 10, 7];
scores.every(s => s >= 5); // true — все прошли
scores.some(s => s === 10); // true — десяточка есть
Русская сортировка: localeCompare
Стандартная сортировка по юникоду разбросает ё по-своему:
const names = ["Влад", "Аня", "Ёжик", "Боря"];
names.sort((a, b) => a.localeCompare(b, "ru"));
// ["Аня", "Боря", "Влад", "Ёжик"] — по правилам языка
Сортировка чисел
По умолчанию sort сравнивает строки — числа нуждаются в компараторе:
const nums = [10, 2, 33];
nums.sort(); // [10, 2, 33] ой
nums.sort((a, b) => a - b); // [2, 10, 33]
Почему нельзя === массивам
Массивы сравниваются по ссылке, а не по содержимому:
const a = [1, 2];
const b = [1, 2];
a === b; // false — разные «контейнеры»
// сравниваем содержимое по одному элементу:
a.length === b.length && a.every((v, i) => v === b[i]);
Копии массива: slice и spread
Не мутируйте исходник из-за рефакторинга — сначала скопируйте:
const source = [1, 2, 3];
const copy1 = source.slice();
const copy2 = [...source]; // spread, без вложений
copy1.push(4);
source; // [1, 2, 3] — цел
Array.isArray
Как отличить массив от объекта — и почему typeof не поможет:
typeof []; // "object" (мешает)
Array.isArray([]); // true
Array.isArray({}); // false
Порядок чисел подряд
Массив номеров из «дырявого» конструктора строим честно:
const pages = Array.from({ length: 5 }, (_, i) => i + 1);
// [1, 2, 3, 4, 5]
Строка в массив символов
Два способа разгрызть строку:
"привет".split(""); // ["п", "р", ...]
[..."привет"]; // то же, но с эмодзи работает лучше
"а,б,в".split(","); // ["а", "б", "в"]
map с индексом
Второй аргумент — порядковый номер текущего элемента:
const list = ["a", "b"];
list.map((item, i) => `${i + 1}. ${item}`);
// ["1. a", "2. b"]
break для быстрого выхода
Нашли нужное — цикл можно останавливать:
const ids = [10, 20, 30, 40];
let found = null;
for (const id of ids) {
if (id === 30) {
found = id;
break; // дальше не шагаем
}
}
Цепочки: filter().map()
Обработку удобно выстраивать цепочкой вызовов:
const orders = [120, 45, 300, 80];
const big = orders
.filter(x => x >= 100)
.map(x => x * 1.3); // [156, 390]
Среднее по оценкам
Маленький этюд метода reduce — сумма, а затем деление:
const marks = [4, 5, 3, 5];
const avg = marks.reduce((sum, m) => sum + m, 0) / marks.length;
// 4.25
Тренировка
- Напишите функцию
isEven(n), возвращающуюtrueдля чётных чисел. - Выведите через
forстроку из 5 «⭐» (соберите в переменную). - Добавьте
if, который скажет вам, можно ли покупать «взрослые» продукты по возрасту. - Через
mapувеличьте все цены массива на 10%.
if: первая развилка
if (условие) { ... } — «если правда, сделай это». Блок в скобках срабатывает только когда условие истинно; иначе — молчание.
const age = 20;
if (age >= 18) {
console.log("доступ открыт");
}
else: путь «иначе»
else — «а если не сработало». Пара if/else покрывает все случаи «да/нет» без второго условия.
const age = 15;
if (age >= 18) {
console.log("взрослый");
} else {
console.log("ребёнок");
}
else if: лестница условий
Несколько вариантов — лестница: if → else if → else. Проверки идут по порядку; первая истинная «забирает» выполнение.
const score = 85;
if (score >= 90) { grade = "A"; }
else if (score >= 75) { grade = "B"; }
else { grade = "C"; }
Логическое И: обе проверки
&& означает «и то, и другое»: истинно, только когда оба условия верны. Одно ложно — весь результат ложь.
const age = 22;
const hasTicket = true;
if (age >= 18 && hasTicket) {
console.log("проход есть");
}
Логическое ИЛИ: хотя бы одна
|| — «достаточно одного»: истинно, если хоть что-то из пары верно. «Лень» оператора экономит работу в длинных цепях.
const card = null;
const cash = 100;
if (card || cash > 0) {
console.log("можно оплатить");
}
Отрицание и скобки: порядок логики
! разворачивает: !ready — «не готово». Скобки расставляют приоритет: !(a && b) ≠ !a && b. Думайте «что именно спросили».
const emailOk = true;
const phoneOk = false;
const ready = emailOk && !phoneOk;
console.log(ready); // true
Строгое и нестрогое: ещё раз ===
Помним про «5" === 5»? На практике это ловит «строку из ввода» против числа. В задачах от сервера типы «болтаются» — строгое сравнение спасает от ложных срабатываний.
if (input.value === "да") {
console.log("ответ «да»");
}
Когда switch лучше if'а
Когда сравниваем «одно значение со списком» — switch читается как таблица и не просит повторных условий: switch (day) { case 1: ... }. Изящно для названий дней, кодов, статусов.
switch (day) {
case 1: name = "пн"; break;
case 2: name = "вт"; break;
default: name = "?";
}
Тернарник в строке: подстановка по условию
Тернарник возвращает значение — значит, его можно «встроить» в текст: `статус: ${ok ? "да" : "нет"}`. Строчка короче и читается «как мысль».
const ok = true;
console.log(`Готово: ${ok ? "✓" : "✗"}`);
Практика: классификатор возраста
Функция ageLabel(возраст): до 7 — «дошкольник», 7–17 — «школьник», 18–64 — «взрослый», 65+ — «пенсионер». Решите её через лестницу else if, затем перечитайте: границы «прилипают»?
function ageLabel(age) {
if (age < 7) return "дошкольник";
if (age < 18) return "школьник";
if (age < 65) return "взрослый";
return "пенсионер";
}
Цикл со счётчиком: for
for (старт; условие; шаг) — классический цикл: создаём счётчик, проверяем предел, делаем шаг. Идеален, когда известно количество повторов.
for (let i = 0; i < 3; i++) {
console.log(i); // 0, 1, 2
}
for...of: перебор значений
for (const item of list) — «каждый элемент из списка»: не нужны индексы и длина. Лучший стартовый цикл для массивов и строк.
const sum = [10, 20, 30];
for (const n of sum) {
console.log(n * 2);
}
while: условие на входе
while (условие) повторяет, пока верно; проверка — до каждой итерации. Когда «не знаем, сколько раз» — например, «пока не введено верно» — это он.
let fuel = 10;
while (fuel > 0) {
console.log("запуск: 1 км");
fuel -= 2;
}
do...while: хотя бы раз
do { ... } while (условие) выполняет тело минимум однажды, проверяя условие в конце. Оправдано, когда «первый раз всегда делаем»: запрос подтверждения, счёт, игра.
let roll;
do {
roll = Math.floor(Math.random() * 6) + 1;
} while (roll !== 6);
console.log("выпало шесть!");
Прерывание цикла: break и continue
break — «выходить из цикла немедленно»; continue — «перейти к следующей итерации». Оба прерывают «лишний» текст.
let i = 0;
while (i < 10) {
i++;
if (i === 3) continue; // пропустить 3
if (i === 7) break; // стоп на 7
console.log(i);
}
Бесконечный цикл: как не уйти
Цикл, чьё условие «не убывает», крутится вечно и «вешает» вкладку: ничего не успевает, память растёт. Признаки: while (true) без break, счётчик не меняется, шаг — к ложному пределу.
Вложенные циклы: сетки и пары
Цикл внутри цикла — «таблица умножения» и «каждый с каждым»: внешний идёт по строкам, внутренний — по клеткам. Количество итераций — произведение.
for (let r = 1; r <= 3; r++) {
let line = "";
for (let c = 1; c <= 3; c++) line += r * c + " ";
console.log(line);
}
Аккумулятор: сумма по списку
Паттерн «собрать итог»: переменная-накопитель, цикл по массиву, каждую итерацию прибавляем. Так считают суммы, произведения, длины, максимумы.
const prices = [99, 199, 299];
let total = 0;
for (const p of prices) {
total = total + p;
}
console.log(total); // 597
Ищем максимум в массиве
Те же «шаги»: стартуем с -Infinity, сравниваем каждый элемент, перезаписываем при большем. Через пару строк у вас готова функция max из любой коллекции.
const marks = [4, 5, 3, 5, 4];
let best = -Infinity;
for (const m of marks) {
if (m > best) best = m;
}
console.log(best); // 5
Практика: лесенка из звёздочек
«Распечатать» треугольник 1,2,3 звезды: цикл строк, внутри — наполняем строку вложенным циклом, выводим. Час возни — и вы «нарисовали» графический вывод без CSS.
for (let row = 1; row <= 3; row++) {
let s = "";
for (let k = 0; k < row; k++) s += "*";
console.log(s);
}
Функция: имя, параметры, результат
Функция — «отдельный кусок работы» с именем: приём (параметры), действие, возврат. Вызываете — получаете результат. Один раз написали — пользуетесь везде.
function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5
Одна задача одной функции
Функция «про одну вещь» — подарок вашему будущему: её легко читать, тестировать, переиспользовать. Если внутри «и считает, и рисует, и пишет» — разделите пополам.
function withTax(price) {
return Math.round(price * 1.2);
}
// одна функция — одна мысль
Ранний выход: return прекращает работу
return завершает функцию сразу. Отсюда приём «проверки-ворота»: невалидный вход — ранний выход, вместо «если не ошибка, делаем...».
function hello(name) {
if (!name) return; // выход раньше
return "Привет, " + name;
}
Стрелочные функции: компактный стиль
(параметры) => результат — стрелка: короче, удобна «в один вызов», бережёт от «this-ловушек» (вернёмся в уроке 9). В основном коде — стрелки, в определениях «тяжёлой» логики — function.
const double = (x) => x * 2;
const greet = (name) => `Привет, ${name}`;
Передача функции в функцию: колбэк
Функция может быть аргументом другой функции: обработчик события, критерий фильтра, «что сделать с каждым» — это колбэк. Методы массивов (map/filter/forEach) построены именно на нём.
const nums = [1, 2, 3];
const squared = nums.map((n) => n * n);
console.log(squared); // [1, 4, 9]
Локальный мир функции: внутри и снаружи
Переменные, объявленные внутри функции, «живут» только там — наружу не «светятся». Снаружи их не видно, внутри видны и «свои», и «верхние». Это область видимости.
function work() {
const inner = "локальная";
}
console.log(inner); // ReferenceError
Рекурсия: функция вызывает себя
Функция, которая вызывает саму себя с «уменьшенным» входом, — рекурсия: «факториал», «обход дерева», «лесенка из пальцев». Для циклов-«деревьев» она естественнее вложенных циклов.
function fact(n) {
return n <= 1 ? 1 : n * fact(n - 1);
}
console.log(fact(5)); // 120
Дефолт через || и ?? против if
Три способа задать «значение по умолчанию»: arg || fallback («если фолзи — замени»), arg ?? fallback («если null/undefined — замени»), и обычный if. ?? — самый «аккуратный» для настоящих пропусков.
function show(name) {
const n = name ?? "Гость";
console.log("Привет, " + n);
}
Практика: мини-калькулятор
Функции add/sub/mul/div + одна «действие» через switch: calc("+", 3, 4). Собирается из изученного: функции, switch, return. Попробуйте добавить «%».
function calc(op, a, b) {
switch (op) {
case "+": return a + b;
case "-": return a - b;
default: return NaN;
}
}
Итоги урока 8: чек-лист читаемости
Функции, условия (if/else/switch/тернарник), циклы (for/while/do/for...of), аккумуляторы, колбэки, рекурсия, области видимости. Чек-лист: 1) функции «про одну задачу», 2) условия — «по строгости сверху», 3) цикл «знаю сколько — for, нет — while», 4) каждая функция с именем-глаголом.
Именованные и анонимные: две «шляпы» функций
Функция может иметь имя (function doSomething) или быть «анонимной» (сразу в колбэке). Имя «придаёт» само-описание и стек-трейсы становятся читабельными. «Шляпы» — способ рассказать о предназначении.
function double(n) { return n * 2; }
Значения по умолчанию: надёжные параметры
Параметр с «дефолтом» не «падает» при пропуске: function greet(name = "Гость"). Дефолт применяется при undefined. «Застрахованная» функция дружелюбнее «строгой» к вызовам извне.
function hello(name = "Гость") {
return "Привет, " + name;
}
Возврат нескольких: объект как «пакет»
return единственное значение; «несколько» — возвращайте объект: {sum, count}. Другой вариант — массив; но объект «с именами» читается яснее. «Пакет данных» из функции — «прочный» контракт.
function stats(nums) {
return { count: nums.length, sum: ...};
}
Стрелочные функции: короткий синтаксис
Стрелка: (a, b) => a + b — компактнее «function». Один параметр без скобок, «выражение» — без return (неявно). Идеальны в колбэках: map, filter, события.
const add = (a, b) => a + b;
Стрелочные функции: почему без своего this
Стрелка «не создаёт» собственный this — наследует «внешний». В обработчиках и методах это часто «спасение» (вместо «обвязки» замыканий). Классика: до стрелки — that=this, теперь — сама стрелка.
btn.addEventListener("click", () => {
save(this.data); // this — внешний
});
Объявление и выражение: два вида записи
function f() {} — «объявление» (работает «до» строки, hoisting). const f = () => {} — «выражение» (до объявления — «нет»). Порядок зависит от стиля; «стрелка+const» — современный стандарт.
Колбэки: функция как аргумент
Колбэк — функция, переданная в другую функцию: «call me later». setTimeout, обработчики, методы массивов — все «едят» функции. «Намерение» передаётся «действием», а не «результатом».
btn.addEventListener("click", () => alert("Нажато!"));
Передача по ссылке: объекты «деликатны»
Примитивы передаются «копией»; объекты/массивы — «ссылкой». Изменение «внутри» меняет «исходник». «Копия» нужна осознанно: spread ({...obj}, [..arr]) «глубоко» не копирует. «Ссылка» — ответственность.
function addOne(arr) { arr.push(1); } // мутирует
Побочные эффекты: зачем функции «тихие»
Функция «чистая» — без внешних изменений: тот же вход → тот же выход. «Побочный» эффект (запись в консоль, DOM, глobal) — «шум» снаружи. Чем «чище» логика — тем легче тестировать и думать.
Рекурсия простая: функция зовёт себя
Функция может вызывать саму себя — база (граница) + шаг. Отсчёт «вниз», обход дерева, «факториал». Без «базы» — бесконечная «лестница» (переполнение стека). «Рекурсия» элегантна на «вложенных» данных.
function countdown(n) {
if (n === 0) return; // база
console.log(n);
return countdown(n - 1); // шаг
}
Последний элемент: pop с безопасностью
pop() берёт последний элемент «из конца» (и убирает его из массива). На пустом массиве — undefined. «Стек» — «последний пришёл — первый ушёл»: pop/push создают такую логику «сама по себе».
const last = stack.pop();
В начало: unshift и shift
unshift(el) — «в начало», shift() — «из начала». «Очередь» — «первый вошёл — первый вышел»: push+shift. Тонкость: unshift/shift «сдвигают» индексы — на больших массивах медленнее, чем работа «с конца».
queue.push(task);
const next = queue.shift();
Поиск: indexOf и includes для массивов
indexOf(значение) — «позицию или -1»; includes(значение) — «есть ли» (булево). Для чисел/строк — просто; для объектов — «ссылка», не «содержимое». Сравнение «строгое» (===).
const has = colors.includes("красный");
filter: «оставить подходящих»
filter возвращает «новый» массив из элементов, где колбэк — true. Не меняет исходный. Цепочки «фильтров» чисты и читаемы. «Сито» — базовый «отбор» коллекций.
const adults = people.filter(p => p.age >= 18);
map: «отражение» каждого элемента
map создаёт «новый массив» с результатами колбэка для каждого элемента. «Трансформация» «1:1»: числа в строки, объекты в подписи, разметку в значения. Незменяемый источник — «чистый» стиль.
const tags = ids.map(id => `#${id}`);
reduce: сборка в единое значение
reduce «сжимает» массив в одно: сумма, объект-итог, «максимальное». Колбэк получает «аккумулятор» и «текущий». Начальное значение — второй аргумент. «Складывание» коллекций — универсальный «сборщик».
const sum = nums.reduce((acc, n) => acc + n, 0);
Срез с конца: отрицательные индексы в slice
slice(-2) — «последние два», slice(1, -1) — «от второго до предпоследнего». Отрицательные индексы считаются «с хвоста». slice не мутирует — «вырезает копию». «Прочитать хвост» — его родная роль.
const lastTwo = arr.slice(-2);
Слияние массивов: spread в действии
spread «разворачивает» массив в элементы: [...a, ...b] — «склейка». Простой, «не мутирующий» способ объединить. Против concat — «читаемый» синтаксис и «свои» места для «новых» значений.
const merged = [...left, ...right];
Компаратор для чисел: (a, b) => a - b
sort() без «компаратора» сортирует «как строки» (10 < 9!). Честная сортировка чисел: (a, b) => a - b (возрастание) или b - a (убывание). Функция «судит» по знаку разности.
nums.sort((a, b) => a - b);
Из массива в строку: join с разделителем
arr.join(", ") — «склейка» строк через разделитель. Без аргумента — «запятая-оболочка» по умолчанию. Разумные разделители («; ", « », «, ») делают список «живым» в тексте и в выводе.
["яблоко", "груша"].join(", "); // "яблоко, груша"
Свойство из переменной: запись в квадратных скобках
obj[key] (с переменной-ключом) читает/пишет динамическое свойство; через «точку» — только «фиксированное имя». Таблицы «по ключу», словари «по id», «настройки по имени» — «квадратные скобки» их родной дом.
const key = "theme";
settings[key] = "dark";
Пары «ключ-значение»: Object.entries
Object.entries(obj) возвращает массив «пар» [ключ, значение]. С ним — перебор и построение «строк таблиц». В паре с for-of — «читаемый» обход. «Словари» в объекты — «раскладка» их «сути».
for (const [key, value] of Object.entries(user)) {
log(key, value);
}
Проверка ключа: оператор in
key in obj — «есть ли свойство» (включая «унаследованные»). vs obj[key] !== undefined — проверяет значение, а не «наличие». Для «ключа с значением undefined» различие важно. «in» — про «существование».
if ("token" in response) { /* есть ключ */ }
Неглубокая копия: Object.assign и spread
Object.assign({}, obj) и {...obj} — «поверхностную» копию: вложенные объекты «общие». «Глубокую» копию — JSON-трюком или библиотекой. «Поверхность» — «переиспользуемая» «пружина» для настроек.
const copy = { ...defaults, ...overrides };
Регистр строки: upper и lower на практике
toUpperCase() / toLowerCase() — «переодевают» регистр. Для сравнения «без регистра» — приводите обе стороны к lower. Классика: поиск и «проверки» по городу, названию, логину.
if (town.toLowerCase() === "москва") { /* ... */ }
Обмен данными: JSON-текст и обратно
JSON.stringify(obj) — объект в «строку-текст», JSON.parse(text) — обратно. Сохранение в localStorage, отправка на сервер, чтение конфигов. «Текстовый» формат для «машинного» общения.
const text = JSON.stringify(data);
const back = JSON.parse(text);
Проверка типа: typeof и его «слабости»
typeof сообщает «тип»: number, string, boolean, object, function... «Слабости»: typeof null → "object", массивы → "object". Для массивов — Array.isArray(x). «Тип» — «первый» фильтр перед работой.
if (Array.isArray(x)) { /* это массив */ }
Практика: гистограмма частот в объекте
Посчитайте «частоту» значений: объект-«словарь», ключ — элемент, значение — счётчик. Цикл + «приращение с fallback» (или с «нулём»). Один «проход» — и «частотная» картина готова.
const freq = {};
for (const w of words) freq[w] = (freq[w] ?? 0) + 1;
Практика: пагинация «слайсом»
Страницы списка: «страница 3 по 10» = arr.slice(page*10, page*10+10). slice «вырезает» «окно» без мутаций. Индексы «с границами» → «кнопки» «влево/вправо» через переменную page. Маленькая «пагинация» готова.
const page = 2, size = 10;
const slice = items.slice(page * size, page * size + size);
Итоги урока 8: функции и коллекции готовы
Функции (объявление, стрелки, колбэки, default-параметры), массивы (pop/push, map/filter/reduce, slice, sort), объекты (ключи, entries, копии, JSON). «Данные» обрабатываются цепочками — «чисто» и «выразительно». Двигаемся дальше — к DOM.
Функция как рецепт
Функция — «рецепт» с названием: принимает «ингредиенты» (параметры), выдает «блюдо» (return). Один рецепт можно «вызвать» много раз. Повторяющиеся действия «упаковываются» в функцию. «Рецепты» — «кирпичи» программ.
Объявление и вызов
function имя(параметры) { тело }. Вызов — «имя(аргументы)». Фигурные скобки — «рамка» тела. Вызов «без» скобок — «передача функции», не «запуск». Объявление «подъём» (hoisting) — «ранние» вызовы работают.
function greet(name) {
console.log("Привет, " + name);
}
greet("Аня");
Параметры и аргументы
Параметр — «слот» в определении; аргумент — «значение» при вызове. Значение аргумента «попадает» в параметр. Число слотов — «штатное расписание» вызова. Имена параметров — «осмысленные»: price, count.
Возврат: оператор return
return «возвращает» значение наружу. Без return — функцию «возвращает» undefined. Произведённый результат «уходит» в место вызова. «Возврат» превращает функцию в «выражение».
function square(n) { return n * n; }
console.log(square(5)); // 25
Ранний выход через return
return «внутри» if завершает функцию «досрочно». «Проверки-стражники» в начале — «плоская» логика. Меньше else — «закон» чистого кода. «Ошибка» — «вернул рано» — «светофор» функции.
Значения параметров по умолчанию
= в параметре задаёт «запасной» вариант при «отсутствии» аргумента. greet(name = "Гость"). Полезно «не требовать» всё от всех. «Дефолты» — дружелюбие API. «Умная» функция «прощает» пустоту.
Стрелочная функция: короткая запись
() => {} — «стрелка»: параметр, стрелка, тело. Одна строка без скобок — «неявный» return. «Короткая» форма для колбэков и сборок. Отличия от function — «тонкости this» (позже). «Стрелки» — «любимец» современности.
const add = (a, b) => a + b;
Анонимная функция и константа
Функция «без имени» — анонимная. Её «хранит» const. const run = function() { … } — «функциональное выражение». Хранение в переменной — «функция как значение». «Имена» при отладке «удобнее», но «анонимность» «легальна».
Имя функции: глагол-намерение
Имя «начинается» с действия: calculate, show, save, remove. Читается «как команда»: showPrice(). Не «priceFunction» — «что делает», а «как называется». Имя — «контракт» поведения. «Говорящее» имя — «половина» документации.
Счётчик вызовов функции
Локальная переменная «внешнего» уровня + вызов «внутри» — «счётчик». Каждый вызов «увеличивает». Для «статистики» и «логов». Замыкание «помнит» счётчик. «Секретариат» функций считает «сколько раз» что-то делалось.
let calls = 0;
function track() { calls++; console.log(calls); }
Область видимости в функциях
let «внутри» функции — «локальная»: наружу «не видна». Одноимённая «внешняя» и «внутренняя» — «разные» жизни. Параметры — «тоже» локальные. «Кладовые» функций изолированы. Имена «не сталкиваются» — «тишь» в программе.
Глобальные и локальные области
Глобальная переменная — «видна всем»; локальная — «своей» функции. Глобальных «мало» — «гигиена». Локальные «одинаковые имена» — «редкость» путаниц. «Уровни» области — «этажи» дома кода.
Замыкание: короткий взгляд
Функция «помнит» переменные своей области «после» её выхода. Внутренняя функция «захватывает» окружение. Полезно для «генераторов», «счётчиков», «фабрик». Полное «понимание» — позже; «зачаток» — сейчас.
Чистая функция: идеал
Чистая функция: одинаковые «входы» → одинаковые «выходы», «без побочных» действий. Не «трогает» внешние переменные. Легко «проверять» и «переиспользовать». Девиз: «вычислю и верну», «не ломай мир».
Примитивы: передача по значению
Числа и строки «передаются» копией: функция «меняет» копию, оригинал «цел». Изменение параметра «не видно» снаружи. «По значению» — «безопасный» канал. Примитивы «не протекают» из функции.
Объекты: передача по ссылке
Массив/объект «передаются» ссылкой: изменение «внутри» — «видно» снаружи. Меняете «сам объект». Для «мутаций» это часто «намеренно». Но «осторожно» с «неожиданными» правками. «Ссылка» — «общий» ящик.
Функция как значение
Функцию можно «хранить» в переменной, «передать» аргументом, «вернуть». «Функции высшего порядка» «принимают» функции. Массив функций, «объект-маршрутизатор». «Код как данные» — «зрелая» мощь JavaScript.
Колбэк: функция в функции
Колбэк — функция, «переданная» другой для вызова «потом». События, таймеры, методы массивов «кишат» колбэками. setInterval(() => …, 1000). «Обратный звонок» — «отложенное» действие. Стрелки «дружат» с колбэками.
setTimeout(() => console.log("через секунду"), 1000);
Практика: сумма через функцию
Напишите sum(a, b) с return; используйте в нескольких «разных» вызовах. Добавьте «среднее» avg(a, b). «Проверьте» на числах. Простая практика «закрепляет» вызовы и возврат. Функции «набирают» «мускулатуру».
Практика: проверка полей функцией
Напишите validate(name, age): пустое ли имя, возраст «в диапазоне». Возвращайте true/false. Используйте с if. «Проверки-функции» — «модульность» форм. Читается как «условие человека»: «есть ли право войти».
Модульность: разбиение на функции
Большая задача «бьётся» на функции-шаги: readData, processData, render. Каждая — «самодостаточный» этап. Поиск багов — «сужается» до одной функции. «Модульность» — «способ мышления», не «прихоть». Разбиение — «архитектура» кода.
DRY: не повторяй себя
DRY (Don't Repeat Yourself) — «одинаковый» код «одном месте». Повтор — «риск» рассинхрона правок. Функция «собирает» разрозненные копии. Три «одинаковые» строки — уже «кандидат» в функцию. DRY — «гигиена» проекта.
Глагольные имена: намерение в названии
showList(), saveToStorage(), applyDiscount(). Глагол «впереди» — как «инструкция». Чтение файла функций — «оглавление» программы. Избегайте «пустых» doWork(). Название — «обязательство» перед читателем.
Рефакторинг повтора в функцию
Рефакторинг: «общие» строки → функция с параметрами-различиями. Результат — «менее строк», «одно место правды». Правка «в одном месте» «распространяется». «Чистка» кода — «не косметика», а «инвестиция».
Библиотека утилит: сборка функций
Файл-«шкаф» с «маленькими» функциями: formatPrice, pad, randomInt. Однократная «напряжённая» работа — «многократная» польза. «Утилиты» — «инструменты» проекта. Стрелки + константы — «компактный» стиль библиотек.
Обнаружение ошибок через функцию
Функции «изолируют» ошибки: «стрельба» в одном месте «не взрывает» всё сразу. Сообщения «ошибок» конкретны по функциям. Печать «входных» значений — «первый» расстрел «подозреваемых». «Острова» функций — «безопасные» берега.
Одна функция — одна ответственность
Функция «делает» одно дело: «считает» или «рисует», «чем» — «не обе». Если «и» — разбейте. Одно «название» — одно «действие». Проще «тестировать» и «понимать». «Принцип» — «фундамент» проектирования.
Комментарии к функциям
Над функцией — «пара строк»: что «делает», что «принимает», что «возвращает». «Зачем» — если «не очевидно». Код «говорит» как, комментарий — «зачем». Чрезмерные «лекции» не нужны: «сырая» правда кода — «голос».
Практика: конвертер валют
toEur(rub), toUsd(rub) — функции-конвертеры с курсом. Вызов «по нескольким» суммам. «Чистые» функции: вход → выход. Добавьте «округление» — округлите итог. «Конвертер» — «живая» модель «маленького» банка.
Практика: словарь приветствий
greet(lang) — switch: "ru", "en", "es" → приветствия. default — «общее». «Словарик» локализации «в функции». «Расширение» языков — одна функция. «Локализация» — «будни» больших приложений.
Массивы: краткий повтор
Массив «хранит» список; методы «обрабатывают». push/pop, length, индексы — «база». Теперь — «инструменты высшего порядка». Чтение «методов» — «словарная» работа: map, filter, every. Коллекции «дышат» «функционально».
includes в массиве
arr.includes(x) → true/false — «есть ли значение». «Наличие» без поиска позиции. Для «чёрных списков», «допусков», «вариантов». «Чувствителен» по типам: includes(5) vs "5". «Быстрая» проверка «члена списка».
if (allowed.includes(role)) { // доступен }
Поиск позиции: indexOf в массиве
arr.indexOf(x) — «индекс» или -1. Индекс — для «разрезания», «переноса», «хэйлайта». «Не найден» → -1 — «проверяйте». «Первый» случай. Аналогия со строками «тот же» стиль. «Позиционный» поиск — «соло» массивов.
Проверки: every и some
every — «все ли удовлетворяют условию»; some — «хоть один». Колбэк на каждый элемент. «Правила-клятвы» данных: «все цены > 0». «Хоть один» в корзине «на складе». Возвращают boolean. «Проверочные» функции — «стражники» данных.
Фильтрация: filter
arr.filter(predicate) → «новый» массив «подходящих». Оригинал «цел» — «иммутабельность». Колбэк «да/нет» на элемент. «Отбор» по условию — «воронка» данных. Любая «журналистика» списков начинается с filter.
const adults = users.filter(u => u.age >= 18);
Трансформация: map
arr.map(fn) → «новый» массив с «применённым» fn к каждому. Длины «совпадают»: 1 к 1. Цены «с налогом», имена «в верхнем». «Транзит» данных «по конвейеру». «Маппинг» — «трансформатор» структур.
Сокращение: reduce
arr.reduce(acc, item) → «одно» значение из «всех». Начальное значение — второй аргумент. Сумма, произведение, «группировка». acc «переходит» между итерациями. «Сила» reduce — «всё счетное» в «одном» проходе.
const total = items.reduce((sum, item) => sum + item.price, 0);
Сортировка: sort со строками и числами
sort() «по возрастанию» строк — «по умолчанию». Числа — «ЧЕСТЬ»: сортируют «как строки»! Компаратор a - b «чинит». «Мутирует» оригинал — «копия» сначала. «Порядок» — «вид» решает «аналитик».
Копия массива: спред [...]
[...arr] — «новый» массив с элементами. «Копия» до сортировки/мутаций. `const copy = [...arr]`. Деструктуризация в «пару» — «плюс»: first = [..., arr]. «Спред» — «лёгкая» копия «верхнего» уровня.
Поиск первого: find
arr.find(predicate) → «первый» подошедший «элемент» (не массив). Не нашли — undefined. По «id», «имени», «статусу». «Значение» vs «массив» — разница с filter. «Первый» — «точный» инструмент «назначения».
Плоский проход: flat
Вложенный массив «расплющивается»: [[1,2],[3]] → flat() → [1,2,3]. Один уровень по умолчанию; flat(2) — глубже. Смешанные «матрицы» для «обработки» — «одна строка». «Формулы» глубин — «сбор» данных в единый ряд.
Деструктуризация массива
[a, b] = arr — «вынуть» по позициям. Пропуск: [first, , third]. Остаток: ...rest. «Правое» присваивание «быстрое». Замена «в парах» без «временной». «Распаковка» — «стиль» современности.
const [x, y] = point; // x=point[0], y=point[1]
Разворот: reverse
arr.reverse() — «переворачивает» массив «на месте» (мутирует). Для «нового» — [...arr].reverse(). «С конца» проще: arr[arr.length - 1]. «Обратный» проход — «популярный» трюк. «Диапазон» приёма — «игры» и «анализ».
Цепочки методов: map + filter
arr.filter(...).map(...) — «конвейер»: сначала «отбор», потом «трансформация». Каждый шаг «возвращает» массив. Чтение «слева направо», как «предложение». Оптимизация «не нужна» на «малых» данных. «Цепочки» — «плавный» код.
Практика: список задач на массивах
Массив «задач» со статусами; filter «в работе»; map — «заголовки»; some — «есть ли срочные»; count через length. «Доска задач» — «одна» маленькая панель из «методов». «Данные» + «операции» = «продукт».
Практика: группировка по длине
Words: при помощи reduce — словарь «длина → слова». «Группировка» — «редька-мастер» ридуса. Аккумулятор — объект. Пробуем «по первым буквам». «Фасеточный» анализ — «аналитика» в «пяти» строках.
Практика: флаг наличия
some «отвечает»: «хоть один продан?» each «все в наличии?» Проверки «списка» — «вопросы» к данным. Пометка «каталог полный» или «дефицит». «Флаги» — «мгновение» решения «без циклов».
Практика: уникальные значения
Дубли в массиве «убрать»: из «всех» в «Set», затем «в массив». [...new Set(arr)]. «Уникальность» для «тегов», «городов», «категорий». Set — «по умолчанию» уникален. «Чистка» данных — «добыча» списков.
Практика: топ-3 максимумов
Скопируйте, отсортируйте по убыванию, срежьте slice(0, 3). «Рейтинг» чисел «на скорую руку». Строки — «попарно» с косозвучным «сравнением». «Топ» — «частый» бизнес-запрос. Комбинация sort + slice — «готовый» ответ.
Практика: случайный элемент списка
Math.random() * arr.length → индекс; arr[индекс]. «Через floor» — целый. «Рандом-ставка», «кого-позвать», «викторина». Случайный «выбор» — «игровая» палочка. «Хрупкое» «устройство» случайности — «развлечение» рядом.
Объект: пары ключ—значение
Объект «запоминает» по ключам: { name: "Аня", age: 20 }. Ключ — строка, значение — «любое». «Словарь» свойств — «картотека» данных. Читается «как таблица» в голове. Объекты — «ткань» современных данных.
const user = { name: "Аня", age: 20 };
Чтение свойств: точка и скобки
user.name — «доступ по точке». user["name"] — «по строке» (динамика). Точка — «для известного» ключа. Скобки — для имени «из переменной»: user[key]. Оба «пути» к «значению» — «шоссе» объектов.
Запись и изменение свойств
user.age = 21 — «обновление»; user.city = "Мск" — «новое» свойство. Объект «мутируется»: свойства «растут» и «меняются». const не «стоп» изменениям свойств. «Объект-блокнот» — «переписываем» страницы, «не» «блокнот».
Удаление свойства: delete
delete user.age — «убирает» пару. Свойство «исчезает»; user.age → undefined. «Чистая» таблица «без мусорных» колонок. Осторожно: наличие vs значение. «Уборка» данных — «редкая», но «нужная» операция.
Присутствие ключа: оператор in на практике
"city" in user → true/false — «есть ли ключ». Отличие от user.city: значение может быть undefined. in «спрашивает про наличие», не «значение». «Проверка структуры» объектов «на вход». «Реестр» ключей — «умный» гость.
Перебор ключей: for…in
for (const key in obj) { … } — «все» ключи. В теле — obj[key]. Порядок «строк» «как записано», чисел — «по возрастанию». Для «слов», «настроек», «таргетов». «Обход» объекта — «повседневность» словарей.
for (const key in config) {
console.log(key + " = " + config[key]);
}
Списки ключей и значений: Object.keys/values
Object.keys(obj) → массив ключей. Object.values(obj) → массив значений. «Мост» объект → массив. Дальше — «методы массивов» применяются. Object.entries — пары «[ключ, значение]». «Стандарт» обхода «через» массивы.
Методы объекта
Свойство-функция: { greet() { … } }. Вызов: user.greet(). Методы «описывают» действия объекта. this «указывает» на объект «внутри» метода (в функции). «Объекты-актёры» — «главный» стиль модели данных.
Вложенные объекты и доступ
Свойство объекта — сам объект: user.address.city. «Цепочка» точек «спускается» глубже. «Сломанное» звено → ошибка (?. спасает). «Документы» структурированы «по уровням». «Глубина» — «карта» реальности.
Точка и скобки: когда что
Точка: «известный» ключ, статичный. Скобки: «из переменной» или ключ с пробелом. obj["первый ключ"] — «пробельный» ключ — только «в скобках». Ключ «вычисляем»: obj[prefix + "Name"]. «Идите» от «известности» «к динаме».
Ссылочная природа объекта
Переменная «хранит ссылку», не «копию». const a = user; const b = a — «оба смотрят на один» объект. Изменение через «b» «видно» через «a». Для «копии» — spread {...obj}. «Ссылка» — «ярлык на общую полку».
Копирование объекта: spread
{ ...user, age: 21 } — «копия с правкой». «Поверхностная» копия: вложенные «остаются» общими. Для «глубокой» — JSON трюк или structuredClone. «Неизменяемые» правки — «стиль» React. «Спред» — «фото» объекта «под копирку».
Деструктуризация объекта
const { name, age } = user — «вынуть» поля в переменные. Порядок «не важен», «имена» важны. Переименование: { name: n }. Значения по умолчанию: { city = "Мск" }. «Распаковка» параметров — «гибкость» функций.
const { name, age } = user;
Значения по умолчанию при чтении
Отсутствующее поле — undefined; «подмените»: user.city ?? "не указан". Деструктуризация с «дефолтами» — also. «Опчины» для «неполных» данных API. «Читайте» только «то, что есть». «Дефолты» — «спасательный» круг пустоты.
JSON: строковый формат данных
JSON — «текстовая» передача объектов: {"name":"Аня","age":20}. Ключи «в двойных кавычках». Никаких функций и «комментариев». Формат «общения» браузера с «сервером». JSON — «эсперанто» сетей.
Парсинг: JSON.parse
JSON.parse(text) — «строка → объект». Из «хранилища»/сети приходи́т строка. Разбор «ошибка» — при «повреждённом» тексте. «Оборачивайте» в try…catch. «Текст в жизнь» — «вход» данных в программу.
const data = JSON.parse(text);
Сериализация: JSON.stringify
JSON.stringify(obj) — «объект → строка». Для «сохранения» в localStorage, «отправки». Свойства-функции «теряются». Округление «формата» — третий аргумент — «отступы». «Строка» — «контейнер» для хранения.
Где живёт JSON: передача и хранение
Сервер «отвечает» JSON-строкой. localStorage хранит «строки». API «говорит» на JSON. «Сессионные» данные «переиздаются» туда-обратно. Понимание JSON — «мост» к «бэкенду» и «архитектуре». Формат «минимизирован»: без «лишних» пробелов.
Практика: каталог товаров (массив объектов)
Коллекция: массив объектов — { id, name, price, stock }. Каждый товар — «объект-карточка». Чтение: products[0].name. Обработки: filter/map над массивом объектов. «Каталог» — «главная» модель «магазина».
Практика: объект-конфигурация
config = { theme, lang, volume } — «настройки» одним объектом. Чтение/правка полей «по месту». Значения «по умолчанию» при чтении. «Переключатели» UI ← «объекты». «Конфиг» — «паспорт» приложения.
Практика: карточка товара функцией
renderCard(product) → «строка» описания: имя, цена, наличие. Функция «съедает» объект, «возвращает» текст. Вызовите «для трех» товаров. «Фабрика карточек» — «повтор без повтора».
Практика: фильтр каталога
Кнопка «фильтра» в данных: category === "tech". filter по «ветке». Три «настройка» «в динамике». «Панель каталога» обрастает «смыслом». «Слой фильтрации» — «ядро» любых «лент».
Практика: поиск по товарам
«Поисковая» строка → filter по имени: p.name.includes(query). «Регистр» — toLowerCase с обеих сторон. Пустая строка — «всё покажем». «Живой» поиск «экономь» «обе стороны». «Поиск» — «самый» желаемый «фильтр» у «людей».
Практика: сумма корзины через reduce
cart — массив { price, qty }. Сумма: reduce (sum, item) => sum + item.price * item.qty. Начальный 0. «Итог» за «один» проход. «Корзинная» математика — «вся» торговля «конька».
Практика: сортировка каталога
Сортировка по цене: [...catalog].sort((a, b) => a.price - b.price). По имени: a.name.localeCompare(b.name). «Стрелка» переключит «порядок». «Каталог» оживает «сортировкой». Вариант «выбирайте» — «куда глаза глядят».
Практика: словарь подсчёта (countBy)
reduce → «ключ: сколько раз». Частоты «букв», «городов», «цветов». Аккумулятор-объект + (acc[k] || 0) + 1. «Гистограмма» категорий — «аналитика» в «строке». «Подсчёт» — «любимец» ридуса.
Практика: вложенный доступ с защитой
profile?.address?.zip — «не падать» при «пустоте». Mixed с ?? "нет". «Спокойный» путь к «глубоким» данным API. Сравните «без ?.» — «ошибка» на «нет профиля». «Защитный» доступ — «гигиена» сетей.
Практика: массовое обновление
«Обновить» многие: map «возвращает» новые объекты с «правкой». const discounted = items.map(i => ({ ...i, price: i.price * 0.9 })). Оригинал «без изменений». «Акции» — «конвейер» стилей. «Иммутабельность» — «сила» функционального кода.
Контрольная работа по уроку 8
Задачи: «функция» суммы; «фильтр» активных; «объект» профиля; «JSON» туда-сюда; «reduce» итог. Пять «упражнений» — «весь» арсенал урока. Решайте «по памяти». «Контрольная» расставит «точки» над «і».
Чек-лист функций и объектов
return «на месте»; имена «глаголы»; «мутаций» «мало»; объекты «по ссылке»; JSON «корректен». Пять «пунктов» — «прогон» перед «сдачей». «Чистые» функции и «иммутабельные» данные — «стандарты» завтрашнего кода.
Итоги урока 8: организация кода
Функции «стóят» структуру, методы массивов «обжигают» данные, объекты «одевают» реальность, JSON «перевозит» в сети. Код стал «проектируемым». Урок 8 — «переход» от «команд» к «системам».
Функции первой необходимости
filter, map, reduce, find, includes, sort — «шесть» инструментов «данных». Отработайте «каждый» на «примерчиках». Навык «выбора» метода — «опыт». «Перебирая» «тривии» — «память» их «намотает».
Хорошие имена функций и переменных
«Глагол» для функции, «существительное» для данных. totalPrice, getUsers. Читается «как английское» предложение. Избегайте «x», «data», «obj». Имена — «подсказки памяти» «программисту» через год.
Домашнее задание: каталог на функциях
Массив «товаров»; функции: показать «все», отфильтровать «по цене», посчитать «итого». «Продайте» «продукт» через «функции». Результат — «мини-магазин» в консоли. Задание «сшивает» весь урок 8.
Дальше: урок 9 — DOM и события
JavaScript «трогает» страницу: находит элементы, меняет, слушает клики. DOM — «модель» документа для JS. События — «отклик» на действия человека. Урок 9 «воссоединит» разметку и логику. Страницы «оживут».
Ошибки в функциях: разбор
Забыли return — «вышло undefined». «Не так» имя — ReferenceError. «Порядок» аргументов — «перепутал» местами. «Неверный» тип — «удивил». Разбор типовых «промахов» — «амортизация» будущих «часов».
Ошибки с объектами: разбор
Несуществующее поле → undefined (не ошибка); «дерево» сломалось → TypeError. «Ссылочная» копия «не» копия. «Правка» «в образе» — «внезапно» «везде». Диагностика «через» ?. и «печат» «значений».
Стиль структур: заметки по мелочам
Порядок методов «в цепочке» — «читаем» слева направо. Не «громоздите» три «фильтра» в одну — «разбейте» с именами. «Форматирование» — Prettier «решит». Умеренность — «красота» кода «длинных» файлов.
Что дальше после курса
База «стоит»: разметка, стили, язык, манипуляция. Дальше — «проекты»: то-дo-лист, корзина, погода. Структуры «данных» и «алгоритмы». Порядок: «соберите» свои «маленькие» продукты. JavaScript-экосистема «откроется».
Заключение урока 8: код — текст для людей
Код читает «человек» чаще, чем «машина». Функции и объекты — «слова» и «фразы» этой «литературы». Пишите «для» людей, «оптимизируйте» «под» чтение. Урок 8 «вылепил» авторский «стиль».
Заголовок 8000: курс со связкой <aside> + <progress aria-label> (атрибут aria-invalid)
Задание 8000 на тему «курс». Урок пары: <aside> и <progress aria-label>, атрибут «aria-invalid» и «role=alert». Практика: журнал оценок. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: фокус на ближайший заголовок после валидации. Проверьте «в режиме вкладок доберитесь до цели». Доступность «курс» читается как имя, затем пояснение.
Заголовок 8001: отзыв со связкой <nav aria-label> + <aside> (атрибут aria-modal=true)
Задание 8001 на тему «отзыв». Урок пары: <nav aria-label> и <aside>, атрибут «aria-modal=true» и «aria-live=assertive». Практика: каталог уроков. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: видимая рамка фокуса. Убедитесь «проверьте сообщение об ошибке». Доступность «отзыв» читается как имя, затем пояснение.
Заголовок 8002: чат со связкой <main> + <details> (атрибут aria-hidden=true)
Задание 8002 на тему «чат». Урок пары: <main> и <details>, атрибут «aria-hidden=true» и «role=tab». Практика: вопрос-ответ модуля. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: крупный курсор в кастомном фокусе. Обеспечьте «в режиме вкладок доберитесь до цели». Доступность «чат» читается как имя, затем пояснение.
Заголовок 8003: комментарий со связкой <details> + <output> (атрибут aria-valuenow)
Задание 8003 на тему «комментарий». Урок пары: <details> и <output>, атрибут «aria-valuenow» и «aria-owns». Практика: трек наставника. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: крупный курсор в кастомном фокусе. Добавьте «в режиме вкладок доберитесь до цели». Доступность «комментарий» читается как имя, затем пояснение.
Заголовок 8004: урок со связкой <select> + <legend> (атрибут aria-pressed)
Задание 8004 на тему «урок». Урок пары: <select> и <legend>, атрибут «aria-pressed» и «aria-invalid». Практика: вопрос-ответ модуля. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: стрелки по сворачиваемому меню. Обеспечьте «проверьте сообщение об ошибке». Доступность «урок» читается как имя, затем пояснение.
Заголовок 8005: курс со связкой <footer> + <meter> (атрибут role=region)
Задание 8005 на тему «курс». Урок пары: <footer> и <meter>, атрибут «role=region» и «aria-valuetext». Практика: страница тарифов. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: проговаривание при return. Проверьте «на скринридере проверьте имя». Доступность «курс» читается как имя, затем пояснение.
Заголовок 8006: вход со связкой <output> + <ul aria-label> (атрибут aria-required=true)
Задание 8006 на тему «вход». Урок пары: <output> и <ul aria-label>, атрибут «aria-required=true» и «aria-valuenow». Практика: страница сертификатов. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: видимая рамка фокуса. Добавьте «тяните фокус после действия». Доступность «вход» читается как имя, затем пояснение.
Заголовок 8007: практика со связкой <aside> + <progress aria-label> (атрибут aria-expanded)
Задание 8007 на тему «практика». Урок пары: <aside> и <progress aria-label>, атрибут «aria-expanded» и «aria-selected». Практика: окно чата с куратором. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: видимая рамка фокуса. Обеспечьте «озвучьте переход без мыши». Доступность «практика» читается как имя, затем пояснение.
Заголовок 8008: чек-аут со связкой <a> + <select> (атрибут aria-controls)
Задание 8008 на тему «чек-аут». Урок пары: <a> и <select>, атрибут «aria-controls» и «aria-haspopup». Практика: анкета студента. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: порядок Tab по слоям. Обеспечьте «убедитесь в уровне заголовка». Доступность «чек-аут» читается как имя, затем пояснение.
Заголовок 8009: демо со связкой <progress aria-label> + <time> (атрибут aria-atomic=true)
Задание 8009 на тему «демо». Урок пары: <progress aria-label> и <time>, атрибут «aria-atomic=true» и «aria-modal=true». Практика: прогресс-бар ДЗ. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: крупный курсор в кастомном фокусе. Свяжите «убедитесь в уровне заголовка». Доступность «демо» читается как имя, затем пояснение.
Заголовок 8010: демо со связкой <main> + <details> (атрибут aria-hidden=true)
Задание 8010 на тему «демо». Урок пары: <main> и <details>, атрибут «aria-hidden=true» и «role=tab». Практика: лендинг курса. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: логичный порядок полей. Добавьте «убедитесь в уровне заголовка». Доступность «демо» читается как имя, затем пояснение.
Заголовок 8011: практика со связкой <a> + <select> (атрибут aria-atomic=true)
Задание 8011 на тему «практика». Урок пары: <a> и <select>, атрибут «aria-atomic=true» и «aria-modal=true». Практика: журнал оценок. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: фокус не застревает в модалке. Обеспечьте «на скринридере проверьте имя». Доступность «практика» читается как имя, затем пояснение.
Заголовок 8012: чат со связкой <progress aria-label> + <time> (атрибут aria-haspopup)
Задание 8012 на тему «чат». Урок пары: <progress aria-label> и <time>, атрибут «aria-haspopup» и «role=button». Практика: расписание группы. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: фокус не застревает в модалке. Свяжите «озвучьте переход без мыши». Доступность «чат» читается как имя, затем пояснение.
Заголовок 8013: сертификат со связкой <figure> + <input> (атрибут role=region)
Задание 8013 на тему «сертификат». Урок пары: <figure> и <input>, атрибут «role=region» и «aria-valuetext». Практика: анкета студента. Заголовки выстраиваются иерархией h1>h2>h3 без пропусков уровня.. Визуальное правило: вкладки и shift+Tab. Убедитесь «убедитесь в уровне заголовка». Доступность «сертификат» читается как имя, затем пояснение.
Заголовок 8014: форма со связкой <meter> + <dl> (атрибут aria-label)
Задание 8014 на тему «форма». Урок пары: <meter> и <dl>, атрибут «aria-label» и «aria-expanded». Практика: анкета студента. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: порядок Tab по слоям. Убедитесь «в режиме вкладок доберитесь до цели». Доступность «форма» читается как имя, затем пояснение.
Заголовок 8015: отзыв со связкой <output> + <ul aria-label> (атрибут aria-describedby)
Задание 8015 на тему «отзыв». Урок пары: <output> и <ul aria-label>, атрибут «aria-describedby» и «aria-controls». Практика: трек наставника. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: стрелки по сворачиваемому меню. Обеспечьте «на скринридере проверьте имя». Доступность «отзыв» читается как имя, затем пояснение.
Заголовок 8016: личный кабинет со связкой <progress aria-label> + <time> (атрибут aria-hidden=true)
Задание 8016 на тему «личный кабинет». Урок пары: <progress aria-label> и <time>, атрибут «aria-hidden=true» и «role=tab». Практика: журнал оценок. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: skip-ссылка. Обеспечьте «озвучьте переход без мыши». Доступность «личный кабинет» читается как имя, затем пояснение.
Заголовок 8017: каталог со связкой <th scope> + <header> (атрибут aria-controls)
Задание 8017 на тему «каталог». Урок пары: <th scope> и <header>, атрибут «aria-controls» и «aria-haspopup». Практика: страница тарифов. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: логичный порядок полей. Добавьте «в режиме вкладок доберитесь до цели». Доступность «каталог» читается как имя, затем пояснение.
Заголовок 8018: практика со связкой <textarea> + <table> (атрибут aria-modal=true)
Задание 8018 на тему «практика». Урок пары: <textarea> и <table>, атрибут «aria-modal=true» и «aria-live=assertive». Практика: лендинг курса. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: фокус не застревает в модалке. Проверьте «убедитесь в уровне заголовка». Доступность «практика» читается как имя, затем пояснение.
Заголовок 8019: презентация со связкой <figure> + <input> (атрибут aria-current)
Задание 8019 на тему «презентация». Урок пары: <figure> и <input>, атрибут «aria-current» и «aria-hidden=true». Практика: форма записи на интенсивы. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: порядок Tab по слоям. Добавьте «на скринридере проверьте имя». Доступность «презентация» читается как имя, затем пояснение.
Заголовок 8020: квиз со связкой <a> + <select> (атрибут aria-valuetext)
Задание 8020 на тему «квиз». Урок пары: <a> и <select>, атрибут «aria-valuetext» и «aria-flowto». Практика: страница оплаты. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: видимая рамка фокуса. Свяжите «на скринридере проверьте имя». Доступность «квиз» читается как имя, затем пояснение.
Заголовок 8021: практика со связкой <ul aria-label> + <button> (атрибут aria-owns)
Задание 8021 на тему «практика». Урок пары: <ul aria-label> и <button>, атрибут «aria-owns» и «aria-describedby». Практика: анкета студента. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: порядок Tab по слоям. Продумайте «убедитесь в уровне заголовка». Доступность «практика» читается как имя, затем пояснение.
Заголовок 8022: регистрация со связкой <meter> + <dl> (атрибут aria-haspopup)
Задание 8022 на тему «регистрация». Урок пары: <meter> и <dl>, атрибут «aria-haspopup» и «role=button». Практика: страница тарифов. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: skip-ссылка. Убедитесь «убедитесь в уровне заголовка». Доступность «регистрация» читается как имя, затем пояснение.
Заголовок 8023: расписание со связкой <ul aria-label> + <button> (атрибут aria-live=polite)
Задание 8023 на тему «расписание». Урок пары: <ul aria-label> и <button>, атрибут «aria-live=polite» и «aria-pressed». Практика: трек наставника. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: порядок Tab по слоям. Добавьте «проверьте сообщение об ошибке». Доступность «расписание» читается как имя, затем пояснение.
Заголовок 8024: домашнее задание со связкой <figure> + <input> (атрибут aria-valuenow)
Задание 8024 на тему «домашнее задание». Урок пары: <figure> и <input>, атрибут «aria-valuenow» и «aria-owns». Практика: окно чата с куратором. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: фокус виден в рамке 3px. Добавьте «на скринридере проверьте имя». Доступность «домашнее задание» читается как имя, затем пояснение.
Заголовок 8025: вебинар со связкой <figure> + <input> (атрибут aria-live=polite)
Задание 8025 на тему «вебинар». Урок пары: <figure> и <input>, атрибут «aria-live=polite» и «aria-pressed». Практика: окно чата с куратором. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: видимая рамка фокуса. Добавьте «в режиме вкладок доберитесь до цели». Доступность «вебинар» читается как имя, затем пояснение.
Заголовок 8026: программа со связкой <header> + <footer> (атрибут aria-relevant)
Задание 8026 на тему «программа». Урок пары: <header> и <footer>, атрибут «aria-relevant» и «aria-label». Практика: окно чата с куратором. Заголовки выстраиваются иерархией h1>h2>h3 без пропусков уровня.. Визуальное правило: видимая рамка фокуса. Добавьте «на скринридере проверьте имя». Доступность «программа» читается как имя, затем пояснение.
Заголовок 8027: сертификат со связкой <dl> + <figure> (атрибут aria-required=true)
Задание 8027 на тему «сертификат». Урок пары: <dl> и <figure>, атрибут «aria-required=true» и «aria-valuenow». Практика: расписание группы. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: фокус виден в рамке 3px. Свяжите «проверьте сообщение об ошибке». Доступность «сертификат» читается как имя, затем пояснение.
Заголовок 8028: отзыв со связкой <input> + <textarea> (атрибут aria-activedescendant)
Задание 8028 на тему «отзыв». Урок пары: <input> и <textarea>, атрибут «aria-activedescendant» и «aria-keyshortcuts». Практика: вопрос-ответ модуля. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: skip-ссылка. Убедитесь «озвучьте переход без мыши». Доступность «отзыв» читается как имя, затем пояснение.
Заголовок 8029: демо со связкой <legend> + <caption> (атрибут aria-label)
Задание 8029 на тему «демо». Урок пары: <legend> и <caption>, атрибут «aria-label» и «aria-expanded». Практика: страница тарифов. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: стрелки по сворачиваемому меню. Убедитесь «проверьте сообщение об ошибке». Доступность «демо» читается как имя, затем пояснение.
Заголовок 8030: уведомление со связкой <output> + <ul aria-label> (атрибут aria-current)
Задание 8030 на тему «уведомление». Урок пары: <output> и <ul aria-label>, атрибут «aria-current» и «aria-hidden=true». Практика: вопрос-ответ модуля. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: логичный порядок полей. Свяжите «убедитесь в уровне заголовка». Доступность «уведомление» читается как имя, затем пояснение.
Заголовок 8031: практика со связкой <footer> + <meter> (атрибут aria-valuenow)
Задание 8031 на тему «практика». Урок пары: <footer> и <meter>, атрибут «aria-valuenow» и «aria-owns». Практика: окно чата с куратором. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: порядок Tab по слоям. Убедитесь «в режиме вкладок доберитесь до цели». Доступность «практика» читается как имя, затем пояснение.
Заголовок 8032: личный кабинет со связкой <progress aria-label> + <time> (атрибут aria-pressed)
Задание 8032 на тему «личный кабинет». Урок пары: <progress aria-label> и <time>, атрибут «aria-pressed» и «aria-invalid». Практика: кабинет ученика. Заголовки выстраиваются иерархией h1>h2>h3 без пропусков уровня.. Визуальное правило: фокус не застревает в модалке. Обеспечьте «озвучьте переход без мыши». Доступность «личный кабинет» читается как имя, затем пояснение.
Заголовок 8033: прогресс со связкой <output> + <ul aria-label> (атрибут aria-keyshortcuts)
Задание 8033 на тему «прогресс». Урок пары: <output> и <ul aria-label>, атрибут «aria-keyshortcuts» и «aria-live=polite». Практика: карточка вебинара. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: фокус на ближайший заголовок после валидации. Проверьте «проверьте сообщение об ошибке». Доступность «прогресс» читается как имя, затем пояснение.
Заголовок 8034: тариф со связкой <label> + <fieldset> (атрибут aria-haspopup)
Задание 8034 на тему «тариф». Урок пары: <label> и <fieldset>, атрибут «aria-haspopup» и «role=button». Практика: вопрос-ответ модуля. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: проговаривание при return. Проверьте «тяните фокус после действия». Доступность «тариф» читается как имя, затем пояснение.
Заголовок 8035: форма со связкой <input> + <textarea> (атрибут role=button)
Задание 8035 на тему «форма». Урок пары: <input> и <textarea>, атрибут «role=button» и «aria-activedescendant». Практика: трек наставника. Заголовки выстраиваются иерархией h1>h2>h3 без пропусков уровня.. Визуальное правило: крупный курсор в кастомном фокусе. Продумайте «озвучьте переход без мыши». Доступность «форма» читается как имя, затем пояснение.
Заголовок 8036: регистрация со связкой <aside> + <progress aria-label> (атрибут aria-haspopup)
Задание 8036 на тему «регистрация». Урок пары: <aside> и <progress aria-label>, атрибут «aria-haspopup» и «role=button». Практика: окно чата с куратором. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: skip-ссылка. Свяжите «убедитесь в уровне заголовка». Доступность «регистрация» читается как имя, затем пояснение.
Заголовок 8037: оплата со связкой <table> + <nav aria-label> (атрибут aria-relevant)
Задание 8037 на тему «оплата». Урок пары: <table> и <nav aria-label>, атрибут «aria-relevant» и «aria-label». Практика: страница тарифов. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: логичный порядок полей. Добавьте «на скринридере проверьте имя». Доступность «оплата» читается как имя, затем пояснение.
Заголовок 8038: урок со связкой <dl> + <figure> (атрибут aria-current)
Задание 8038 на тему «урок». Урок пары: <dl> и <figure>, атрибут «aria-current» и «aria-hidden=true». Практика: журнал оценок. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: фокус на ближайший заголовок после валидации. Свяжите «убедитесь в уровне заголовка». Доступность «урок» читается как имя, затем пояснение.
Заголовок 8039: корзина со связкой <output> + <ul aria-label> (атрибут aria-labelledby)
Задание 8039 на тему «корзина». Урок пары: <output> и <ul aria-label>, атрибут «aria-labelledby» и «aria-current». Практика: журнал оценок. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: фокус виден в рамке 3px. Свяжите «на скринридере проверьте имя». Доступность «корзина» читается как имя, затем пояснение.
Заголовок 8040: регистрация со связкой <time> + <ol> (атрибут aria-modal=true)
Задание 8040 на тему «регистрация». Урок пары: <time> и <ol>, атрибут «aria-modal=true» и «aria-live=assertive». Практика: анкета студента. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: фокус не застревает в модалке. Продумайте «проверьте сообщение об ошибке». Доступность «регистрация» читается как имя, затем пояснение.
Заголовок 8041: личные данные со связкой <button> + <label> (атрибут aria-current)
Задание 8041 на тему «личные данные». Урок пары: <button> и <label>, атрибут «aria-current» и «aria-hidden=true». Практика: журнал оценок. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: начало: фокус на первую ошибку. Продумайте «в режиме вкладок доберитесь до цели». Доступность «личные данные» читается как имя, затем пояснение.
Заголовок 8042: вход со связкой <dl> + <figure> (атрибут aria-valuenow)
Задание 8042 на тему «вход». Урок пары: <dl> и <figure>, атрибут «aria-valuenow» и «aria-owns». Практика: карточка вебинара. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: проговаривание при return. Свяжите «на скринридере проверьте имя». Доступность «вход» читается как имя, затем пояснение.
Заголовок 8043: заказ со связкой <nav aria-label> + <aside> (атрибут aria-describedby)
Задание 8043 на тему «заказ». Урок пары: <nav aria-label> и <aside>, атрибут «aria-describedby» и «aria-controls». Практика: прогресс-бар ДЗ. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: стрелки по сворачиваемому меню. Свяжите «в режиме вкладок доберитесь до цели». Доступность «заказ» читается как имя, затем пояснение.
Заголовок 8044: вход со связкой <nav aria-label> + <aside> (атрибут aria-flowto)
Задание 8044 на тему «вход». Урок пары: <nav aria-label> и <aside>, атрибут «aria-flowto» и «aria-labelledby». Практика: каталог уроков. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: skip-ссылка. Свяжите «убедитесь в уровне заголовка». Доступность «вход» читается как имя, затем пояснение.
Заголовок 8045: вебинар со связкой <output> + <ul aria-label> (атрибут aria-hidden=true)
Задание 8045 на тему «вебинар». Урок пары: <output> и <ul aria-label>, атрибут «aria-hidden=true» и «role=tab». Практика: каталог уроков. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: крупный курсор в кастомном фокусе. Убедитесь «озвучьте переход без мыши». Доступность «вебинар» читается как имя, затем пояснение.
Заголовок 8046: лекция со связкой <ul aria-label> + <button> (атрибут aria-expanded)
Задание 8046 на тему «лекция». Урок пары: <ul aria-label> и <button>, атрибут «aria-expanded» и «aria-selected». Практика: карточка вебинара. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: фокус на ближайший заголовок после валидации. Продумайте «проверьте сообщение об ошибке». Доступность «лекция» читается как имя, затем пояснение.
Заголовок 8047: урок со связкой <dl> + <figure> (атрибут aria-hidden=true)
Задание 8047 на тему «урок». Урок пары: <dl> и <figure>, атрибут «aria-hidden=true» и «role=tab». Практика: трек наставника. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: skip-ссылка. Продумайте «озвучьте переход без мыши». Доступность «урок» читается как имя, затем пояснение.
Заголовок 8048: вход со связкой <select> + <legend> (атрибут aria-live=assertive)
Задание 8048 на тему «вход». Урок пары: <select> и <legend>, атрибут «aria-live=assertive» и «aria-checked». Практика: страница сертификатов. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: порядок Tab по слоям. Проверьте «убедитесь в уровне заголовка». Доступность «вход» читается как имя, затем пояснение.
Заголовок 8049: расписание со связкой <time> + <ol> (атрибут role=alert)
Задание 8049 на тему «расписание». Урок пары: <time> и <ol>, атрибут «role=alert» и «aria-relevant». Практика: кабинет ученика. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: порядок Tab по слоям. Свяжите «тяните фокус после действия». Доступность «расписание» читается как имя, затем пояснение.
Заголовок 8050: презентация со связкой <label> + <fieldset> (атрибут aria-modal=true)
Задание 8050 на тему «презентация». Урок пары: <label> и <fieldset>, атрибут «aria-modal=true» и «aria-live=assertive». Практика: журнал оценок. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: фокус на ближайший заголовок после валидации. Добавьте «убедитесь в уровне заголовка». Доступность «презентация» читается как имя, затем пояснение.
Заголовок 8051: расписание со связкой <ol> + <a> (атрибут aria-hidden=true)
Задание 8051 на тему «расписание». Урок пары: <ol> и <a>, атрибут «aria-hidden=true» и «role=tab». Практика: каталог уроков. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: фокус на ближайший заголовок после валидации. Проверьте «убедитесь в уровне заголовка». Доступность «расписание» читается как имя, затем пояснение.
Заголовок 8052: вход со связкой <label> + <fieldset> (атрибут aria-current)
Задание 8052 на тему «вход». Урок пары: <label> и <fieldset>, атрибут «aria-current» и «aria-hidden=true». Практика: лендинг курса. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: логичный порядок полей. Добавьте «озвучьте переход без мыши». Доступность «вход» читается как имя, затем пояснение.
Заголовок 8053: вебинар со связкой <aside> + <progress aria-label> (атрибут aria-flowto)
Задание 8053 на тему «вебинар». Урок пары: <aside> и <progress aria-label>, атрибут «aria-flowto» и «aria-labelledby». Практика: анкета студента. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: крупный курсор в кастомном фокусе. Убедитесь «убедитесь в уровне заголовка». Доступность «вебинар» читается как имя, затем пояснение.
Заголовок 8054: рассылка со связкой <nav aria-label> + <aside> (атрибут aria-live=polite)
Задание 8054 на тему «рассылка». Урок пары: <nav aria-label> и <aside>, атрибут «aria-live=polite» и «aria-pressed». Практика: кабинет ученика. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: проговаривание при return. Добавьте «убедитесь в уровне заголовка». Доступность «рассылка» читается как имя, затем пояснение.
Заголовок 8055: курс со связкой <legend> + <caption> (атрибут role=tab)
Задание 8055 на тему «курс». Урок пары: <legend> и <caption>, атрибут «role=tab» и «aria-atomic=true». Практика: прогресс-бар ДЗ. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: крупный курсор в кастомном фокусе. Свяжите «тяните фокус после действия». Доступность «курс» читается как имя, затем пояснение.
Заголовок 8056: модуль со связкой <main> + <details> (атрибут aria-required=true)
Задание 8056 на тему «модуль». Урок пары: <main> и <details>, атрибут «aria-required=true» и «aria-valuenow». Практика: расписание группы. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: фокус на ближайший заголовок после валидации. Убедитесь «в режиме вкладок доберитесь до цели». Доступность «модуль» читается как имя, затем пояснение.
Заголовок 8057: квиз со связкой <aside> + <progress aria-label> (атрибут aria-labelledby)
Задание 8057 на тему «квиз». Урок пары: <aside> и <progress aria-label>, атрибут «aria-labelledby» и «aria-current». Практика: вопрос-ответ модуля. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: вкладки и shift+Tab. Проверьте «в режиме вкладок доберитесь до цели». Доступность «квиз» читается как имя, затем пояснение.
Заголовок 8058: личный кабинет со связкой <th scope> + <header> (атрибут aria-flowto)
Задание 8058 на тему «личный кабинет». Урок пары: <th scope> и <header>, атрибут «aria-flowto» и «aria-labelledby». Практика: вопрос-ответ модуля. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: фокус не застревает в модалке. Обеспечьте «убедитесь в уровне заголовка». Доступность «личный кабинет» читается как имя, затем пояснение.
Заголовок 8059: квиз со связкой <button> + <label> (атрибут aria-flowto)
Задание 8059 на тему «квиз». Урок пары: <button> и <label>, атрибут «aria-flowto» и «aria-labelledby». Практика: карточка вебинара. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: порядок Tab по слоям. Убедитесь «озвучьте переход без мыши». Доступность «квиз» читается как имя, затем пояснение.
Заголовок 8060: сертификат со связкой <ol> + <a> (атрибут aria-valuenow)
Задание 8060 на тему «сертификат». Урок пары: <ol> и <a>, атрибут «aria-valuenow» и «aria-owns». Практика: лендинг курса. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: skip-ссылка. Свяжите «убедитесь в уровне заголовка». Доступность «сертификат» читается как имя, затем пояснение.
Заголовок 8061: личные данные со связкой <nav aria-label> + <aside> (атрибут aria-keyshortcuts)
Задание 8061 на тему «личные данные». Урок пары: <nav aria-label> и <aside>, атрибут «aria-keyshortcuts» и «aria-live=polite». Практика: прогресс-бар ДЗ. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: логичный порядок полей. Продумайте «проверьте сообщение об ошибке». Доступность «личные данные» читается как имя, затем пояснение.
Заголовок 8062: домашнее задание со связкой <ul aria-label> + <button> (атрибут aria-controls)
Задание 8062 на тему «домашнее задание». Урок пары: <ul aria-label> и <button>, атрибут «aria-controls» и «aria-haspopup». Практика: расписание группы. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: порядок Tab по слоям. Проверьте «убедитесь в уровне заголовка». Доступность «домашнее задание» читается как имя, затем пояснение.
Заголовок 8063: курс со связкой <figure> + <input> (атрибут aria-keyshortcuts)
Задание 8063 на тему «курс». Урок пары: <figure> и <input>, атрибут «aria-keyshortcuts» и «aria-live=polite». Практика: окно чата с куратором. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: начало: фокус на первую ошибку. Продумайте «тяните фокус после действия». Доступность «курс» читается как имя, затем пояснение.
Заголовок 8064: гайд со связкой <caption> + <main> (атрибут aria-haspopup)
Задание 8064 на тему «гайд». Урок пары: <caption> и <main>, атрибут «aria-haspopup» и «role=button». Практика: карточка вебинара. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: фокус виден в рамке 3px. Продумайте «тяните фокус после действия». Доступность «гайд» читается как имя, затем пояснение.
Заголовок 8065: оплата со связкой <label> + <fieldset> (атрибут aria-hidden=true)
Задание 8065 на тему «оплата». Урок пары: <label> и <fieldset>, атрибут «aria-hidden=true» и «role=tab». Практика: трек наставника. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: фокус не застревает в модалке. Свяжите «убедитесь в уровне заголовка». Доступность «оплата» читается как имя, затем пояснение.
Заголовок 8066: форма со связкой <dl> + <figure> (атрибут aria-expanded)
Задание 8066 на тему «форма». Урок пары: <dl> и <figure>, атрибут «aria-expanded» и «aria-selected». Практика: форма записи на интенсивы. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: проговаривание при return. Добавьте «проверьте сообщение об ошибке». Доступность «форма» читается как имя, затем пояснение.
Заголовок 8067: запись со связкой <nav aria-label> + <aside> (атрибут aria-hidden=true)
Задание 8067 на тему «запись». Урок пары: <nav aria-label> и <aside>, атрибут «aria-hidden=true» и «role=tab». Практика: форма записи на интенсивы. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: вкладки и shift+Tab. Обеспечьте «озвучьте переход без мыши». Доступность «запись» читается как имя, затем пояснение.
Заголовок 8068: трек со связкой <legend> + <caption> (атрибут aria-current)
Задание 8068 на тему «трек». Урок пары: <legend> и <caption>, атрибут «aria-current» и «aria-hidden=true». Практика: лендинг курса. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: видимая рамка фокуса. Добавьте «на скринридере проверьте имя». Доступность «трек» читается как имя, затем пояснение.
Заголовок 8069: баллы со связкой <input> + <textarea> (атрибут aria-valuetext)
Задание 8069 на тему «баллы». Урок пары: <input> и <textarea>, атрибут «aria-valuetext» и «aria-flowto». Практика: форма записи на интенсивы. Заголовки выстраиваются иерархией h1>h2>h3 без пропусков уровня.. Визуальное правило: проговаривание при return. Убедитесь «тяните фокус после действия». Доступность «баллы» читается как имя, затем пояснение.
Заголовок 8070: рассылка со связкой <main> + <details> (атрибут aria-live=assertive)
Задание 8070 на тему «рассылка». Урок пары: <main> и <details>, атрибут «aria-live=assertive» и «aria-checked». Практика: страница сертификатов. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: видимая рамка фокуса. Добавьте «озвучьте переход без мыши». Доступность «рассылка» читается как имя, затем пояснение.
Заголовок 8071: гайд со связкой <dl> + <figure> (атрибут aria-activedescendant)
Задание 8071 на тему «гайд». Урок пары: <dl> и <figure>, атрибут «aria-activedescendant» и «aria-keyshortcuts». Практика: каталог уроков. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: крупный курсор в кастомном фокусе. Обеспечьте «убедитесь в уровне заголовка». Доступность «гайд» читается как имя, затем пояснение.
Заголовок 8072: лекция со связкой <time> + <ol> (атрибут aria-live=assertive)
Задание 8072 на тему «лекция». Урок пары: <time> и <ol>, атрибут «aria-live=assertive» и «aria-checked». Практика: каталог уроков. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: проговаривание при return. Продумайте «на скринридере проверьте имя». Доступность «лекция» читается как имя, затем пояснение.
Заголовок 8073: гайд со связкой <legend> + <caption> (атрибут aria-live=assertive)
Задание 8073 на тему «гайд». Урок пары: <legend> и <caption>, атрибут «aria-live=assertive» и «aria-checked». Практика: форма записи на интенсивы. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: начало: фокус на первую ошибку. Проверьте «проверьте сообщение об ошибке». Доступность «гайд» читается как имя, затем пояснение.
Заголовок 8074: комментарий со связкой <textarea> + <table> (атрибут aria-current)
Задание 8074 на тему «комментарий». Урок пары: <textarea> и <table>, атрибут «aria-current» и «aria-hidden=true». Практика: карточка вебинара. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: порядок Tab по слоям. Убедитесь «в режиме вкладок доберитесь до цели». Доступность «комментарий» читается как имя, затем пояснение.
Заголовок 8075: трек со связкой <aside> + <progress aria-label> (атрибут aria-valuenow)
Задание 8075 на тему «трек». Урок пары: <aside> и <progress aria-label>, атрибут «aria-valuenow» и «aria-owns». Практика: расписание группы. Порядок Tab соответствует визуальному чтению; видимая рамка обязательна.. Визуальное правило: стрелки по сворачиваемому меню. Добавьте «в режиме вкладок доберитесь до цели». Доступность «трек» читается как имя, затем пояснение.
Заголовок 8076: комментарий со связкой <button> + <label> (атрибут aria-keyshortcuts)
Задание 8076 на тему «комментарий». Урок пары: <button> и <label>, атрибут «aria-keyshortcuts» и «aria-live=polite». Практика: страница тарифов. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: видимая рамка фокуса. Убедитесь «озвучьте переход без мыши». Доступность «комментарий» читается как имя, затем пояснение.
Заголовок 8077: рассылка со связкой <label> + <fieldset> (атрибут aria-activedescendant)
Задание 8077 на тему «рассылка». Урок пары: <label> и <fieldset>, атрибут «aria-activedescendant» и «aria-keyshortcuts». Практика: страница оплаты. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: фокус не застревает в модалке. Добавьте «озвучьте переход без мыши». Доступность «рассылка» читается как имя, затем пояснение.
Заголовок 8078: баллы со связкой <th scope> + <header> (атрибут role=alert)
Задание 8078 на тему «баллы». Урок пары: <th scope> и <header>, атрибут «role=alert» и «aria-relevant». Практика: журнал оценок. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: фокус на ближайший заголовок после валидации. Продумайте «на скринридере проверьте имя». Доступность «баллы» читается как имя, затем пояснение.
Заголовок 8079: тест со связкой <nav aria-label> + <aside> (атрибут aria-selected)
Задание 8079 на тему «тест». Урок пары: <nav aria-label> и <aside>, атрибут «aria-selected» и «role=region». Практика: трек наставника. Живые регионы aria-live озвучивают изменения без фокуса.. Визуальное правило: видимая рамка фокуса. Обеспечьте «проверьте сообщение об ошибке». Доступность «тест» читается как имя, затем пояснение.
Заголовок 8080: отзыв со связкой <nav aria-label> + <aside> (атрибут aria-live=assertive)
Задание 8080 на тему «отзыв». Урок пары: <nav aria-label> и <aside>, атрибут «aria-live=assertive» и «aria-checked». Практика: вопрос-ответ модуля. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: порядок Tab по слоям. Проверьте «убедитесь в уровне заголовка». Доступность «отзыв» читается как имя, затем пояснение.
Заголовок 8081: презентация со связкой <caption> + <main> (атрибут aria-label)
Задание 8081 на тему «презентация». Урок пары: <caption> и <main>, атрибут «aria-label» и «aria-expanded». Практика: лендинг курса. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: фокус не застревает в модалке. Обеспечьте «на скринридере проверьте имя». Доступность «презентация» читается как имя, затем пояснение.
Заголовок 8082: домашнее задание со связкой <figure> + <input> (атрибут role=alert)
Задание 8082 на тему «домашнее задание». Урок пары: <figure> и <input>, атрибут «role=alert» и «aria-relevant». Практика: страница оплаты. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: логичный порядок полей. Свяжите «проверьте сообщение об ошибке». Доступность «домашнее задание» читается как имя, затем пояснение.
Заголовок 8083: отзыв со связкой <a> + <select> (атрибут aria-checked)
Задание 8083 на тему «отзыв». Урок пары: <a> и <select>, атрибут «aria-checked» и «aria-required=true». Практика: форма записи на интенсивы. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: skip-ссылка. Обеспечьте «убедитесь в уровне заголовка». Доступность «отзыв» читается как имя, затем пояснение.
Заголовок 8084: прогресс со связкой <textarea> + <table> (атрибут aria-controls)
Задание 8084 на тему «прогресс». Урок пары: <textarea> и <table>, атрибут «aria-controls» и «aria-haspopup». Практика: форма записи на интенсивы. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: видимая рамка фокуса. Убедитесь «убедитесь в уровне заголовка». Доступность «прогресс» читается как имя, затем пояснение.
Заголовок 8085: курс со связкой <button> + <label> (атрибут aria-keyshortcuts)
Задание 8085 на тему «курс». Урок пары: <button> и <label>, атрибут «aria-keyshortcuts» и «aria-live=polite». Практика: журнал оценок. Скринридер прочтёт имя без контекста страницы; ориентиры навигации помогают.. Визуальное правило: фокус на ближайший заголовок после валидации. Продумайте «на скринридере проверьте имя». Доступность «курс» читается как имя, затем пояснение.
Заголовок 8086: комментарий со связкой <footer> + <meter> (атрибут aria-owns)
Задание 8086 на тему «комментарий». Урок пары: <footer> и <meter>, атрибут «aria-owns» и «aria-describedby». Практика: расписание группы. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: крупный курсор в кастомном фокусе. Убедитесь «убедитесь в уровне заголовка». Доступность «комментарий» читается как имя, затем пояснение.
Заголовок 8087: форма со связкой <button> + <label> (атрибут aria-atomic=true)
Задание 8087 на тему «форма». Урок пары: <button> и <label>, атрибут «aria-atomic=true» и «aria-modal=true». Практика: трек наставника. Состояние раскрытия передают aria-expanded и aria-контролы честно.. Визуальное правило: вкладки и shift+Tab. Обеспечьте «озвучьте переход без мыши». Доступность «форма» читается как имя, затем пояснение.
Заголовок 8088: подписка со связкой <time> + <ol> (атрибут role=tab)
Задание 8088 на тему «подписка». Урок пары: <time> и <ol>, атрибут «role=tab» и «aria-atomic=true». Практика: журнал оценок. Имя у элемента — всегда одно предложение смысла; label и ссылка имени связаны.. Визуальное правило: фокус на ближайший заголовок после валидации. Обеспечьте «в режиме вкладок доберитесь до цели». Доступность «подписка» читается как имя, затем пояснение.
Заголовок 8089: чек-аут со связкой <th scope> + <header> (атрибут aria-selected)
Задание 8089 на тему «чек-аут». Урок пары: <th scope> и <header>, атрибут «aria-selected» и «role=region». Практика: вопрос-ответ модуля. Заголовки выстраиваются иерархией h1>h2>h3 без пропусков уровня.. Визуальное правило: начало: фокус на первую ошибку. Убедитесь «тяните фокус после действия». Доступность «чек-аут» читается как имя, затем пояснение.
Заголовок 8090: домашнее задание со связкой <label> + <fieldset> (атрибут aria-live=polite)
Задание 8090 на тему «домашнее задание». Урок пары: <label> и <fieldset>, атрибут «aria-live=polite» и «aria-pressed». Практика: страница оплаты. Декоративные иконки прячут aria-hidden; смысл остаётся в тексте.. Визуальное правило: вкладки и shift+Tab. Убедитесь «проверьте сообщение об ошибке». Доступность «домашнее задание» читается как имя, затем пояснение.
Заголовок 8091: чек-аут со связкой <table> + <nav aria-label> (атрибут aria-labelledby)
Задание 8091 на тему «чек-аут». Урок пары: <table> и <nav aria-label>, атрибут «aria-labelledby» и «aria-current». Практика: трек наставника. Форматив группируют fieldset+legend; у полей видимое label.. Визуальное правило: порядок Tab по слоям. Убедитесь «в режиме вкладок доберитесь до цели». Доступность «чек-аут» читается как имя, затем пояснение.