Перейти к содержанию

Лабораторная работа №3 - Объектная модель документа. Использование DOM для доступа к элементам веб-страницы.

1. Теория

1.0. Цель работы

Сформировать у обучающегося устойчивые навыки работы с объектной моделью документа (DOM): получать элементы web-страницы, читать и изменять их свойства, создавать и удалять узлы, обрабатывать пользовательские события и реализовывать динамическое обновление интерфейса на основе данных предметной области. Дополнительно закрепить работу с функциями, массивами, объектами, методами обработки данных и базовыми принципами модульности (разделение кода минимум на 2 файла JavaScript).


1.1. Место лабораторной работы №3 в проекте семестра

Лабораторная работа №1 создала основу:

  • репозиторий GitHub;
  • структура проекта (index.html, style.css, script.js, README.md, passport.md);
  • простая верстка под предметную область;
  • проверка подключения JavaScript;
  • формирование контекста проекта через паспорт предметной области.

Лабораторная работа №2 развила проект:

  • добавила алгоритмическое ядро;
  • ввела набор данных предметной области;
  • закрепила работу с const/let, типами данных, операторами, условиями и циклами;
  • добавила первичную демонстрацию результатов (консоль + блок вывода на странице);
  • подготовила основу для перехода к DOM и пользовательскому интерфейсу.

Лабораторная работа №3 делает следующий шаг:

  • связывает алгоритмическое ядро с интерфейсом через DOM;
  • вводит принцип: данные → обработка → отображение;
  • переносит вывод результата из “текста в <pre>” в динамическое построение интерфейса;
  • закрепляет архитектурную дисциплину: логика оформляется функциями и выносится в отдельные файлы (модули).

То есть теперь проект становится похожим на реальное web-приложение:

  • есть данные предметной области;
  • есть функции обработки данных;
  • есть интерфейс, который обновляется динамически;
  • есть события пользователя (клики/ввод), которые управляют состоянием системы;
  • логика разнесена по файлам (модули).

1.2. DOM: объектная модель документа и роль document

DOM (Document Object Model) — это представление HTML-документа в виде дерева объектов, которое создаёт браузер при загрузке страницы. Каждый HTML-элемент превращается в узел дерева (node), а JavaScript получает возможность:

  • находить нужные элементы;
  • читать их содержимое и свойства;
  • изменять текст, атрибуты и классы;
  • создавать новые элементы и вставлять их на страницу;
  • удалять элементы;
  • реагировать на события пользователя.

Ключевой объект в браузерном JavaScript — document. Он представляет текущую HTML-страницу и является “точкой входа” к DOM.

Пример HTML:

<h1 id="title">Моя система</h1>

Пример JavaScript-доступа к этому элементу:

const titleEl = document.getElementById("title");
console.log(titleEl.textContent); // "Моя система"

Главная идея DOM: JavaScript не “рисует” страницу заново, а изменяет дерево объектов, после чего браузер отображает изменения в интерфейсе.


1.3. Получение элементов DOM: getElementById, querySelector, querySelectorAll

Для работы с интерфейсом сначала нужно получить ссылки на DOM-элементы.

Основные методы:

const byId = document.getElementById("list");         // один элемент по id
const first = document.querySelector(".card");        // первый элемент по CSS-селектору
const all = document.querySelectorAll(".card");       // коллекция (NodeList) по CSS-селектору

Важно понимать различия:

  • getElementById возвращает один элемент (или null, если не найден).
  • querySelector возвращает первый подходящий элемент (или null).
  • querySelectorAll возвращает коллекцию (NodeList), по которой нужно проходить циклом.

Пример перебора коллекции:

const cards = document.querySelectorAll(".card");
for (const card of cards) {
  console.log(card);
}

Практическое правило лабораторной работы: ссылки на DOM-элементы обычно объявляются через const, потому что сама ссылка не должна переназначаться.


1.4. Изменение содержимого, атрибутов и классов DOM-элементов

После получения элемента DOM можно изменять его свойства.

Изменение текста (рекомендуемый безопасный способ):

messageEl.textContent = "Данные обновлены";

textContent вставляет именно текст, не интерпретируя HTML-теги.

Вставка HTML-разметки (использовать осторожно):

containerEl.innerHTML = "<b>Внимание</b>";

В учебной работе предпочтительнее тренировать работу с DOM через createElement, потому что это формирует инженерное понимание интерфейса как структуры узлов, а не как строки.

Управление CSS-классами:

messageEl.classList.add("success");
messageEl.classList.remove("error");
messageEl.classList.toggle("hidden");

1.5. Создание DOM-узлов: createElement, appendChild, append

DOM-рендеринг — это ситуация, когда список на странице формируется из массива данных, а каждый элемент массива превращается в визуальную карточку/строку в интерфейсе.

Пример: создаём карточку записи.

const card = document.createElement("div");
card.className = "card";

const title = document.createElement("h3");
title.textContent = "Заявка #1";

card.appendChild(title);
listEl.appendChild(card);

Что важно понять студенту:

  • createElement создаёт узел, но он “не виден”, пока вы не вставили его в DOM через appendChild/append.
  • интерфейс строится не строками, а объектами-элементами (узлами DOM).
  • каждый DOM-узел может содержать дочерние узлы, формируя иерархию.

1.6. Очистка и перерисовка списка: функция renderList

Классическая схема интерфейса (применяется почти во всех web-приложениях):

  1. очистить контейнер;
  2. пройти по данным;
  3. создать элементы;
  4. вставить элементы в DOM.

Пример базовой функции рендера:

function renderList(items) {
  listEl.textContent = ""; // очистка контейнера
  for (const item of items) {
    const row = document.createElement("div");
    row.textContent = `${item.id}: ${item.title} (${item.status})`;
    listEl.appendChild(row);
  }
}

Это основа любой отрисовки списка (таблица заявок, заказы, задачи, записи журнала и т.п.). Функция renderList должна использоваться как единая точка вывода интерфейса: это делает код аккуратным и управляемым.


1.7. Удаление узлов: remove() и корректная логика удаления

Удаление может быть двух типов:

  • удаление конкретного DOM-элемента;
  • обновление DOM через перерисовку списка после удаления записи из данных.

Пример удаления узла:

row.remove();

Но в учебном проекте правильнее придерживаться принципа:

  • сначала удалить данные из массива;
  • затем вызвать renderList(...), чтобы интерфейс отобразил текущее состояние данных.

Так студент формирует правильную связь:

данные — источник истины, DOM — представление данных.


1.8. События и обработчики: как интерфейс управляет логикой

Взаимодействие пользователя с интерфейсом происходит через события:

  • click — нажатие;
  • input — ввод в поле;
  • change — изменение значения;
  • submit — отправка формы (в этой ЛР формы используются минимально и без углубления).

Пример:

btnAll.addEventListener("click", () => {
  renderList(items);
});

Ключевой принцип: пользователь не “выполняет код”, он создаёт событие, а программа реагирует обработчиком.


1.9. Делегирование событий (расширение DOM-раздела, обзорно)

Если карточек много, можно не ставить обработчик на каждую кнопку внутри карточек, а поставить один обработчик на контейнер списка и определять, по чему именно кликнули.

Пример:

listEl.addEventListener("click", (e) => {
  if (e.target.dataset.action === "remove") {
    const id = Number(e.target.dataset.id);
    removeById(items, id);
    renderList(items);
  }
});

Для ЛР-3 это не обязательно, но как “профессиональный акцент” полезно понимать идею: один обработчик на контейнер вместо множества обработчиков на однотипных элементах.


1.10. Данные предметной области: что это и как они моделируются

Предметная область — это контекст системы (например: Service Desk, заказы, студенты, склад, заявки, расписание и т.д.).

Данные предметной области — это конкретные записи этой области:

  • заявка;
  • заказ;
  • задача;
  • запись журнала;
  • инцидент;
  • заявка на справку;
  • и т.п.

В коде такие записи моделируются как объекты, потому что объект хранит связанные поля в одной структуре.

Пример одной записи:

const item = { id: 1, title: "Не работает принтер", value: 1200, status: "new", createdAt: "2026-02-10" };

1.11. Почему данные хранятся в виде массива объектов

Потому что:

  • одна запись = один объект (с полями);
  • много записей = массив объектов.

Пример: “заявки” (адаптировать под любую предметную область):

const items = [
  { id: 1, title: "Не работает принтер", value: 1200, status: "new",  createdAt: "2026-02-10" },
  { id: 2, title: "Настроить почту",     value: 800,  status: "done", createdAt: "2026-02-11" },
  { id: 3, title: "Сбой сети",           value: 1500, status: "new",  createdAt: "2026-02-12" }
];

Почему это правильная форма:

  • массив даёт порядок и перебор (for, for..of, filter, map);
  • объект даёт структуру и смысл полей (item.status, item.value).

1.12. Функции обработки данных

Если писать логику прямо внутри обработчиков кнопок, получится высокая связанность и “хаос”:

  • сложно читать;
  • сложно отлаживать;
  • сложно расширять.

Правильный подход:

  • обработчик события (UI) вызывает функцию обработки данных;
  • функция возвращает результат;
  • UI отображает результат через DOM.

Таким образом формируется инженерный стиль:

UI-слой (DOM + события) отделён от логики обработки данных.


1.13. Методы обработки данных: filter, find, sort, reduce

В ЛР-3 допускается и рекомендуется применять методы массивов, потому что они дают компактный и ясный код обработки данных.


1.13.1. Фильтрация (filter)

Отобрать только NEW:

function filterByStatus(items, status) {
  return items.filter(item => item.status === status);
}

1.13.2. Поиск (find)

Найти запись по id:

function findById(items, id) {
  return items.find(item => item.id === id) || null;
}

1.13.3. Сортировка (sort)

Сортировать по value по убыванию:

function sortByValueDesc(items) {
  const copy = items.slice();
  copy.sort((a, b) => b.value - a.value);
  return copy;
}

Важно:

  • sort меняет массив “на месте”, поэтому создаём копию через slice().

1.13.4. Агрегация (reduce)

Посчитать статистику:

function buildStats(items) {
  return items.reduce((acc, item) => {
    acc.totalCount += 1;
    acc.sumValue += item.value;
    if (item.value > acc.maxValue) acc.maxValue = item.value;
    if (item.status === "new") acc.newCount += 1;
    return acc;
  }, { totalCount: 0, sumValue: 0, maxValue: 0, newCount: 0 });
}

1.14. Как всё связывается: “данные → функции → DOM → события → состояние”

Это ключевой “проектный” смысл ЛР-3.


1.14.1. Данные предметной области хранятся в виде массива объектов

  • массив items;
  • каждый объект — запись предметной области.

1.14.2. Реализованы функции обработки данных (фильтрация/поиск/сортировка/агрегация)

  • фильтрация: filterByStatus, filterByMinValue;
  • поиск: findById;
  • сортировка: sortByValueDesc;
  • агрегация: buildStats.

1.14.3. Интерфейс формируется/обновляется через DOM (создание/удаление узлов)

  • функция renderList(itemsToRender) формирует интерфейс;
  • карточки создаются через createElement;
  • контейнер очищается и перерисовывается;
  • удаление производится либо через remove(), либо через перерисовку после изменения данных.

1.14.4. Обработчики событий управляют состоянием интерфейса

  • кнопки вызывают нужную функцию обработки данных, затем renderList;
  • поле ввода влияет на фильтрацию;
  • добавление/удаление изменяет массив и приводит к обновлению списка.

1.14.5. Логика выделена в модули

Принцип разделения ответственности:

  • data.js — хранит набор данных предметной области (массив объектов);
  • logic.js — хранит функции обработки данных (filter/find/sort/reduce и т.д.);
  • script.js — связывает DOM, события и вызовы функций (UI-слой).

1.15. Основы модульности

1.15.1. Минимальная модульность без ES-модулей

Чтобы не вводить отдельную тему type="module", модульность реализуется через разделение по файлам и порядок подключения.

index.html

<script src="data.js"></script>
<script src="logic.js"></script>
<script src="script.js"></script>

Тогда:

  • items из data.js будет доступен в script.js;
  • функции из logic.js также будут доступны.

Правило: порядок подключения важен.


1.15.2. Пример структуры файлов

data.js   → const items = [...]
logic.js  → функции filter/find/sort/reduce
script.js → DOM, события, renderList

2. Задание

Цель: закрепить работу с DOM и событиями, а также применить функции, массивы, объекты, методы обработки данных и основы модульности на материале своей предметной области.


Смысл лабораторной работы

Переход от “алгоритмов в консоли” к “алгоритмам, управляемым интерфейсом”: данные предметной области представлены как массив объектов, обработка данных оформляется функциями, а интерфейс формируется и обновляется через DOM на основе пользовательских событий.


Ключевой результат

Интерактивная страница, в которой:

  • данные предметной области хранятся в виде массива объектов;
  • реализованы функции обработки данных (фильтрация/поиск/сортировка/агрегация);
  • интерфейс формируется/обновляется через DOM (создание/удаление узлов);
  • обработчики событий управляют состоянием интерфейса;
  • логика выделена в модули (минимум 2 файла JS).

2.1. Задания на закрепление теоретического материала (выполнить до работы с предметной областью)

Данный блок выполняется в отдельном файле practice-lr3.js (или в конце script.js), чтобы студент мог продемонстрировать понимание теории до использования своих данных предметной области.

Требования к оформлению:

  • каждая задача должна завершаться console.log(...) с выводом результата;
  • запрещены регулярные выражения и асинхронность (fetch/async/await) в этой лабораторной работе;
  • допускается использование filter, find, sort, reduce.

2.1.1. Блок A — функции

Задача A1.
Создать функцию calcTotal(a, b), которая:

  • принимает два числа a и b;
  • возвращает их сумму;
  • выводит результат в консоль.

Ожидаемый результат:

  • calcTotal(10, 5) возвращает 15 и выводится в консоль.

Задача A2.
Создать функцию formatRecord(id, title, status), которая:

  • принимает id (number), title (string), status (string);
  • возвращает строку формата: "#<id> <title> [<status>]";
  • продемонстрировать вызов функции в консоли.

Ожидаемый результат:

  • для входа formatRecord(3, "Тестовая запись", "new") возвращается строка "#3 Тестовая запись [new]".

2.1.2. Блок B — массивы

Задача B1.
Создать массив чисел values = [1200, 500, 800, 1500] и:

  • посчитать сумму всех элементов циклом for;
  • вывести сумму в консоль.

Ожидаемый результат:

  • корректная сумма 4000.

Задача B2.
На том же массиве values:

  • отфильтровать значения >= 800 с помощью filter;
  • вывести новый массив в консоль.

Ожидаемый результат:

  • [1200, 800, 1500].

2.1.3. Блок C — объекты

Задача C1.
Создать объект record, содержащий поля:

  • id (number),
  • title (string),
  • value (number),
  • status (string),
  • createdAt (string).

Вывести объект в консоль и затем:

  • изменить status на другое значение;
  • снова вывести объект в консоль.

Ожидаемый результат:

  • видно изменение поля status без переназначения переменной (через const допускается изменение содержимого).

Задача C2.
Создать функцию isNew(record), которая:

  • принимает объект записи;
  • возвращает true, если record.status === "new", иначе false;
  • продемонстрировать работу функции в консоли на 2 объектах с разными статусами.

Ожидаемый результат:

  • корректные true/false.

2.1.4. Блок D — методы обработки данных

Задача D1.
Создать массив объектов testItems из 4 записей (произвольных) и:

  • найти запись с заданным id через find;
  • вывести найденный объект в консоль (или null, если не найдено).

Ожидаемый результат:

  • найден правильный объект.

Задача D2.
На массиве testItems:

  • посчитать статистику через reduce: количество записей и сумму value;
  • вывести объект статистики в консоль.

Ожидаемый результат:

  • объект вида { totalCount: ..., sumValue: ... } с корректными значениями.

2.1.5. Блок E — основы модульности

Задача E1.
Создать файлы data.js, logic.js, script.js (даже если они пока пустые) и подключить их в index.html в порядке:

<script src="data.js"></script>
<script src="logic.js"></script>
<script src="script.js"></script>

Ожидаемый результат:

  • страница открывается без ошибок в консоли.

Задача E2. В logic.js создать функцию helloFromLogic(), которая возвращает строку "logic works".

В script.js:

  • вызвать helloFromLogic() и вывести результат в консоль.

Ожидаемый результат:

  • в консоли выводится "logic works".

2.1.6. Блок F — DOM (2 задачи)

Задача F1. В index.html создать элемент:

<div id="message"></div>

В script.js:

  • получить его через getElementById;
  • установить textContent = "DOM работает".

Ожидаемый результат:

  • на странице отображается текст "DOM работает".

Задача F2. В index.html создать контейнер:

<div id="demoList"></div>

В script.js:

  • создать 3 элемента <p> через createElement;
  • заполнить их текстом;
  • вставить в #demoList через appendChild.

Ожидаемый результат:

  • на странице появляются 3 строки (3 параграфа).

2.2. Исходные данные (предметная область)

Для выполнения лабораторной работы используется предметная область, закреплённая за студентом на семестр (см. перечень в ЛМС / паспорт предметной области passport.md).

Требования к исходным данным:

  • предметная область должна быть та же, что и в ЛР-1 и ЛР-2;
  • данные должны быть осмысленными (соответствовать предметной области, а не “item1/item2”);
  • в данных должны присутствовать разные статусы (минимум 2), обязательно наличие "new".

2.3. Модульность проекта

Задание: Организовать код проекта в виде модулей (разделение по файлам), чтобы отделить данные, логику обработки и работу с DOM.

Требования:

  1. В корне проекта создать (или добавить) файлы:

  2. data.js

  3. logic.js
  4. script.js
  5. В index.html подключить файлы в правильном порядке:
<script src="data.js"></script>
<script src="logic.js"></script>
<script src="script.js"></script>
  1. Убедиться, что в консоли нет ошибок, связанных с неопределёнными переменными/функциями (например, items is not defined).

Ожидаемый результат:

  • проект запускается;
  • данные и функции доступны в script.js;
  • нет ошибок подключения.

2.4. Данные предметной области как массив объектов (обязательное)

Задание: Создать набор данных предметной области, который будет источником для построения интерфейса.

Требования:

  1. В файле data.js создать массив items, содержащий минимум 8 объектов.
  2. Каждый объект обязан иметь поля:

  3. id (number)

  4. title (string)
  5. value (number)
  6. status (string)
  7. createdAt (string YYYY-MM-DD)

  8. Значения должны соответствовать предметной области студента.

Пример структуры (адаптировать под свою область):

const items = [
  { id: 1, title: "Не работает принтер", value: 1200, status: "new", createdAt: "2026-02-10" },
  { id: 2, title: "Настроить почту",      value: 800,  status: "done", createdAt: "2026-02-11" },
  { id: 3, title: "Сбой сети",           value: 1500, status: "new", createdAt: "2026-02-12" }
];

Ожидаемый результат:

  • console.log(items) выводит массив объектов;
  • в наборе есть разные статусы, включая "new".

2.5. Функции обработки данных

Задание: Вынести обработку данных в отдельные функции в файле logic.js.

Требования:

В файле logic.js реализовать функции:

  1. Фильтрация по статусу:
function filterByStatus(items, status) {
  return items.filter(item => item.status === status);
}
  1. Поиск по id:
function findById(items, id) {
  return items.find(item => item.id === id) || null;
}
  1. Сортировка по value по убыванию (через копию массива):
function sortByValueDesc(items) {
  const copy = items.slice();
  copy.sort((a, b) => b.value - a.value);
  return copy;
}
  1. Агрегация статистики (через reduce):
function buildStats(items) {
  return items.reduce((acc, item) => {
    acc.totalCount += 1;
    acc.sumValue += item.value;
    if (item.value > acc.maxValue) acc.maxValue = item.value;
    if (item.status === "new") acc.newCount += 1;
    return acc;
  }, { totalCount: 0, sumValue: 0, maxValue: 0, newCount: 0 });
}

Ожидаемый результат:

  • функции вызываются из script.js;
  • логика обработки данных не дублируется в обработчиках кнопок;
  • результаты функций можно вывести в консоль для проверки.

2.6. Формирование списка через DOM

Задание: Реализовать отрисовку списка записей не строкой в <pre>, а через создание DOM-узлов.

Требования:

  1. В index.html создать контейнер списка:
<div id="list"></div>
  1. В script.js реализовать функцию renderList(itemsToRender), которая:

  2. очищает контейнер списка;

  3. для каждого элемента создаёт DOM-узел (карточку/строку);
  4. отображает минимум: id, title, value, status, createdAt;
  5. добавляет кнопку “Удалить” внутри карточки (подготовка к удалению).

Пример (структуру можно менять под свой дизайн, но принцип сохраняется):

function renderList(itemsToRender) {
  listEl.textContent = "";

  for (const item of itemsToRender) {
    const card = document.createElement("div");
    card.className = "card";

    const h3 = document.createElement("h3");
    h3.textContent = `${item.title}`;

    const info = document.createElement("p");
    info.textContent = `id=${item.id} | value=${item.value} | status=${item.status} | createdAt=${item.createdAt}`;

    const btnRemove = document.createElement("button");
    btnRemove.textContent = "Удалить";
    btnRemove.dataset.action = "remove";
    btnRemove.dataset.id = String(item.id);

    card.appendChild(h3);
    card.appendChild(info);
    card.appendChild(btnRemove);

    listEl.appendChild(card);
  }
}

Ожидаемый результат:

  • список отображается как набор карточек/строк;
  • на странице присутствуют созданные DOM-узлы.

2.7. События и управление состоянием интерфейса

Задание: Создать кнопки управления и реализовать обработчики событий, которые изменяют отображаемый список и выводят статистику.

Требования:

  1. В index.html добавить кнопки:

  2. “Показать все”

  3. “Показать NEW”
  4. “Сортировать по value ↓”
  5. “Показать статистику”

Пример:

<button id="btnAll">Показать все</button>
<button id="btnNew">Показать NEW</button>
<button id="btnSort">Сортировать по value ↓</button>
<button id="btnStats">Показать статистику</button>
<div id="message"></div>
  1. В script.js реализовать обработчики:

  2. btnAllrenderList(items)

  3. btnNewrenderList(filterByStatus(items, "new"))
  4. btnSortrenderList(sortByValueDesc(items))
  5. btnStats → вычислить buildStats(items) и вывести результат в #message через textContent

Пример вывода статистики:

const stats = buildStats(items);
messageEl.textContent =
  `Всего записей: ${stats.totalCount}\n` +
  `Сумма value: ${stats.sumValue}\n` +
  `Максимум value: ${stats.maxValue}\n` +
  `Количество status="new": ${stats.newCount}`;

Ожидаемый результат:

  • кнопки работают;
  • список и статистика меняются без перезагрузки страницы;
  • данные отображаются через DOM.

3. Итоговая задача: “Интерактивный список записей” (ЛР1 → ЛР2 → ЛР3)

Цель: развить интерфейс проекта семестра, превратив данные и алгоритмы из ЛР-2 в полноценный интерактивный UI через DOM.


3.1. Модификация верстки index.html (UI управления + список + сообщения)

В существующую верстку проекта добавить:

  1. Блок управления (кнопки + область сообщений #message).
  2. Контейнер списка #list.
  3. (Рекомендуется) простую стилизацию карточек в style.css (не является главным критерием, но улучшает читаемость).

3.2. Требования к логике и архитектуре

  • данные находятся в data.js (массив объектов);
  • обработка данных оформлена функциями в logic.js;
  • работа с DOM и событиями выполняется в script.js;
  • интерфейс обновляется через renderList(...);
  • запрещено дублировать одинаковую обработку данных в нескольких обработчиках (используются функции).

3.3. Обязательные сценарии итоговой задачи

Студент обязан продемонстрировать:

  1. Показ всех записей.
  2. Фильтрацию по статусу "new".
  3. Сортировку по value по убыванию.
  4. Вывод статистики (totalCount, sumValue, maxValue, newCount).
  5. Наличие кнопки “Удалить” в карточке (кнопка должна быть создана через DOM и иметь dataset для id).

3.4. Требования к сдаче

В одном репозитории должны быть:

  • обновлённый index.html (кнопки, #list, #message);
  • data.js (массив объектов);
  • logic.js (функции обработки данных);
  • script.js (DOM + события + renderList);
  • при необходимости — уточнение в README.md (что добавлено в ЛР3);
  • passport.md остаётся и используется дальше.

3.5. Для выполнения требуется

  1. Шаблон отчёта, указанный в описании лабораторной работы.
  2. Вариант задания, закреплённый за студентом на семестр и опубликованный в ЛМС.
  3. Требования к оформлению — согласно методическим указаниям в ЛМС или соответствующему разделу документации.
  4. Ссылка на репозиторий, прикрепляется студентом к отчету.

3.6. Запрет

Запрещается использование систем искусственного интеллекта для выполнения лабораторной работы.

Работы, выполненные с использованием ИИ, полностью или частично скопированные, а также не сданные, оцениваются в 0 баллов без возможности доработки.


4. Контрольные вопросы

  1. Что такое DOM и почему его называют объектной моделью документа?
  2. Чем getElementById отличается от querySelector?
  3. Что возвращает querySelectorAll и как правильно обработать результат?
  4. Чем textContent отличается от innerHTML?
  5. Что делает document.createElement() и почему элемент “не виден”, пока его не вставили в DOM?
  6. Зачем нужна функция renderList и почему нельзя дублировать отрисовку в каждом обработчике?
  7. Как в обработчике события получить данные из input.value?
  8. Почему сортировка через sort() требует осторожности и зачем делать копию массива?
  9. Что делает reduce() и почему он полезен для статистики?
  10. Зачем разносить проект на data.js, logic.js, script.js и почему важен порядок подключения файлов?

5. Чек-лист для самопроверки

Баллы Критерии оценки
20 Выполнены задания на закрепление теории (блок 2.1: по 2 задачи на каждый блок A–F, результаты выведены в консоль/на страницу, ошибок нет); реализованы модули (data.js, logic.js, script.js) и корректное подключение; данные предметной области как массив объектов (8+); функции фильтрации/поиска/сортировки/агрегации вынесены в logic.js; список формируется через DOM (createElement, append/appendChild), есть кнопка “Удалить” в карточке с использованием dataset; реализованы обработчики кнопок управления (все сценарии 2.7) и корректное обновление UI через renderList(...); статистика выводится в #message через textContent; изменения зафиксированы в GitHub (коммиты и актуальные файлы).
16–19 Теоретический блок 2.1 выполнен почти полностью (допущены 1–2 недочёта: не выведен результат одной задачи, есть незначительная ошибка оформления), и/или один из ключевых сценариев предметной части реализован частично (например, сортировка/статистика/кнопка удаления/фильтрация NEW), и/или есть небольшие логические недочёты (например, сортировка меняет исходный массив без копии, вывод статистики не полностью структурирован), при этом модульность и DOM-рендер в целом присутствуют.
12–15 Теоретический блок 2.1 выполнен частично (выполнены не все блоки A–F или нет демонстрации результатов), и/или предметная часть работает фрагментарно: DOM-отрисовка есть и данные корректны, но модульность нарушена (всё в одном файле) или функции обработки данных дублируются в обработчиках или реализовано менее 3 обязательных сценариев из 2.7; кнопка “Удалить” может быть отсутствовать или не привязана через dataset.
8–11 Есть получение элементов DOM и отдельные обработчики событий, но теоретический блок 2.1 не выполнен или формальный; список не формируется через createElement (например, выводится одним блоком через textContent/innerHTML), нет устойчивой функции renderList, статистика неструктурирована или отсутствует, привязка к предметной области слабая (данные не отражают предметную область или слишком условные).
1–7 Формальный шаблон без рабочей логики: отсутствует теоретический блок 2.1, нет модульности, нет функций обработки данных, нет корректного DOM-рендера, кнопки не работают или вызывают ошибки, данные не оформлены как массив объектов.
0 Работа не сдана / неработоспособна / выполнена с использованием ИИ.

6. Шаблон отчёта

👉 Скачать шаблон отчёта