<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[MobileDevTisbi]]></title><description><![CDATA[Obsidian digital garden]]></description><link>http://github.com/dylang/node-rss</link><image><url>site-lib/media/favicon.png</url><title>MobileDevTisbi</title><link/></image><generator>Webpage HTML Export plugin for Obsidian</generator><lastBuildDate>Thu, 07 May 2026 22:29:13 GMT</lastBuildDate><atom:link href="site-lib/rss.xml" rel="self" type="application/rss+xml"/><pubDate>Thu, 07 May 2026 22:28:11 GMT</pubDate><ttl>60</ttl><dc:creator/><item><title><![CDATA[Дополнительные темы]]></title><description><![CDATA[Это темы которые не входят в основной цикл курса, но будут достаточно полезными. К тому же тут будут объяснения некоторых терминов.
<a data-href="Методология BEM" href="материалы/подтемы/дополнительные-темы/методология-bem.html" class="internal-link" target="_self" rel="noopener nofollow">Методология BEM</a>
<br><a data-href="Спагетти в коде" href="материалы/подтемы/дополнительные-темы/спагетти-в-коде.html" class="internal-link" target="_self" rel="noopener nofollow">Спагетти в коде</a>
]]></description><link>дополнительные-темы.html</link><guid isPermaLink="false">Дополнительные темы.md</guid><pubDate>Thu, 07 May 2026 10:37:49 GMT</pubDate></item><item><title><![CDATA[Методология BEM]]></title><description><![CDATA[При разработке крупных интерфейсов без чёткой структуры CSS быстро превращается в «спагетти»: селекторы конфликтуют, стили влияют на непреднамеренные элементы, а изменение одного компонента ломает другие. Особенно остро это ощущается в командной работе и при масштабировании проекта.Методологии, такие как BEM, решают эти проблемы за счёт:
явного разделения ответственности между компонентами,
предсказуемой структуры классов,
изоляции стилей.
BEM (Block – Element – Modifier) была разработана в Яндексе около 2010 года для решения задач масштабируемости больших веб-интерфейсов. Основная идея — строить UI из независимых, переиспользуемых блоков, которые не зависят от контекста размещения.Блок — это автономный компонент интерфейса, который может существовать независимо.
Примеры: Button, Header, ProductCard.Важно:
Блок не знает о других блоках.
Может быть переиспользован в любом месте без изменений стилей.
Элемент — часть блока, не имеющая смысла вне него.
Пример: у блока ProductCard могут быть элементы __image, __title, __price.Правило:
Элемент всегда принадлежит конкретному блоку.
Нельзя использовать элемент без родительского блока.
Модификатор — это флаг, описывающий состояние или вариант внешнего вида блока/элемента.
Примеры: button--primary, menu__item--active.Важно:
Модификатор всегда используется вместе с базовым классом блока или элемента.
Он не задаёт стили сам по себе — только расширяет или переопределяет базовые. Блок: .block
Элемент: .block__element
Модификатор блока: .block--modifier
Модификатор элемента: .block__element--modifier Используйте осмысленные английские имена (search-form, а не sfrm).
Не используйте теги, ID или глобальные селекторы в связке с BEM.
Избегайте вложенности в селекторах — каждый класс должен быть самодостаточным. Корректно:&lt;div className="card card--highlighted"&gt; &lt;h2 className="card__title"&gt;Title&lt;/h2&gt;
&lt;/div&gt; Некорректно:// Элемент вне блока
&lt;span className="title"&gt;Title&lt;/span&gt; // Модификатор без базового класса
&lt;div className="card--highlighted"&gt;...&lt;/div&gt; // Вложенность элементов
&lt;div className="card__header__logo"&gt;...&lt;/div&gt; Читаемость: по имени класса сразу ясно, к какому блоку он относится.
Изоляция: стили одного блока не влияют на другие.
Поддержка: легко вносить изменения без страха сломать что-то в другом месте.
Командная работа: единые правила упрощают код-ревью и onboarding.
// Button.jsx
export default function Button({ variant = 'default', children, disabled = false }) { const baseClass = 'button'; const modifierClass = variant ? `button--${variant}` : ''; const disabledClass = disabled ? 'button--disabled' : ''; return ( &lt;button className={[baseClass, modifierClass, disabledClass].filter(Boolean).join(' ')}&gt; {children} &lt;/button&gt; );
}
/* Button.css */
.button { padding: 8px 16px; border: 1px solid #ccc; background: white;
} .button--primary { background: #007bff; color: white;
} .button--disabled { opacity: 0.6; pointer-events: none;
}
// ProductCard.jsx
export default function ProductCard({ title, price, isFeatured, hasDiscount }) { return ( &lt;article className={`product-card ${isFeatured ? 'product-card--featured' : ''}`}&gt; &lt;img className="product-card__image" src="..." alt={title} /&gt; &lt;h3 className="product-card__title"&gt;{title}&lt;/h3&gt; &lt;span className={`product-card__price ${hasDiscount ? 'product-card__price--discounted' : ''}`}&gt; ${price} &lt;/span&gt; &lt;/article&gt; );
}
.product-card { border: 1px solid #eee; padding: 16px;
} .product-card--featured { border-color: gold; box-shadow: 0 0 8px rgba(255, 215, 0, 0.3);
} .product-card__title { font-size: 1.2rem; margin: 8px 0;
} .product-card__price--discounted { color: red; text-decoration: line-through;
} Sass/Less: можно использовать вложенность, но только для модификаторов и элементов внутри блока, например:
.button { // базовые стили &amp;--primary { /* ... */ } &amp;__icon { /* ... */ }
} Это не нарушает принципы BEM, если генерируемый CSS остаётся плоским. Stylelint: настройте правила plugin/stylelint-bem для автоматической проверки именования. CSS Modules: отлично сочетаются с BEM — вы получаете изоляцию на уровне сборки + семантику BEM. В CSS-in-JS (например, styled-components) BEM теряет актуальность, так как каждый компонент уже изолирован. Однако идеи BEM (блок/элемент/модификатор) полезны для внутренней структуры компонента.Альтернатива: использовать объектную структуру стилей:const styles = { button: { /* базовый */ }, button_primary: { /* модификатор */ }
};
BEM особенно эффективен в React, когда:
вы используете обычный CSS или CSS Modules,
компоненты рендерят много дочерних элементов,
важна читаемость HTML в DevTools.
Не нужно применять BEM к каждому &lt;div&gt; — только к тем компонентам, которые имеют визуальную или функциональную целостность.
SMACSS: похож на BEM, но менее строгий.
Atomic CSS / Utility-first (Tailwind): вместо семантических имён — утилиты (p-4, bg-blue-500). Подходит для быстрой разработки, но хуже документирует бизнес-логику.
CSS Modules / Scoped CSS: решают проблему изоляции, но не дают соглашения по структуре. BEM остаётся лучшим выбором, когда важна долгосрочная поддержка, командная разработка и семантическая ясность.
BEM — это не догма, а практический инструмент для организации CSS. Его сила — в последовательности, а не в жёстких правилах.Рекомендации:
Начните применять BEM с новых компонентов.
Не стремитесь к «идеальному» BEM — стремитесь к последовательному.
В React используйте BEM там, где он добавляет ценность: в UI-библиотеках, дизайн-системах, крупных проектах.
Главное — писать код, который легко читать не только вам сейчас, но и вашему коллеге (и вам) через год. BEM помогает в этом.]]></description><link>материалы/подтемы/дополнительные-темы/методология-bem.html</link><guid isPermaLink="false">Материалы/Подтемы/Дополнительные темы/Методология BEM.md</guid><pubDate>Thu, 07 May 2026 10:35:18 GMT</pubDate></item><item><title><![CDATA[Спагетти в коде]]></title><description><![CDATA[Термин «спагетти» (от англ. spaghetti code) — это разговорное, но устоявшееся в программировании выражение, обозначающее плохо структурированный, запутанный и трудно поддерживаемый код.
Сильная взаимосвязанность компонентов: изменение в одном месте неожиданно влияет на другие.
Отсутствие чёткой архитектуры: логика размазана по файлам без разделения ответственности.
Глубокая или хаотичная вложенность (например, в CSS — длинные цепочки селекторов вроде .header .nav ul li a:hover span).
Побочные эффекты: стили или скрипты работают «только потому, что так сложилось», а не по задуманной логике.
Сложность тестирования и рефакторинга: страх что-то изменить, потому что всё может сломаться.
]]></description><link>материалы/подтемы/дополнительные-темы/спагетти-в-коде.html</link><guid isPermaLink="false">Материалы/Подтемы/Дополнительные темы/Спагетти в коде.md</guid><pubDate>Thu, 07 May 2026 10:30:04 GMT</pubDate></item><item><title><![CDATA[Тема №29. Работа с API в React Native]]></title><description><![CDATA[В этой теме вы научитесь выполнять запросы к веб-API из React Native-приложения, обрабатывать ответы и отображать данные на экране. Поймёте, как интегрировать асинхронные данные в нативный интерфейс, обрабатывать загрузку и ошибки — как в реальных мобильных приложениях.
<a data-href="Запросы через fetch в React Native" href="материалы/подтемы/секция-3.-react-native/тема-№29/запросы-через-fetch-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Запросы через fetch в React Native</a>
<br><a data-href="Обработка CORS и сетевых ошибок" href="материалы/подтемы/секция-3.-react-native/тема-№29/обработка-cors-и-сетевых-ошибок.html" class="internal-link" target="_self" rel="noopener nofollow">Обработка CORS и сетевых ошибок</a>
<br><a data-href="Использование Axios в React Native" href="материалы/подтемы/секция-3.-react-native/тема-№29/использование-axios-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Использование Axios в React Native</a> <br><a data-href="Практика №17. Мессенджер NIKITA" href="задания/секция-3.-react-native/практика-№17.-мессенджер-nikita.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №17. Мессенджер NIKITA</a>
<br><a data-href="Тема №30. Тестирование и отладка в React Native" href="лекции/секция-3.-react-native/тема-№30.-тестирование-и-отладка-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №30. Тестирование и отладка в React Native</a>]]></description><link>лекции/секция-3.-react-native/тема-№29.-работа-с-api-в-react-native.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №29. Работа с API в React Native.md</guid><pubDate>Thu, 07 May 2026 10:17:45 GMT</pubDate></item><item><title><![CDATA[Тема №28. Работа с локальным хранилищем и файлами]]></title><description><![CDATA[В этой теме вы изучите, как сохранять данные на устройстве в React Native — без браузерного localStorage. Поймёте, как использовать AsyncStorage для хранения простых данных и библиотеки react-native-fs для работы с файлами. Это необходимо для кэширования, сохранения настроек и офлайн-работы приложений.
<a data-href="Особенность локального хранилища в React Native" href="материалы/подтемы/секция-3.-react-native/тема-№28/особенность-локального-хранилища-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Особенность локального хранилища в React Native</a>
<br><a data-href="AsyncStorage" href="материалы/подтемы/секция-3.-react-native/тема-№28/asyncstorage.html" class="internal-link" target="_self" rel="noopener nofollow">AsyncStorage</a>
<br><a data-href="Типизация AsyncStorage в TypeScript" href="материалы/подтемы/секция-3.-react-native/тема-№28/типизация-asyncstorage-в-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация AsyncStorage в TypeScript</a>
<br><a data-href="Работа с файлами" href="материалы/подтемы/секция-3.-react-native/тема-№28/работа-с-файлами.html" class="internal-link" target="_self" rel="noopener nofollow">Работа с файлами</a>
<br><a data-href="Когда что использовать" href="материалы/подтемы/секция-3.-react-native/тема-№28/когда-что-использовать.html" class="internal-link" target="_self" rel="noopener nofollow">Когда что использовать</a> <br><a data-href="Практика №16. To-Do организатор" href="задания/секция-3.-react-native/практика-№16.-to-do-организатор.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №16. To-Do организатор</a>
<br><a data-href="Тема №29. Работа с API в React Native" href="лекции/секция-3.-react-native/тема-№29.-работа-с-api-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №29. Работа с API в React Native</a>]]></description><link>лекции/секция-3.-react-native/тема-№28.-работа-с-локальным-хранилищем-и-файлами.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №28. Работа с локальным хранилищем и файлами.md</guid><pubDate>Thu, 07 May 2026 10:17:29 GMT</pubDate></item><item><title><![CDATA[Тема №26. Управление состоянием в React Native]]></title><description><![CDATA[В этой теме вы повторите темы состояний но уже в контексте приложения в React Native.
<a data-href="useState в мобильных приложениях" href="материалы/подтемы/секция-3.-react-native/тема-№26/usestate-в-мобильных-приложениях.html" class="internal-link" target="_self" rel="noopener nofollow">useState в мобильных приложениях</a>
<br><a data-href="useContext для глобального состояния" href="материалы/подтемы/секция-3.-react-native/тема-№26/usecontext-для-глобального-состояния.html" class="internal-link" target="_self" rel="noopener nofollow">useContext для глобального состояния</a>
<br><a data-href="useReducer для сложной логики состояния" href="материалы/подтемы/секция-3.-react-native/тема-№26/usereducer-для-сложной-логики-состояния.html" class="internal-link" target="_self" rel="noopener nofollow">useReducer для сложной логики состояния</a>
<br><a data-href="Обработка асинхронного состояния" href="материалы/подтемы/секция-3.-react-native/тема-№26/обработка-асинхронного-состояния.html" class="internal-link" target="_self" rel="noopener nofollow">Обработка асинхронного состояния</a>
<br><a data-href="Рекомендации по управлению состоянием" href="материалы/подтемы/секция-3.-react-native/тема-№26/рекомендации-по-управлению-состоянием.html" class="internal-link" target="_self" rel="noopener nofollow">Рекомендации по управлению состоянием</a> <br><a data-href="Практика №15. Калькулятор" href="задания/секция-3.-react-native/практика-№15.-калькулятор.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №15. Калькулятор</a>
<br><a data-href="Тема №27. Навигация в React Native" href="лекции/секция-3.-react-native/тема-№27.-навигация-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №27. Навигация в React Native</a>]]></description><link>лекции/секция-3.-react-native/тема-№26.-управление-состоянием-в-react-native.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №26. Управление состоянием в React Native.md</guid><pubDate>Thu, 07 May 2026 10:16:59 GMT</pubDate></item><item><title><![CDATA[Практика №17. Мессенджер NIKITA]]></title><description><![CDATA[Разработать мобильное приложение - простой мессенджер NIKITA. Пользователь выбирает аккаунт, видит список чатов и может писать сообщения в выбранном диалоге. Все данные загружаются и отправляются через REST API. Это задание не имеет конкретного ТЗ и требует навыки в проектировании задачи - большая часть оценки зависима как раз от "качества" понимания запроса, чтения доступного API и реализации UX/UI.
Документация API — (по запросу) Для диаграмм: <a rel="noopener nofollow" class="external-link is-unresolved" href="https://mermaid.live" target="_self">https://mermaid.live</a> <br>Для дизайна (опционально): <a rel="noopener nofollow" class="external-link is-unresolved" href="https://www.figma.com" target="_self">https://www.figma.com</a>
Приложение должно содержать три страницы:
Страница входа;
Страница чатов;
Конкретный чат.
И должно быть реализовано в React Native + Expo без сторонних зависимостей.GET /users → [{ id: "u1", name: "Анна", avatar: "..." }]
GET /chats?userId=u1 → [{ id: "c1", otherUserId: "u2", lastMessage: "Привет", timestamp: "..." }]
GET /messages?chatId=c1 → [{ id: "m1", senderId: "u2", text: "Привет!", timestamp: "..." }]
POST /messages ← { chatId: "c1", senderId: "u1", text: "Как дела?", timestamp: ISO }
На выполнение выделяется 7 практических пары.
Градация баллов после дедлайна:
1 пара: 75%
2 пара: 50%
3 пара: 25%
]]></description><link>задания/секция-3.-react-native/практика-№17.-мессенджер-nikita.html</link><guid isPermaLink="false">Задания/Секция 3. React Native/Практика №17. Мессенджер NIKITA.md</guid><pubDate>Thu, 07 May 2026 10:16:31 GMT</pubDate></item><item><title><![CDATA[Практика №14. Социальная сеть - Часть 3. Подключение к бэкэнду]]></title><description><![CDATA[Разработать одностраничное веб-приложение (SPA) на React с использованием Vite и JavaScript, имитирующее базовую социальную сеть. В отличие от предыдущей части, теперь приложение должно взаимодействовать с реальным RESTful API бэкенда. Структура проекта должна соответствовать стандартной архитектуре React + Vite. Репозиторий на GitHub должен называться: Group_LastName_task-12, Group_LastName_task-13 или Group_LastName_task-14.
Заготовка проекта react-project.
(Материалы/Заготовки под практики/react-project.zip)
Документация API — (по запросу)
В рамках этой части необходимо заменить mock-данные из JSON на реальные запросы к бэкенду, реализовать полноценную авторизацию через API и обеспечить корректную работу всех функций, описанных в задании 12 (и 13), но уже с сохранением изменений на сервере.Приложение должно поддерживать все функции из части 12 и 13, но теперь:
Все данные (посты, пользователи, комментарии, лайки, заявки в друзья) загружаются из бэкенда.
Любые действия пользователя (лайки, комментарии, редактирование профиля и т.д.) отправляются на сервер и сохраняются там.
Авторизация реализуется через логин/пароль, передаваемые на эндпоинт авторизации.
После успешной авторизации клиент получает access token, который используется во всех последующих запросах.
Токен должен храниться в localStorage.
При перезагрузке страницы приложение должно восстанавливать сессию, если токен ещё валиден. Просматривать публичные посты;
Просматривать публичные профили пользователей;
Искать пользователей;
Переходить на страницу авторизации. Редактировать свой профиль;
Создавать, редактировать и удалять свои посты;
Писать и удалять комментарии (свои и чужие — в своих постах);
Лайкать/дизлайкать посты;
Отправлять, принимать и отклонять заявки в друзья;
Выходить из аккаунта (очистка токена). Все HTTP-запросы должны выполняться через кастомные хуки (например, usePosts, useAuth).
Обработка ошибок обязательна: показывать пользователю понятные сообщения («Неверный логин», «Недостаточно прав» и т.д.).
Не использовать внешние библиотеки, кроме разрешённых в заготовке.
Все компоненты — в отдельных файлах, с соблюдением архитектуры (components/, pages/, hooks/, services/ и т.д.).
Должна быть страница 404.
UX/UI должен быть удобным и визуально качественным.
Обязательна история коммитов.
3 практических сессий После сессии 1: 75% от максимального балла После сессии 2: 50% После сессии 3: 25% ]]></description><link>задания/секция-2.-react/практика-№14.-социальная-сеть-часть-3.-подключение-к-бэкэнду.html</link><guid isPermaLink="false">Задания/Секция 2. React/Практика №14. Социальная сеть - Часть 3. Подключение к бэкэнду.md</guid><pubDate>Thu, 07 May 2026 10:08:33 GMT</pubDate></item><item><title><![CDATA[Практика №16. To-Do организатор]]></title><description><![CDATA[Разработать мобильное приложение для управления списками задач (to-do lists) на React Native с использованием TypeScript и локального хранилища. Приложение должно позволять создавать несколько списков задач, добавлять в них задачи с описанием, дедлайнами и статусами, а также редактировать и удалять их. Все данные сохраняются на устройстве и восстанавливаются после перезапуска.Задание обязано быть опубликовано в новом приватном репозитории организации GitHub с названием Группа_Фамилия_task-16.
(пусто)
Приложение должно состоять из трёх основных экранов:
Главная страница — список всех списков задач.
Страница списка задач — отображение и управление задачами внутри выбранного списка.
Страница задачи — детальное представление и редактирование одной задачи.
Все действия пользователя (создание, редактирование, удаление) должны мгновенно отражаться в интерфейсе и сохраняться в локальном хранилище.
Создание списка с уникальным названием;
Редактирование названия списка;
Удаление списка со всеми задачами внутри;
Отображение всех списков на главной странице. Создание задачи с: Названием (обязательно),
Описанием (опционально),
Статусом ("Получено" по умолчанию),
Датой создания (автоматически),
Датой дедлайна (опционально). Редактирование любого поля задачи;
Удаление задачи;
Фильтрация задач по статусу: "Получено"
"В процессе"
"Сделано"
"Отменено" Для каждой задачи отображаются:
Название,
Описание (если есть),
Статус (визуально выделен цветом или значком),
Дата создания,
Дата дедлайна (если указана). Использование TypeScript — обязательно;
Хранение данных — только в локальной памяти устройства (AsyncStorage);
Запрещено использовать облачные API или внешние базы данных;
Все экраны — реализованы через навигацию; Чистый, понятный, без перегрузки элементами;
Поддержка темного/светлого режима — не обязательна, но приветствуется;
Кнопки и поля ввода — корректно масштабируются под разные экраны;
Использование ScrollView, FlatList для списков — обязательно.
На выполнение выделяется 4 практических пары.
Градация баллов после дедлайна:
1 пара: 50%
2 пара: 25%
3 пара: 10%
]]></description><link>задания/секция-3.-react-native/практика-№16.-to-do-организатор.html</link><guid isPermaLink="false">Задания/Секция 3. React Native/Практика №16. To-Do организатор.md</guid><pubDate>Thu, 07 May 2026 10:07:52 GMT</pubDate></item><item><title><![CDATA[Практика №10. Интерактивный счётчик с изменением темы]]></title><description><![CDATA[В рамках этого задания вам необходимо создать одностраничное веб-приложение с интерактивным счётчиком и возможностью смены темы. Оно обязано быть сделано при помощи React (vite), следовать правильному неймингу и иметь правильную структуру.Задание обязано быть опубликовано в новом приватном репозитории организации GitHub с названием Группа_Фамилия_task-10.Заготовка проекта react-project.
(Материалы/Заготовки под практики/react-project.zip)
Создайте новый компонент который реализует интерактивный счётчик со следующими параметрами: min
max
initial (по умолчанию должен стать min если не указано) Отобразите текущее значение счётчика в элементе и добавьте компонент в App (с заданными значениями). min = 0
max = 10
initial = 5 Под значением разместите три кнопки в одном контейнере: Кнопка «Уменьшить»
Кнопка «Сбросить»
Кнопка «Увеличить» Реализуйте логику: При нажатии «Уменьшить» значение уменьшается на 1, но не ниже min.
При нажатии «Увеличить» значение увеличивается на 1, но не выше max.
При нажатии «Сбросить» значение возвращается к initial. Кнопки должны автоматически отключаться при достижении границ: Если текущее значение равно min, кнопка «Уменьшить» имеет атрибут disabled.
Если текущее значение равно max, кнопка «Увеличить» имеет атрибут disabled. Все изменения должны отображаться мгновенно без перезагрузки страницы.
Используйте только встроенные средства React (хуки useState и JSX). Запрещено использовать innerHTML, сторонние библиотеки или глобальные переменные вне компонента.
Значения не должны сохраняться между сессиями.
Реализуйте переключение между светлой и тёмной темой:
Добавьте кнопку «Сменить тему» как отдельный компонент.
При первом запуске приложение использует светлую тему.
При нажатии на кнопку тема переключается: светлая ↔ тёмная.
В тёмной теме фон страницы — тёмно-серый (#121212), текст — белый (#ffffff).
В светлой теме фон — белый (#ffffff), текст — чёрный (#000000).
Состояние темы должно восстанавливаться при перезагрузке страницы даже после перезагрузки браузера.
Помимо фона, оно должно влиять и на компоненты счётчика и саму кнопку переключения.
На выполнение выделяется 3 практических пары.
Градация баллов после дедлайна:
1 пара: 50%
2 пара: 25%
3 пара: 10%
]]></description><link>задания/секция-2.-react/практика-№10.-интерактивный-счётчик-с-изменением-темы.html</link><guid isPermaLink="false">Задания/Секция 2. React/Практика №10. Интерактивный счётчик с изменением темы.md</guid><pubDate>Thu, 07 May 2026 10:04:17 GMT</pubDate></item><item><title><![CDATA[Практика №15. Калькулятор]]></title><description><![CDATA[Разработать мобильное приложение «Калькулятор», визуально и функционально соответствующее стандартному калькулятору Apple. Приложение должно быть реализовано на React Native с использованием TypeScript и Expo, без навигации между экранами (одноэкранное). Репозиторий должен быть опубликован в GitHub-организации предмета под именем Group_LastName_task-15.
Пример дизайна: калькулятор Apple (iOS)
<img alt="Pasted image 20260507125922.png" src="материалы/файлы/pasted-image-20260507125922.png" target="_self">
Для проверки UI — запуск через Expo Go на устройстве или эмуляторе
Необходимо создать полностью рабочий калькулятор с корректной логикой вычислений и аккуратным, адаптивным интерфейсом. Все элементы должны быть реализованы вручную (без использования готовых библиотек калькуляторов). Разрешено использовать только стандартные компоненты React Native и базовые стили (StyleSheet, View, Text, Pressable и т.п.).Приложение должно поддерживать следующие операции:
Ввод чисел от 0 до 9;
Ввод десятичной точки (.) — не более одной в числе;
Смена знака числа (±);
Очистка всего (AC) — сброс текущего состояния вычисления;
Четыре арифметические операции: +, -, ×, ÷;
Вычисление процента (%) — например: 200 × 5 % → 10;
Нажатие = для получения результата;
Корректное отображение промежуточных и финальных значений на дисплее;
Обработка ошибок: Деление на ноль → отобразить "Error" и блокировать дальнейший ввод до нажатия AC;
Переполнение (опционально, но желательно). Один экран без навигации;
Макет должен быть адаптивным под разные размеры экрана;
Цветовая палитра и пропорции кнопок — как у калькулятора Apple:
Шрифт — моноширинный или системный, крупный на дисплее;
Кнопки должны иметь обратную связь при нажатии (например, изменение opacity). Использование TypeScript;
Архитектура: код должен быть читаемым, разбитым на файлы и структурированным;
Логика вычислений — реализована самостоятельно (без eval()!);
Хранение состояния — через useState и собственные переменные (без Redux/Zustand);
Запрещено использовать сторонние UI-библиотеки (например, react-native-paper, native-base); Поддержка непрерывных вычислений: 5 + 3 = → 8 + 2 = → 10;
Улучшенная обработка длинных чисел (ограничение количества знаков на дисплее).
На выполнение выделяется 2 практических пары.
Градация баллов после дедлайна:
1 пара: 50%
2 пара: 25%
3 пара: 10%
]]></description><link>задания/секция-3.-react-native/практика-№15.-калькулятор.html</link><guid isPermaLink="false">Задания/Секция 3. React Native/Практика №15. Калькулятор.md</guid><pubDate>Thu, 07 May 2026 10:04:03 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20260507125922]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20260507125922.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20260507125922.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20260507125922.png</guid><pubDate>Thu, 07 May 2026 09:59:22 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Тема №23. Запросы к API в TypeScript]]></title><description><![CDATA[В этой теме вы изучите, как выполнять запросы к веб-API из приложений на TypeScript — от понимания, что такое API и как он работает, до отправки запросов с типизацией ответов. Вы познакомитесь с форматами данных JSON и FormData, научитесь описывать типы для ответов сервера и обрабатывать ошибки. Это фундамент для работы с бэкендом в мобильных и веб-приложениях.
<a data-href="Что такое API" href="материалы/подтемы/секция-2.-react/тема-№22-1/что-такое-api.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое API</a>
<br><a data-href="Форматы данных" href="материалы/подтемы/секция-2.-react/тема-№22-1/форматы-данных.html" class="internal-link" target="_self" rel="noopener nofollow">Форматы данных</a>
<br><a data-href="Отправка запросов" href="материалы/подтемы/секция-2.-react/тема-№22-1/отправка-запросов.html" class="internal-link" target="_self" rel="noopener nofollow">Отправка запросов</a>
<br><a data-href="Типизация ответов API" href="материалы/подтемы/секция-2.-react/тема-№22-1/типизация-ответов-api.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация ответов API</a>
<br><a data-href="Обработка ошибок" href="материалы/подтемы/секция-2.-react/тема-№22-1/обработка-ошибок.html" class="internal-link" target="_self" rel="noopener nofollow">Обработка ошибок</a> <br><a data-href="Практика №14. Социальная сеть - Часть 3. Подключение к бэкэнду" href="задания/секция-2.-react/практика-№14.-социальная-сеть-часть-3.-подключение-к-бэкэнду.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №14. Социальная сеть - Часть 3. Подключение к бэкэнду</a>
<br><a data-href="Тема №24. Введение в React Native" href="лекции/секция-3.-react-native/тема-№24.-введение-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №24. Введение в React Native</a>]]></description><link>лекции/секция-2.-react/тема-№23.-запросы-к-api-в-typescript.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №23. Запросы к API в TypeScript.md</guid><pubDate>Wed, 29 Apr 2026 09:41:00 GMT</pubDate></item><item><title><![CDATA[Тема №18. Routers в React]]></title><description><![CDATA[В этой теме вы изучите маршрутизацию в React — механизм для отображения разных компонентов в зависимости от текущего URL. Поймёте, как организовать навигацию между экранами приложения, используя библиотеку React Router, и как передавать параметры между маршрутами.
<a data-href="Что такое маршрутизация" href="материалы/подтемы/секция-2.-react/тема-№18/что-такое-маршрутизация.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое маршрутизация</a>
<br><a data-href="React Router — основная библиотека" href="материалы/подтемы/секция-2.-react/тема-№18/react-router-—-основная-библиотека.html" class="internal-link" target="_self" rel="noopener nofollow">React Router — основная библиотека</a>
<br><a data-href="Основные компоненты React Router" href="материалы/подтемы/секция-2.-react/тема-№18/основные-компоненты-react-router.html" class="internal-link" target="_self" rel="noopener nofollow">Основные компоненты React Router</a>
<br><a data-href="Параметры маршрута" href="материалы/подтемы/секция-2.-react/тема-№18/параметры-маршрута.html" class="internal-link" target="_self" rel="noopener nofollow">Параметры маршрута</a>
<br><a data-href="Вложенные маршруты" href="материалы/подтемы/секция-2.-react/тема-№18/вложенные-маршруты.html" class="internal-link" target="_self" rel="noopener nofollow">Вложенные маршруты</a>
<br><a data-href="Программная навигация" href="материалы/подтемы/секция-2.-react/тема-№18/программная-навигация.html" class="internal-link" target="_self" rel="noopener nofollow">Программная навигация</a>
<br><a data-href="Обработка несуществующих маршрутов" href="материалы/подтемы/секция-2.-react/тема-№18/обработка-несуществующих-маршрутов.html" class="internal-link" target="_self" rel="noopener nofollow">Обработка несуществующих маршрутов</a>
<br><a data-href="Загрузка данных в маршрутах" href="материалы/подтемы/секция-2.-react/тема-№18/загрузка-данных-в-маршрутах.html" class="internal-link" target="_self" rel="noopener nofollow">Загрузка данных в маршрутах</a> <br><a data-href="Практика №12. Социальная сеть - Часть 1. Верстка" href="задания/секция-2.-react/практика-№12.-социальная-сеть-часть-1.-верстка.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №12. Социальная сеть - Часть 1. Верстка</a>
<br><a data-href="Тема №19. Асинхронность в JavaScript" href="лекции/секция-2.-react/тема-№19.-асинхронность-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №19. Асинхронность в JavaScript</a>]]></description><link>лекции/секция-2.-react/тема-№18.-routers-в-react.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №18. Routers в React.md</guid><pubDate>Wed, 29 Apr 2026 09:40:25 GMT</pubDate></item><item><title><![CDATA[Что происходит при сборке]]></title><description><![CDATA[Сборка — это процесс преобразования исходного кода React Native-приложения в готовый нативный установочный файл. Хотя вы пишете на JavaScript, конечный пользователь устанавливает приложение, которое выглядит и работает как обычное iOS- или Android-приложение. Вот что происходит «под капотом» при запуске eas build.Expo генерирует минимальные нативные проекты для iOS и Android (на основе шаблонов). В эти проекты внедряется ваш JavaScript-код, а также все зависимости из package.json. Получается гибрид: нативная оболочка + интерпретатор JavaScript (Hermes или JSC).Во время сборки:
Metro Bundler объединяет все ваши .js и .ts файлы в один бандл (index.js).
Бандл минифицируется и оптимизируется.
На Android он может быть скомпилирован в байт-код Hermes (если включено).
Этот бандл копируется внутрь APK/IPA и становится частью ресурсов приложения.
В результате приложение больше не зависит от локального сервера — весь код уже внутри.После сборки вы получаете:
.apk — установочный файл для Android.
.ipa — установочный файл для iOS (требует подписи Apple Developer аккаунтом).
Эти файлы можно:
Установить напрямую на устройство (APK).
Загрузить в Google Play или App Store.
Распространять через TestFlight или Firebase App Distribution.
Важно: такое приложение больше не использует Expo Go. Оно полностью автономно и содержит только ваш код и необходимые части Expo SDK.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№31/что-происходит-при-сборке.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №31/Что происходит при сборке.md</guid><pubDate>Fri, 24 Apr 2026 11:47:22 GMT</pubDate></item><item><title><![CDATA[Сборка через Expo]]></title><description><![CDATA[Expo предоставляет облачную систему сборки под названием EAS (Expo Application Services). Она позволяет создавать нативные установочные файлы (.apk для Android, .ipa для iOS) без необходимости настройки локальной среды разработки (Xcode, Android Studio, JDK и т.д.).Основная команда для запуска сборки:eas build --platform android
илиeas build --platform ios
Если в проекте настроены профили сборки в eas.json, можно указать их явно:eas build --profile preview --platform android
Это создаёт тестовую сборку — приложение с вашим кодом, но без подписи для публикации в магазинах. Такой APK можно установить напрямую на устройство для проверки.Для финальной публикации используется профиль production:eas build --profile production --platform ios
Такая сборка подписывается сертификатами Apple и готова к загрузке в App Store.EAS — это набор облачных сервисов от Expo:
EAS Build — компиляция приложения на серверах Expo.
EAS Submit — автоматическая отправка в App Store и Google Play.
EAS Update — OTA-обновления JavaScript-кода без пересборки.
Для использования EAS требуется аккаунт Expo и инициализированный проект через eas init. После этого все сборки выполняются удалённо, а результат (ссылка на скачивание) появляется в терминале и в веб-интерфейсе Expo Dashboard.Преимущество EAS — изоляция от сложностей нативной разработки. Вы работаете только с JavaScript/TypeScript и конфигурацией, а Expo заботится о генерации нативных проектов, подписи и упаковке.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№31/сборка-через-expo.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №31/Сборка через Expo.md</guid><pubDate>Fri, 24 Apr 2026 11:46:45 GMT</pubDate></item><item><title><![CDATA[Изменение имени приложения]]></title><description><![CDATA[Имя приложения — это текст, который отображается под иконкой на главном экране устройства. Оно может отличаться от технического имени (slug) и должно быть удобочитаемым для пользователя.В нативной разработке iOS имя приложения задаётся в файле ios/MyApp/Info.plist через ключ CFBundleDisplayName. Однако при использовании Expo вы не редактируете этот файл вручную. Вместо этого Expo берёт значение из поля expo.name в app.json и автоматически подставляет его в Info.plist во время сборки.Аналогично, в Android имя определяется в android/app/src/main/AndroidManifest.xml через атрибут android:label у тега &lt;application&gt;. При сборке через Expo это значение тоже генерируется из expo.name.Если вы используете EAS Build (Expo Application Services), достаточно изменить поле name в app.json:{ "expo": { "name": "Новое Имя Приложения" }
}
При следующей сборке (eas build) Expo автоматически обновит имя в обоих нативных проектах — без необходимости открывать Xcode или Android Studio.Важно: после изменения имени требуется новая сборка. Простой перезапуск через expo start не обновит отображаемое имя в Expo Go, так как там используется кэшированная версия метаданных.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№31/изменение-имени-приложения.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №31/Изменение имени приложения.md</guid><pubDate>Fri, 24 Apr 2026 11:46:06 GMT</pubDate></item><item><title><![CDATA[Настройка метаданных]]></title><description><![CDATA[Метаданные — это данные о приложении, которые пользователь видит до установки: название, иконка, заставка, ориентация экрана и версия. В Expo-проектах они управляются централизованно через файл конфигурации: app.json или app.config.js.Пример минимальной конфигурации:{ "expo": { "name": "Моё Приложение", "slug": "my-app", "version": "1.0.0", "orientation": "portrait", "icon": "./assets/icon.png", "splash": { "image": "./assets/splash.png", "resizeMode": "contain", "backgroundColor": "#ffffff" }, "platforms": ["android", "ios"] }
}
Отображаемое имя приложения на устройстве. Может содержать пробелы и кириллицу (но для App Store рекомендуется латиница).Уникальный идентификатор приложения в системе Expo. Используется в URL для OTA-обновлений. Должен быть валидным URL-сегментом (только латиница, цифры, дефисы, подчёркивания).Версия приложения в формате x.y.z. Эта версия отображается в магазинах. При каждой новой публикации она должна увеличиваться.Фиксирует ориентацию экрана: "portrait", "landscape" или "default" (разрешает обе).Путь к изображению иконки (рекомендуется 1024×1024 px, PNG без прозрачности). Expo автоматически генерирует все необходимые размеры для iOS и Android.Настройка стартового экрана:
image — изображение заставки (часто с логотипом).
resizeMode — как изображение масштабируется ("contain", "cover").
backgroundColor — фон за изображением (обязателен для быстрой загрузки).
Ручная подготовка иконок под все разрешения — трудоёмкая задача. Expo делает это автоматически при сборке, если указан корректный icon. Для дополнительного контроля можно использовать сторонние инструменты:
expo-icon — CLI-утилита для генерации иконок.
Онлайн-генераторы (например, <a rel="noopener nofollow" class="external-link is-unresolved" href="https://appicon.co" target="_self">https://appicon.co</a>).
Важно: иконка должна быть квадратной, без альфа-канала и с достаточным запасом по краям (некоторые платформы обрезают углы).Стартовый экран показывается сразу при запуске, пока загружается JavaScript-бандл. Его цель — создать ощущение быстрого старта. Фон должен совпадать с фоном первого экрана приложения, чтобы переход был незаметным.Если не указать splash, Expo покажет чёрный экран, что выглядит как зависание. Поэтому даже простая заставка лучше, чем ничего.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№31/настройка-метаданных.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №31/Настройка метаданных.md</guid><pubDate>Fri, 24 Apr 2026 11:45:25 GMT</pubDate></item><item><title><![CDATA[Что такое сборка (build)]]></title><description><![CDATA[В процессе разработки React Native-приложение запускается в режиме отладки: оно подключено к Metro-серверу, получает JavaScript-код по сети и может обновляться «на лету». Такой режим удобен для разработки, но непригоден для распространения. Сборка (build) — это процесс преобразования исходного кода приложения в готовый нативный пакет, который можно установить на устройство без подключения к серверу разработчика.В режиме разработки:
Код загружается с локального компьютера через Wi-Fi.
Включены инструменты отладки: Remote Debugger, React DevTools, Fast Refresh.
Приложение зависит от Expo Go или собственного development-клиента.
В режиме выпуска (production build):
Весь JavaScript-код упакован в один бандл и встроен в приложение.
Отладочные инструменты отключены.
Приложение полностью автономно и может работать без интернета (если не требует API).
Команда expo start запускает только development-сервер. Она не создаёт установочный файл (.apk, .ipa). Приложение, запущенное через Expo Go, технически принадлежит Expo, а не вам — его нельзя опубликовать в App Store или Google Play. Для публикации требуется независимая сборка, где ваш код интегрирован в собственный нативный контейнер.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№31/что-такое-сборка-(build).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №31/Что такое сборка (build).md</guid><pubDate>Fri, 24 Apr 2026 11:44:51 GMT</pubDate></item><item><title><![CDATA[Тема №31. Сборка и подготовка приложения к публикации]]></title><description><![CDATA[В этой теме вы узнаете, как подготовить React Native-приложение к выпуску: настройка иконок, стартовых экранов, имён и версий. Поймёте, что такое билд-процесс и зачем он нужен — без глубокого погружения в Xcode или Android Studio.
<a data-href="Что такое сборка (build)" href="материалы/подтемы/секция-3.-react-native/тема-№31/что-такое-сборка-(build).html" class="internal-link" target="_self" rel="noopener nofollow">Что такое сборка (build)</a>
<br><a data-href="Настройка метаданных" href="материалы/подтемы/секция-3.-react-native/тема-№31/настройка-метаданных.html" class="internal-link" target="_self" rel="noopener nofollow">Настройка метаданных</a>
<br><a data-href="Изменение имени приложения" href="материалы/подтемы/секция-3.-react-native/тема-№31/изменение-имени-приложения.html" class="internal-link" target="_self" rel="noopener nofollow">Изменение имени приложения</a>
<br><a data-href="Сборка через Expo" href="материалы/подтемы/секция-3.-react-native/тема-№31/сборка-через-expo.html" class="internal-link" target="_self" rel="noopener nofollow">Сборка через Expo</a>
<br><a data-href="Что происходит при сборке" href="материалы/подтемы/секция-3.-react-native/тема-№31/что-происходит-при-сборке.html" class="internal-link" target="_self" rel="noopener nofollow">Что происходит при сборке</a>
(пусто)<br><a data-href="Дополнительные темы" href="дополнительные-темы.html" class="internal-link" target="_self" rel="noopener nofollow">Дополнительные темы</a>]]></description><link>лекции/секция-3.-react-native/тема-№31.-сборка-и-подготовка-приложения-к-публикации.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №31. Сборка и подготовка приложения к публикации.md</guid><pubDate>Fri, 24 Apr 2026 11:43:58 GMT</pubDate></item><item><title><![CDATA[Базовое тестирование]]></title><description><![CDATA[Тестирование в React Native помогает убедиться, что код работает так, как ожидается, и предотвращает появление регрессий при внесении изменений. На начальном этапе обучения достаточно понимать разницу между тестированием логики и тестированием интерфейса.
Unit-тесты (модульные) — проверяют отдельные функции или модули без зависимости от UI.
Интеграционные тесты — проверяют взаимодействие нескольких частей приложения.
E2E-тесты (end-to-end) — имитируют действия пользователя в готовом приложении.
Jest встроен в React Native по умолчанию. Он позволяет писать тесты для чистых функций, утилит, хуков (с ограничениями) и бизнес-логики.Пример unit-теста:// utils/formatPrice.ts
export const formatPrice = (price: number): string =&gt; { return `${price.toFixed(2)} ₽`;
}; // __tests__/formatPrice.test.ts
import { formatPrice } from '../utils/formatPrice'; test('formats price correctly', () =&gt; { expect(formatPrice(10)).toBe('10.00 ₽'); expect(formatPrice(9.99)).toBe('9.99 ₽');
});
Запуск тестов:npm test
# или
npx jest React Native Testing Library (RNTL) — библиотека для тестирования компонентов в изолированной среде. Позволяет рендерить компонент и проверять наличие текста, кнопок, состояние после взаимодействия.
Detox — фреймворк для E2E-тестов. Запускает реальное приложение на эмуляторе и выполняет сценарии (например, «нажать кнопку → проверить экран»).
Однако на начальном этапе не рекомендуется углубляться в UI-тесты. Они сложнее в настройке и поддержке, особенно без опыта.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№30/базовое-тестирование.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №30/Базовое тестирование.md</guid><pubDate>Fri, 24 Apr 2026 11:39:59 GMT</pubDate></item><item><title><![CDATA[Отладка стилей]]></title><description><![CDATA[Отладка стилей в React Native часто вызывает трудности у новичков, потому что визуальные проблемы (например, элемент не отображается или занимает неверный размер) могут быть следствием неправильной иерархии компонентов, ограничений родителя или особенностей движка layout (Flexbox).Основной инструмент для отладки стилей — Component Inspector, встроенный в Dev Menu:
Вызовите Dev Menu (Cmd+D на iOS, Cmd+M на Android).
Выберите Show Inspector.
Нажмите на любой элемент на экране.
После этого появится оверлей с информацией:
Имя компонента (например, View, Text, TouchableOpacity).
Применённые стили (в том числе унаследованные от темы или библиотеки).
Фактические размеры (ширина, высота) и позиция на экране.
Отступы: padding, margin, границы.
Это позволяет быстро понять, почему элемент выглядит не так, как ожидалось.
Родитель без размеров: если родительский View не имеет явной ширины или высоты, дочерние элементы могут не отобразиться.
Неправильное использование Flexbox: например, забытый flexDirection: 'row' при горизонтальном расположении.
Абсолютное позиционирование без координат: элемент может уйти за пределы экрана.
Цвет фона совпадает с фоном родителя: элемент есть, но его не видно.
overflow: 'hidden' у родителя: обрезает дочерние элементы, выходящие за границы.
Чтобы увидеть границы компонентов, можно временно добавить разные цвета фона:&lt;View style={{ backgroundColor: 'red', padding: 10 }}&gt; &lt;View style={{ backgroundColor: 'blue', height: 50 }} /&gt;
&lt;/View&gt;
Это помогает понять, как компоненты занимают пространство.Если подключён Flipper с React DevTools, можно просматривать стили компонента во вкладке React — при выборе элемента отображаются все применённые свойства из style.Отладка стилей требует системного подхода: начинайте с проверки иерархии, затем анализируйте размеры и направление flex-контейнеров. Инспектор значительно ускоряет этот процесс.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№30/отладка-стилей.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №30/Отладка стилей.md</guid><pubDate>Fri, 24 Apr 2026 11:38:57 GMT</pubDate></item><item><title><![CDATA[Логи и консоль]]></title><description><![CDATA[В React Native для вывода отладочной информации и диагностики ошибок используется стандартный API console, такой как console.log(), console.warn() и console.error(). Эти вызовы работают так же, как в браузере, но их отображение зависит от среды разработки.
При запуске через Metro (npx react-native run-android / run-ios или expo start) сообщения из console.log() выводятся в терминал, где запущен Metro-сервер.
Если подключён Flipper, все логи автоматически перехватываются и отображаются во вкладке Logs с возможностью фильтрации по уровню (info, warn, error).
В браузерном отладчике (устаревший режим через Dev Menu → Debug) логи появляются в консоли DevTools браузера. console.log('Сообщение') — обычное информационное сообщение. В терминале отображается без выделения.
console.warn('Предупреждение') — жёлтое уведомление на устройстве («Yellow Box»). Не останавливает выполнение, но указывает на потенциальную проблему (например, устаревшее API).
console.error('Ошибка') — красный экран ошибки («Red Box»). Прерывает выполнение и показывает стек вызовов. Используется при критических ошибках, таких как синтаксические ошибки или необработанные исключения.
Красный экран содержит:
Краткое описание ошибки.
Имя файла и номер строки, где произошла ошибка.
Стек вызовов — цепочка функций, приведших к ошибке.
Пример ошибки:TypeError: undefined is not an object (evaluating 'user.name')
Это означает, что переменная user равна undefined, и попытка прочитать свойство name завершилась неудачей.
Используйте console.log() умеренно — не оставляйте их в production-коде.
Для временного отключения всех логов можно переопределить console.log в production-сборке.
Жёлтые предупреждения стоит исправлять: они часто указывают на проблемы, которые в будущем могут стать ошибками.
Понимание логов и умение читать ошибки — ключевой навык при разработке мобильных приложений, особенно учитывая отсутствие привычной браузерной консоли.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№30/логи-и-консоль.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №30/Логи и консоль.md</guid><pubDate>Fri, 24 Apr 2026 11:37:55 GMT</pubDate></item><item><title><![CDATA[React Native Debugger и Flipper]]></title><description><![CDATA[Flipper — это официальный инструмент отладки для React Native, разработанный Meta. Он представляет собой десктопное приложение, которое подключается к запущенному приложению (на эмуляторе, симуляторе или физическом устройстве) и предоставляет централизованный интерфейс для анализа состояния, логов, сетевых запросов и структуры компонентов.
React DevTools — просмотр дерева компонентов, их пропсов и состояния.
Redux / Zustand / Context DevTools — если вы используете систему управления состоянием, Flipper может отображать историю изменений (при наличии соответствующего плагина).
Network Inspector — отслеживание всех HTTP(S)-запросов: метод, URL, заголовки, тело запроса и ответа.
Logs — сбор всех вызовов console.log(), console.warn(), console.error() в одном месте с возможностью фильтрации.
Crash Reporter — автоматическое уведомление об ошибках времени выполнения.
Device Logs — просмотр системных логов устройства (особенно полезно на Android). Скачайте Flipper с официального сайта: <a rel="noopener nofollow" class="external-link is-unresolved" href="https://fbflipper.com" target="_self">https://fbflipper.com</a>.
Запустите ваше React Native-приложение (npx react-native run-android или run-ios).
Откройте Flipper — он автоматически обнаружит подключённое приложение, если оно запущено в режиме разработки.
Убедитесь, что в проекте установлены необходимые зависимости: Для React DevTools: обычно встроены по умолчанию.
Для Redux DevTools: требуется установка @redux-devtools/flipper и настройка стора. Примечание: Expo Go не поддерживает Flipper напрямую. Для использования Flipper с Expo необходимо перейти на bare workflow или использовать EAS Build с кастомной нативной конфигурацией.
Ранее популярный инструмент React Native Debugger объединял React DevTools, Redux DevTools и Chrome DevTools в одном окне. Однако он больше не поддерживается и несовместим с новыми версиями React Native. Рекомендуется использовать Flipper как основной инструмент отладки.Flipper значительно упрощает диагностику проблем и позволяет глубже понимать поведение приложения без постоянного переключения между терминалом, браузером и эмулятором.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№30/react-native-debugger-и-flipper.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №30/React Native Debugger и Flipper.md</guid><pubDate>Fri, 24 Apr 2026 11:36:57 GMT</pubDate></item><item><title><![CDATA[Dev Menu (Меню разработчика)]]></title><description><![CDATA[Меню разработчика (Dev Menu) — это встроенное средство отладки в React Native, которое доступно только в режиме разработки. Оно позволяет быстро перезагружать приложение, включать инструменты отладки и просматривать структуру компонентов.В зависимости от платформы и среды запуска используется разный способ вызова:
iOS (симулятор): Cmd + D
Android (эмулятор): Cmd + M (на macOS) или Ctrl + M (на Windows/Linux)
Физическое устройство: потрясите устройство (Shake Gesture)
Если вы используете Expo Go, меню вызывается одинаково на обеих платформах — через потряхивание или сочетание клавиш в симуляторе/эмуляторе.
Reload — перезагружает JS-бандл без перезапуска нативного приложения.
Enable Fast Refresh — включает механизм быстрой перезагрузки, который сохраняет состояние компонентов при изменениях в коде (аналог Hot Reloading, но более надёжный).
Debug — открывает отладчик в браузере (устаревший способ; сейчас рекомендуется использовать Flipper).
Show Inspector — активирует инспектор компонентов: при нажатии на любой элемент на экране вы увидите его имя, пропсы и стили.
Toggle Performance Monitor — показывает метрики производительности: FPS, использование памяти, частоту ререндеров. Dev Menu недоступен в production-сборке (--variant release или через expo build).
Если меню не появляется, убедитесь, что приложение запущено в development-режиме (npx react-native run-android / run-ios или expo start).
После освоения Dev Menu вы сможете быстрее находить и исправлять ошибки в интерфейсе и логике приложения.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№30/dev-menu-(меню-разработчика).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №30/Dev Menu (Меню разработчика).md</guid><pubDate>Fri, 24 Apr 2026 11:30:20 GMT</pubDate></item><item><title><![CDATA[Тема №30. Тестирование и отладка в React Native]]></title><description><![CDATA[В этой теме вы познакомитесь с инструментами отладки и базовыми подходами к тестированию в React Native. Научитесь использовать Dev Menu, Flipper и консоль для поиска ошибок, а также поймёте, почему тестирование важно даже на этапе ознакомления.
<a data-href="Dev Menu (Меню разработчика)" href="материалы/подтемы/секция-3.-react-native/тема-№30/dev-menu-(меню-разработчика).html" class="internal-link" target="_self" rel="noopener nofollow">Dev Menu (Меню разработчика)</a>
<br><a data-href="React Native Debugger и Flipper" href="материалы/подтемы/секция-3.-react-native/тема-№30/react-native-debugger-и-flipper.html" class="internal-link" target="_self" rel="noopener nofollow">React Native Debugger и Flipper</a>
<br><a data-href="Логи и консоль" href="материалы/подтемы/секция-3.-react-native/тема-№30/логи-и-консоль.html" class="internal-link" target="_self" rel="noopener nofollow">Логи и консоль</a>
<br><a data-href="Отладка стилей" href="материалы/подтемы/секция-3.-react-native/тема-№30/отладка-стилей.html" class="internal-link" target="_self" rel="noopener nofollow">Отладка стилей</a>
<br><a data-href="Базовое тестирование" href="материалы/подтемы/секция-3.-react-native/тема-№30/базовое-тестирование.html" class="internal-link" target="_self" rel="noopener nofollow">Базовое тестирование</a>
(пусто)<br><a data-href="Тема №31. Сборка и подготовка приложения к публикации" href="лекции/секция-3.-react-native/тема-№31.-сборка-и-подготовка-приложения-к-публикации.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №31. Сборка и подготовка приложения к публикации</a>]]></description><link>лекции/секция-3.-react-native/тема-№30.-тестирование-и-отладка-в-react-native.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №30. Тестирование и отладка в React Native.md</guid><pubDate>Fri, 24 Apr 2026 11:29:14 GMT</pubDate></item><item><title><![CDATA[Использование Axios в React Native]]></title><description><![CDATA[Axios — это популярная библиотека для выполнения HTTP-запросов. В React Native её можно использовать точно так же, как и в обычном JavaScript-приложении. Хотя встроенный fetch часто достаточен, Axios предоставляет ряд удобств, особенно в крупных проектах.Чтобы начать использовать Axios, установите его через npm:npm install axios
После этого импортируйте в компонент:import axios from 'axios'; Автоматическое преобразование JSON
При использовании Axios ответ уже содержит распарсенные данные в свойстве data. Не нужно вызывать .json(). Выбрасывание ошибок при HTTP-ошибках
Если сервер возвращает статус 4xx или 5xx, Axios автоматически отклоняет промис. Это упрощает обработку ошибок — не нужно проверять response.ok. Поддержка таймаутов
Можно задать максимальное время ожидания ответа:
axios.get('https://api.example.com/data', { timeout: 5000 }); Интерцепторы (перехватчики)
Позволяют централизованно обрабатывать все запросы и ответы — например, добавлять токен авторизации или логировать ошибки. const fetchData = async () =&gt; { try { const response = await axios.get&lt;User[]&gt;('https://jsonplaceholder.typicode.com/users'); const users = response.data; // уже типизировано и распарсено console.log(users); } catch (error) { if (axios.isAxiosError(error)) { if (error.code === 'ECONNABORTED') { console.error('Таймаут запроса'); } else if (error.response) { console.error('Ошибка сервера:', error.response.status); } else if (error.request) { console.error('Нет ответа от сервера — возможно, нет интернета'); } } else { console.error('Неизвестная ошибка:', error); } }
};
Здесь используется встроенная проверка axios.isAxiosError, чтобы безопасно работать с ошибками.
В проектах с множеством API-запросов.
Когда нужна централизованная обработка авторизации или логирования.
Если важна читаемость кода и меньше шаблонного кода для обработки ошибок.
В небольших приложениях fetch часто предпочтительнее, так как не увеличивает размер бандла и не требует зависимостей.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№29/использование-axios-в-react-native.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №29/Использование Axios в React Native.md</guid><pubDate>Fri, 24 Apr 2026 11:28:21 GMT</pubDate></item><item><title><![CDATA[Обработка CORS и сетевых ошибок]]></title><description><![CDATA[В React Native поведение при работе с сетевыми запросами отличается от веб-браузеров, особенно в части CORS (Cross-Origin Resource Sharing).CORS — это механизм безопасности браузера, который блокирует запросы к доменам, отличным от того, с которого загружена веб-страница. Однако в React Native CORS не применяется, потому что приложение не работает внутри браузерного контекста. Вместо этого запросы выполняются через нативные сетевые стеки: NSURLSession на iOS и OkHttp на Android. Это означает, что вы можете свободно отправлять запросы на любой сервер без необходимости настройки прокси или изменения заголовков CORS на бэкенде.Тем не менее, остаются другие типы ошибок, которые необходимо обрабатывать:Сетевые ошибки возникают, когда устройство не может установить соединение с сервером. Примеры:
Отсутствует интернет-соединение
Сервер недоступен
Неверный URL или DNS-ошибка
Такие ошибки перехватываются в блоке catch при использовании fetch:try { const response = await fetch('https://api.example.com/data'); // ...
} catch (error) { // Сюда попадаем только при сетевой ошибке console.error('Нет подключения к сети:', error);
}
Важно: если сервер ответил (даже статусом 500), это не считается сетевой ошибкой — промис не будет отклонён. Поэтому для полной обработки ошибок нужно комбинировать catch и проверку response.ok.Даже при успешном соединении сервер может вернуть ошибку (4xx, 5xx). Чтобы её обнаружить, проверяйте свойство ok:const response = await fetch('https://api.example.com/data');
if (!response.ok) { throw new Error(`Ошибка сервера: ${response.status}`);
}
Полный пример безопасного запроса:const loadData = async () =&gt; { try { const response = await fetch('https://api.example.com/data'); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } const data = await response.json(); return data; } catch (error) { if (error instanceof TypeError) { // Ошибка сети (например, "Network request failed") throw new Error('Нет подключения к интернету'); } else { // Ошибка от сервера или другая логическая ошибка throw error; } }
};
В пользовательском интерфейсе такую ошибку можно отобразить как понятное сообщение: «Проверьте подключение к интернету» или «Сервер временно недоступен».Хотя CORS не мешает запросам в React Native, сервер всё равно должен корректно обрабатывать входящие запросы. Например, если API требует определённые заголовки (Authorization, Content-Type), их нужно указывать явно в настройках fetch.Эта особенность упрощает разработку, но не отменяет необходимость надёжной обработки всех возможных сценариев сбоя.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№29/обработка-cors-и-сетевых-ошибок.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №29/Обработка CORS и сетевых ошибок.md</guid><pubDate>Fri, 24 Apr 2026 11:26:47 GMT</pubDate></item><item><title><![CDATA[Запросы через fetch в React Native]]></title><description><![CDATA[В React Native для выполнения HTTP-запросов к внешним API используется встроенный глобальный метод fetch. Он полностью совместим с тем, что используется в современных браузерах, и не требует установки дополнительных библиотек.Метод fetch возвращает промис, который разрешается в объект Response. Чтобы получить тело ответа в виде JSON, нужно вызвать метод .json() у этого объекта — он также возвращает промис.Простейший пример запроса к публичному API:const fetchData = async () =&gt; { try { const response = await fetch('https://jsonplaceholder.typicode.com/users'); const users = await response.json(); console.log(users); } catch (error) { console.error('Ошибка сети:', error); }
};
Важно помнить два ключевых момента:
fetch не выбрасывает ошибку при HTTP-статусах вроде 404 или 500. Он считает их успешными ответами, потому что соединение установлено и сервер ответил. Поэтому нужно дополнительно проверять свойство response.ok (оно равно true, если статус в диапазоне 200–299).
Ошибки действительно возникают только при проблемах с сетью: отсутствие интернета, недоступность хоста и т.п.
Пример с проверкой статуса:const response = await fetch('https://api.example.com/data');
if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
Такой подход позволяет надёжно обрабатывать как сетевые, так и логические ошибки на стороне сервера.Для отправки данных (например, при создании ресурса) используется второй аргумент fetch — объект с настройками запроса:const createUser = async (userData: { name: string; email: string }) =&gt; { const response = await fetch('https://api.example.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(userData), }); if (!response.ok) { throw new Error('Не удалось создать пользователя'); } return await response.json();
};
Этот шаблон применим ко всем типам запросов: GET, POST, PUT, PATCH, DELETE.В отличие от веба, в React Native:
Нет политики CORS — приложение может делать запросы на любой домен без ограничений.
Все запросы выполняются через нативные модули (NSURLSession на iOS, OkHttp на Android), поэтому работают даже при отключённом Wi-Fi, если есть мобильный интернет.
Это упрощает интеграцию с бэкендом по сравнению с веб-разработкой.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№29/запросы-через-fetch-в-react-native.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №29/Запросы через fetch в React Native.md</guid><pubDate>Fri, 24 Apr 2026 11:25:23 GMT</pubDate></item><item><title><![CDATA[Когда что использовать]]></title><description><![CDATA[Выбор способа локального хранения в React Native зависит от типа и объёма данных, а также от сценария использования.AsyncStorage применяется, когда нужно сохранить небольшие структурированные данные в формате «ключ-значение». Типичные примеры:
Токен авторизации
Выбранная тема интерфейса («светлая»/«тёмная»)
Флаг завершённого онбординга
Последнее обновление данных
Настройки пользователя (язык, единицы измерения)
Преимущества: простота API, быстрый доступ, автоматическая интеграция с нативными системами хранения. Недостатки: ограничение по объёму (~6 МБ), хранение только строк, отсутствие запросов.Файловая система (react-native-fs) используется для работы с бинарными или объёмными данными, которые неудобно или невозможно представить как строку JSON. Примеры:
Кэширование изображений (аватары, фото из ленты)
Сохранение загруженных документов (PDF, CSV)
Экспорт данных приложения в файл
Временные файлы для офлайн-обработки
Преимущества: прямой доступ к файлам, поддержка потоковой записи, работа с большими объёмами. Недостатки: сложность управления путями, необходимость контроля за очисткой кэша, отсутствие структурированного поиска.Базы данных (SQLite, Realm, WatermelonDB) — это следующий уровень, который применяется, когда:
Есть множество связанных записей (например, список задач с подзадачами)
Требуются фильтрация, сортировка, поиск по полям
Необходима поддержка транзакций
Данные регулярно обновляются и синхронизируются с сервером
Эти решения выходят за рамки текущей темы, но важно понимать, что AsyncStorage и файловая система — это не замена базе данных, а инструменты для конкретных задач: конфигурации и медиаконтента соответственно.Правило выбора:
Если данные можно выразить одной строкой или небольшим JSON-объектом — используйте AsyncStorage.
Если данные — это файл (изображение, документ, аудио) — используйте react-native-fs.
Если у вас таблицы, связи и запросы — рассматривайте SQLite или другие локальные БД.
]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№28/когда-что-использовать.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №28/Когда что использовать.md</guid><pubDate>Fri, 24 Apr 2026 11:18:22 GMT</pubDate></item><item><title><![CDATA[Работа с файлами]]></title><description><![CDATA[Для работы с файлами в React Native используется сторонняя библиотека react-native-fs, так как стандартный JavaScript не предоставляет прямого доступа к файловой системе устройства. Эта библиотека даёт возможность читать, записывать, копировать, удалять файлы и управлять директориями на уровне нативной файловой системы iOS и Android.Установка:npm install react-native-fs
После установки (и, при необходимости, <a data-tooltip-position="top" aria-label="Линковка нативных библиотек" data-href="Линковка нативных библиотек" href="материалы/подтемы/секция-3.-react-native/тема-№28/линковка-нативных-библиотек.html" class="internal-link" target="_self" rel="noopener nofollow">линковки</a> — хотя в новых версиях React Native это обычно не требуется) можно использовать глобальный объект RNFS.Основные возможности:
Чтение и запись текстовых и бинарных файлов.
Работа с предопределёнными путями: DocumentDirectoryPath, CachesDirectoryPath, MainBundlePath и др.
Скачивание файлов из сети напрямую на диск.
Проверка существования файла, получение его размера и метаданных.
Пример сохранения изображения по URI в кэш:import RNFS from 'react-native-fs'; const saveImageToCache = async (uri: string, filename: string): Promise&lt;string&gt; =&gt; { const filePath = `${RNFS.CachesDirectoryPath}/${filename}`; // Копируем файл из временного URI (например, после выбора через ImagePicker) await RNFS.copyFile(uri, filePath); return filePath; // возвращаем локальный путь для последующего использования
};
Пример чтения текстового файла:const readFileContent = async (filename: string): Promise&lt;string | null&gt; =&gt; { const filePath = `${RNFS.DocumentDirectoryPath}/${filename}`; try { const content = await RNFS.readFile(filePath, 'utf8'); return content; } catch (error) { console.error('Failed to read file', error); return null; }
};
Важно понимать, что разные директории имеют разное поведение:
CachesDirectoryPath — данные могут быть удалены системой при нехватке места (подходит для временных файлов, кэша).
DocumentDirectoryPath — данные сохраняются между запусками и резервным копированием (подходит для пользовательских документов).
Библиотека react-native-fs работает с нативными путями, поэтому нельзя использовать её для прямого отображения файлов в компонентах без преобразования URI (например, в Image нужно использовать file:// + путь).Этот инструмент особенно полезен для офлайн-кэширования медиа, экспорта данных в CSV/PDF или сохранения аватаров пользователя на устройстве.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№28/работа-с-файлами.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №28/Работа с файлами.md</guid><pubDate>Fri, 24 Apr 2026 11:15:11 GMT</pubDate></item><item><title><![CDATA[Линковка нативных библиотек]]></title><description><![CDATA[В React Native начиная с версии 0.60+ автоматическая линковка (autolinking) включена по умолчанию. Это означает, что для большинства нативных библиотек — включая react-native-fs и @react-native-async-storage/async-storage — ручная линковка не требуется.Раньше (в версиях до 0.60) после установки пакета через npm нужно было выполнить:npx react-native link имя-пакета
Эта команда автоматически добавляла нативные зависимости в проекты Android и iOS. Однако из-за частых ошибок и сложности поддержки сообщество перешло на autolinking.Сейчас достаточно:
Установить пакет через npm install.
Для iOS — перейти в папку ios и выполнить pod install, чтобы обновить зависимости CocoaPods.
Пересобрать приложение: npx react-native run-android или npx react-native run-ios.
Исключения (редкие): если библиотека не поддерживает autolinking (обычно очень старые или кастомные модули), в её документации будет указано, что требуется ручная настройка нативных файлов. В подавляющем большинстве случаев этого не нужно.Таким образом, при работе с современными библиотеками в курсе линковка не выполняется вручную — достаточно установки и пересборки проекта.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№28/линковка-нативных-библиотек.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №28/Линковка нативных библиотек.md</guid><pubDate>Fri, 24 Apr 2026 11:14:59 GMT</pubDate></item><item><title><![CDATA[Типизация AsyncStorage в TypeScript]]></title><description><![CDATA[При использовании AsyncStorage в TypeScript важно правильно типизировать входные и выходные данные, так как сама библиотека оперирует только строками. Чтобы избежать ошибок и повысить читаемость кода, рекомендуется создавать отдельные функции-обёртки с явной типизацией.Так как AsyncStorage хранит только строки, любые объекты или примитивы (числа, булевы значения) должны быть преобразованы перед сохранением и восстановлены при чтении. Это делает ручную сериализацию/десериализацию обязательной.Пример типизированного сервиса для работы с токеном авторизации:import AsyncStorage from '@react-native-async-storage/async-storage'; const TOKEN_KEY = 'auth_token'; export const saveToken = async (token: string): Promise&lt;void&gt; =&gt; { try { await AsyncStorage.setItem(TOKEN_KEY, token); } catch (error) { console.error('Failed to save token', error); throw error; }
}; export const getToken = async (): Promise&lt;string | null&gt; =&gt; { try { const token = await AsyncStorage.getItem(TOKEN_KEY); return token; // возвращается string | null } catch (error) { console.error('Failed to get token', error); return null; }
}; export const removeToken = async (): Promise&lt;void&gt; =&gt; { try { await AsyncStorage.removeItem(TOKEN_KEY); } catch (error) { console.error('Failed to remove token', error); throw error; }
};
Для хранения структурированных данных (например, профиля пользователя) можно обобщить подход:export const saveObject = async &lt;T&gt;(key: string, value: T): Promise&lt;void&gt; =&gt; { try { const jsonValue = JSON.stringify(value); await AsyncStorage.setItem(key, jsonValue); } catch (error) { console.error(`Failed to save object for key: ${key}`, error); throw error; }
}; export const getObject = async &lt;T&gt;(key: string): Promise&lt;T | null&gt; =&gt; { try { const jsonValue = await AsyncStorage.getItem(key); return jsonValue != null ? JSON.parse(jsonValue) : null; } catch (error) { console.error(`Failed to parse object for key: ${key}`, error); return null; }
};
Обратите внимание: ошибки при работе с AsyncStorage обычно связаны с нехваткой памяти, повреждением данных или превышением лимита хранилища — а не с сетевыми проблемами, так как операции происходят локально. Поэтому обработка ошибок через try/catch обязательна, даже если сеть не участвует.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№28/типизация-asyncstorage-в-typescript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №28/Типизация AsyncStorage в TypeScript.md</guid><pubDate>Fri, 24 Apr 2026 11:12:18 GMT</pubDate></item><item><title><![CDATA[AsyncStorage]]></title><description><![CDATA[AsyncStorage — это асинхронное, неблокирующее хранилище данных «ключ-значение», встроенное в экосистему React Native через отдельный пакет. Оно предназначено для хранения небольших объёмов данных на устройстве пользователя между сессиями приложения. В отличие от браузерного localStorage, AsyncStorage работает на уровне нативного кода (через iOS UserDefaults и Android SharedPreferences), но предоставляет простой JavaScript-интерфейс.Для использования необходимо установить пакет:npm install @react-native-async-storage/async-storage
После установки основные операции выполняются через три метода:
setItem(key: string, value: string) — сохраняет строковое значение по указанному ключу.
getItem(key: string) — возвращает строку, сохранённую по ключу, или null, если ключ не найден.
removeItem(key: string) — удаляет значение по ключу.
Важно: AsyncStorage принимает только строки. Чтобы сохранить объект, его нужно сериализовать с помощью JSON.stringify(), а при чтении — десериализовать через JSON.parse().Пример сохранения и чтения настроек темы:import AsyncStorage from '@react-native-async-storage/async-storage'; const saveTheme = async (theme: 'light' | 'dark') =&gt; { await AsyncStorage.setItem('app_theme', theme);
}; const loadTheme = async (): Promise&lt;'light' | 'dark' | null&gt; =&gt; { const theme = await AsyncStorage.getItem('app_theme'); return theme as 'light' | 'dark' | null;
};
Ограничения AsyncStorage:
Максимальный объём данных — около 6 МБ (зависит от платформы).
Нет поддержки запросов, индексов или транзакций.
Не подходит для хранения чувствительных данных (например, паролей) без дополнительного шифрования.
Несмотря на ограничения, AsyncStorage идеально подходит для хранения токенов авторизации, пользовательских предпочтений, флагов онбординга и других лёгких данных, необходимых для работы приложения в офлайн-режиме.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№28/asyncstorage.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №28/AsyncStorage.md</guid><pubDate>Fri, 24 Apr 2026 11:10:57 GMT</pubDate></item><item><title><![CDATA[Особенность локального хранилища в React Native]]></title><description><![CDATA[React Native не работает в браузере, а значит — недоступны привычные веб-API, такие как localStorage, sessionStorage или IndexedDB. Эти инструменты реализованы в среде браузера и привязаны к DOM. В мобильном приложении DOM отсутствует, поэтому для хранения данных на устройстве нужно использовать нативные решения, предоставляемые операционной системой (iOS/Android) через специальные библиотеки.Это означает, что даже простая задача — сохранить тему интерфейса или токен авторизации — требует другого подхода. К счастью, экосистема React Native предлагает проверенные инструменты: AsyncStorage для простых пар «ключ-значение» и react-native-fs для полноценной работы с файловой системой устройства.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№28/особенность-локального-хранилища-в-react-native.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №28/Особенность локального хранилища в React Native.md</guid><pubDate>Fri, 24 Apr 2026 11:09:55 GMT</pubDate></item><item><title><![CDATA[Модальные экраны]]></title><description><![CDATA[Модальные экраны в React Navigation — это способ отображения экрана как временного, второстепенного интерфейса, который не является частью основного потока навигации. Такие экраны часто используются для форм, подтверждений или настроек и визуально отличаются от обычных переходов.Для включения модального режима используется опция presentation: 'modal'. Её можно применить либо ко всему стеку, либо к отдельному экрану.Применение ко всему стеку (обычно для отдельного модального навигатора):&lt;Stack.Navigator screenOptions={{ presentation: 'modal' }}&gt; &lt;Stack.Screen name="CreatePost" component={CreatePostScreen} /&gt;
&lt;/Stack.Navigator&gt;
Применение к одному экрану:&lt;Stack.Screen name="EditProfile" component={EditProfileScreen} options={{ presentation: 'modal' }}
/&gt; На iOS модальный экран появляется снизу как лист (sheet) и может быть закрыт свайпом вниз.
На Android модальное окно выглядит как обычный экран, но с затемнённым фоном и анимацией входа/выхода, отличающейся от стандартной.
Несмотря на визуальные отличия, модальный экран управляется теми же методами:
navigation.navigate('EditProfile') — открытие.
navigation.goBack() или navigation.dismiss() — закрытие (на iOS dismiss() предпочтительнее для модальных экранов). Создание или редактирование записи.
Подтверждение удаления или другого критического действия.
Настройки, не требующие постоянного доступа из основного интерфейса.
Модальные экраны следует использовать умеренно — только для задач, которые логически отделены от основного пользовательского потока.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/модальные-экраны.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Модальные экраны.md</guid><pubDate>Fri, 24 Apr 2026 11:06:30 GMT</pubDate></item><item><title><![CDATA[Навигация между экранами]]></title><description><![CDATA[Объект navigation автоматически передаётся каждому компоненту-экрану в React Navigation. С его помощью можно управлять переходами и изменять состояние навигационного стека.navigation.navigate(name, params?) — выполняет переход на экран с указанным именем. Если такой экран уже есть в стеке, навигация перейдёт к нему без создания дубликата. Вторым аргументом можно передать параметры:navigation.navigate('Profile', { userId: 42 });
navigation.goBack() — возвращает пользователя на предыдущий экран. Эквивалентно нажатию системной кнопки «Назад» или жесту свайпа (на iOS).navigation.replace(name, params?) — заменяет текущий экран на новый. Пользователь не сможет вернуться назад на заменённый экран, так как он удаляется из стека:navigation.replace('Login');
navigation.popToTop() — возвращает пользователя к первому экрану в стеке, удаляя все промежуточные экраны. Полезно, например, после завершения многошагового процесса.Эти методы работают в пределах одного навигатора (например, одного Stack.Navigator). Для переходов между разными навигаторами (например, из стека во вкладку) требуется дополнительная настройка, которая выходит за рамки базовой навигации.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/навигация-между-экранами.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Навигация между экранами.md</guid><pubDate>Fri, 24 Apr 2026 11:05:58 GMT</pubDate></item><item><title><![CDATA[Тема №27. Навигация в React Native]]></title><description><![CDATA[В этой теме вы изучите навигацию между экранами в React Native с помощью библиотеки React Navigation. Поймёте, как организовать многократную навигацию, передавать параметры между экранами и настраивать заголовки. Это ключевой механизм для построения полноценного мобильного приложения.
<a data-href="Что такое React Navigation" href="материалы/подтемы/секция-3.-react-native/тема-№27/что-такое-react-navigation.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое React Navigation</a>
<br><a data-href="Типы навигаторов" href="материалы/подтемы/секция-3.-react-native/тема-№27/типы-навигаторов.html" class="internal-link" target="_self" rel="noopener nofollow">Типы навигаторов</a>
<br><a data-href="Настройка Stack Navigator" href="материалы/подтемы/секция-3.-react-native/тема-№27/настройка-stack-navigator.html" class="internal-link" target="_self" rel="noopener nofollow">Настройка Stack Navigator</a>
<br><a data-href="Заголовки и кнопки" href="материалы/подтемы/секция-3.-react-native/тема-№27/заголовки-и-кнопки.html" class="internal-link" target="_self" rel="noopener nofollow">Заголовки и кнопки</a>
<br><a data-href="Навигация между экранами" href="материалы/подтемы/секция-3.-react-native/тема-№27/навигация-между-экранами.html" class="internal-link" target="_self" rel="noopener nofollow">Навигация между экранами</a>
<br><a data-href="Модальные экраны" href="материалы/подтемы/секция-3.-react-native/тема-№27/модальные-экраны.html" class="internal-link" target="_self" rel="noopener nofollow">Модальные экраны</a>
(пусто)<br><a data-href="Тема №28. Работа с локальным хранилищем и файлами" href="лекции/секция-3.-react-native/тема-№28.-работа-с-локальным-хранилищем-и-файлами.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №28. Работа с локальным хранилищем и файлами</a>]]></description><link>лекции/секция-3.-react-native/тема-№27.-навигация-в-react-native.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №27. Навигация в React Native.md</guid><pubDate>Fri, 24 Apr 2026 11:05:21 GMT</pubDate></item><item><title><![CDATA[Заголовки и кнопки]]></title><description><![CDATA[Заголовки и кнопки в React Navigation настраиваются через свойство options, которое можно передать компоненту &lt;Stack.Screen&gt;. Это позволяет гибко управлять внешним видом верхней панели навигации для каждого экрана отдельно.По умолчанию заголовок экрана совпадает с его name, но его можно изменить:&lt;Stack.Screen name="Profile" component={ProfileScreen} options={{ title: 'Мой профиль' }}
/&gt;
Также можно использовать функцию, если нужно динамически определить заголовок на основе параметров:options={({ route }) =&gt; ({ title: route.params?.userName || 'Профиль' })}
Кнопки в правой или левой части заголовка задаются через headerRight и headerLeft. Эти свойства принимают функцию, возвращающую React-элемент:&lt;Stack.Screen name="Profile" component={ProfileScreen} options={{ headerRight: () =&gt; ( &lt;Button onPress={() =&gt; alert('Редактировать')} title="Edit" color="#007AFF" /&gt; ), }}
/&gt;
Внутри функции можно использовать замыкание для доступа к пропсам экрана, если options определены как функция:options={({ navigation, route }) =&gt; ({ headerRight: () =&gt; ( &lt;Button onPress={() =&gt; navigation.navigate('EditProfile', { userId: route.params?.userId })} title="Edit" /&gt; ),
})}
Это позволяет не только отображать кнопки, но и выполнять навигационные действия или другие операции при их нажатии.Все изменения применяются только к конкретному экрану и не влияют на другие экраны в стеке.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/заголовки-и-кнопки.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Заголовки и кнопки.md</guid><pubDate>Fri, 24 Apr 2026 11:02:19 GMT</pubDate></item><item><title><![CDATA[Настройка Stack Navigator]]></title><description><![CDATA[Настройка Stack.Navigator — это первый практический шаг в реализации навигации в React Native. Она позволяет определить, какие экраны доступны в стеке и как они связаны между собой.Для начала необходимо импортировать необходимые функции из библиотеки:import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
Затем создаётся <a data-tooltip-position="top" aria-label="Фабричные функции" data-href="Фабричные функции" href="материалы/подтемы/секция-3.-react-native/тема-№27/фабричные-функции.html" class="internal-link" target="_self" rel="noopener nofollow">фабрика</a> навигатора с помощью createStackNavigator(). Эта функция возвращает объект с компонентами Navigator и Screen, которые используются для построения структуры:const Stack = createStackNavigator();
Далее внутри корневого компонента приложения (обычно обёрнутого в NavigationContainer) определяются экраны:function App() { return ( &lt;NavigationContainer&gt; &lt;Stack.Navigator&gt; &lt;Stack.Screen name="Home" component={HomeScreen} /&gt; &lt;Stack.Screen name="Profile" component={ProfileScreen} /&gt; &lt;/Stack.Navigator&gt; &lt;/NavigationContainer&gt; );
}
Каждый экран задаётся через &lt;Stack.Screen&gt;, где:
name — уникальное имя маршрута, используемое при навигации.
component — React-компонент, который будет отображаться на этом экране.
При переходе на другой экран можно передать данные:// На экране Home
navigation.navigate('Profile', { userId: 123, userName: 'Анна' });
Здесь navigation — объект, автоматически передаваемый в каждый экран через пропсы.Внутри компонента ProfileScreen параметры доступны через пропс route:function ProfileScreen({ route }) { const { userId, userName } = route.params || {}; return &lt;Text&gt;Профиль: {userName} (ID: {userId})&lt;/Text&gt;;
}
Если параметры не переданы, route.params будет undefined, поэтому рекомендуется использовать деструктуризацию с fallback-значением (|| {}), чтобы избежать ошибок.Эти базовые механизмы позволяют строить гибкую и понятную навигацию между экранами с передачей контекста.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/настройка-stack-navigator.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Настройка Stack Navigator.md</guid><pubDate>Fri, 24 Apr 2026 11:01:09 GMT</pubDate></item><item><title><![CDATA[Фабричные функции]]></title><description><![CDATA[Фабрика — это функция, которая создаёт и возвращает другой объект или набор связанных объектов. В контексте React Navigation фабрика используется для генерации конкретного типа навигатора с его внутренними компонентами.В случае createStackNavigator() эта функция является фабрикой: она не отображает UI напрямую, а возвращает объект, содержащий два компонента — Navigator и Screen. Эти компоненты уже используются в JSX для построения структуры навигации.Практическое применение:
Вы вызываете фабрику один раз: const Stack = createStackNavigator();
Полученный объект Stack содержит готовые к использованию компоненты: &lt;Stack.Navigator&gt; и &lt;Stack.Screen&gt;.
Это позволяет изолировать конфигурацию навигатора и повторно использовать один и тот же тип навигации в разных частях приложения.
Такой подход обеспечивает чистоту кода, типобезопасность (особенно в TypeScript) и декларативный стиль описания маршрутов.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/фабричные-функции.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Фабричные функции.md</guid><pubDate>Fri, 24 Apr 2026 11:00:52 GMT</pubDate></item><item><title><![CDATA[Типы навигаторов]]></title><description><![CDATA[В React Navigation существует несколько типов навигаторов, каждый из которых решает определённую задачу по организации переходов между экранами. Выбор типа зависит от структуры приложения и ожидаемого пользовательского опыта.Stack.Navigator реализует навигацию по принципу стека: каждый новый экран помещается поверх предыдущего, как веб-страницы в браузере. Пользователь может вернуться назад с помощью кнопки «Назад» или жеста (на iOS). Это наиболее часто используемый тип навигатора для приложений с иерархической структурой.Пример: переход с экрана списка товаров на экран детального просмотра.Tab.Navigator создаёт нижнюю панель с вкладками (на iOS) или верхнюю/нижнюю панель (на Android, в зависимости от конфигурации). Каждая вкладка представляет собой независимый экран или даже отдельный стек навигации. Подходит для приложений с несколькими основными разделами одинаковой важности.Пример: вкладки «Главная», «Поиск», «Профиль».Drawer.Navigator открывает боковое меню («шторку») при свайпе с края экрана или нажатии на иконку меню. Обычно используется для второстепенных разделов или настроек. Может содержать список пунктов, каждый из которых ведёт на свой экран.Пример: меню с пунктами «Настройки», «Помощь», «Выход».Эти три типа можно комбинировать. Например, каждая вкладка в Tab.Navigator может содержать свой собственный Stack.Navigator, что позволяет сохранять историю переходов внутри каждого раздела.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/типы-навигаторов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Типы навигаторов.md</guid><pubDate>Fri, 24 Apr 2026 10:58:15 GMT</pubDate></item><item><title><![CDATA[Что такое React Navigation]]></title><description><![CDATA[React Navigation — это официальная библиотека для организации навигации в приложениях на React Native. Она позволяет легко управлять переходами между экранами, передавать данные и настраивать внешний вид навигационных элементов (например, заголовков или кнопок). Библиотека построена на основе нативных компонентов, что обеспечивает высокую производительность и естественное поведение на iOS и Android.Для начала работы с React Navigation необходимо установить основные пакеты:npm install @react-navigation/native @react-navigation/stack
Также требуются дополнительные зависимости, обеспечивающие корректную работу на обеих платформах:npm install react-native-screens react-native-safe-area-context
После установки необходимо выполнить дополнительные шаги в зависимости от платформы:
Для iOS: запустить npx pod-install внутри папки ios.
Для Android: убедиться, что в MainActivity.java правильно настроен MainActivity.
Эти зависимости обеспечивают:
react-native-screens — оптимизацию рендеринга навигационных экранов за счёт нативных контроллеров.
react-native-safe-area-context — корректное отображение контента в безопасных зонах (например, вокруг выреза на iPhone).
React Navigation не является частью ядра React Native, но рекомендован сообществом и поддерживается активно. Он предоставляет декларативный API, который интуитивно понятен разработчикам, знакомым с React.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№27/что-такое-react-navigation.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №27/Что такое React Navigation.md</guid><pubDate>Fri, 24 Apr 2026 10:55:51 GMT</pubDate></item><item><title><![CDATA[Рекомендации по управлению состоянием]]></title><description><![CDATA[Эффективное управление состоянием — ключ к поддерживаемому и читаемому коду в React Native. Ниже приведены основные рекомендации, которые помогут избежать распространённых ошибок и упростят развитие приложения.Если значение можно получить из других частей состояния или пропсов, не сохраняйте его отдельно. Это снижает риск рассинхронизации и уменьшает объём данных.Неправильно:const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState('');
const [fullName, setFullName] = useState(''); // избыточно // При каждом изменении имени нужно обновлять fullName
Правильно:const [firstName, setFirstName] = useState('');
const [lastName, setLastName] = useState(''); const fullName = `${firstName} ${lastName}`; // вычисляется при рендере Локальное состояние (useState, useReducer) — для данных, нужных только внутри одного компонента или экрана (например, текст в поле ввода, открытый аккордеон).
Глобальное состояние (useContext или внешние библиотеки) — для данных, используемых во многих частях приложения (тема, авторизация, настройки).
Не стоит «поднимать» состояние выше, чем это действительно необходимо. Излишнее использование контекста усложняет отладку и вызывает лишние перерисовки.Контекст лучше использовать для передачи данных, а не поведения. Однако если вы всё же передаёте функции управления состоянием (например, toggleTheme), обязательно мемоизируйте их с помощью useCallback. Иначе каждый рендер провайдера будет создавать новую функцию, что приведёт к ненужным обновлениям всех потребителей контекста.Пример правильного подхода:const [darkMode, setDarkMode] = useState(false); const toggleTheme = useCallback(() =&gt; { setDarkMode(prev =&gt; !prev);
}, []); &lt;ThemeContext.Provider value={{ darkMode, toggleTheme }}&gt;
Объединяйте связанные значения в один объект состояния, если они обновляются вместе:// Лучше так
const [formState, setFormState] = useState({ email: '', password: '' }); // Чем так
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
Это особенно актуально при использовании useReducer, где структура состояния уже централизована.Даже если сейчас состояние простое, подумайте, как оно может измениться в будущем. Например, вместо булева флага isLoading иногда полезнее использовать строковый статус ('idle' | 'loading' | 'success' | 'error'), если возможны разные типы загрузки.Следуя этим принципам, вы создадите приложение, в котором легко вносить изменения, находить ошибки и добавлять новые функции.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№26/рекомендации-по-управлению-состоянием.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №26/Рекомендации по управлению состоянием.md</guid><pubDate>Fri, 24 Apr 2026 10:53:15 GMT</pubDate></item><item><title><![CDATA[Обработка асинхронного состояния]]></title><description><![CDATA[В мобильных приложениях часто требуется загружать данные из сети: список пользователей, постов, товаров и т.п. Такие операции асинхронны, и состояние компонента должно отражать разные этапы этого процесса: ожидание, успех или ошибку.Для корректной обработки асинхронных операций рекомендуется использовать три переменные состояния:
loading — флаг загрузки,
data — полученные данные,
error — информация об ошибке (если произошла).
Пример инициализации:const [loading, setLoading] = useState(true);
const [data, setData] = useState&lt;User[] | null&gt;(null);
const [error, setError] = useState&lt;string | null&gt;(null);
Загрузка обычно выполняется внутри эффекта (useEffect) при монтировании компонента:import { useEffect, useState } from 'react';
import { View, Text, ActivityIndicator } from 'react-native'; type User = { id: number; name: string;
}; export default function UsersScreen() { const [loading, setLoading] = useState(true); const [data, setData] = useState&lt;User[] | null&gt;(null); const [error, setError] = useState&lt;string | null&gt;(null); useEffect(() =&gt; { const fetchUsers = async () =&gt; { try { const response = await fetch('https://jsonplaceholder.typicode.com/users'); if (!response.ok) throw new Error('Ошибка сети'); const users: User[] = await response.json(); setData(users); } catch (err) { setError(err instanceof Error ? err.message : 'Неизвестная ошибка'); } finally { setLoading(false); } }; fetchUsers(); }, []); if (loading) { return &lt;ActivityIndicator size="large" /&gt;; } if (error) { return &lt;Text&gt;Ошибка: {error}&lt;/Text&gt;; } return ( &lt;View&gt; {data?.map(user =&gt; ( &lt;Text key={user.id}&gt;{user.name}&lt;/Text&gt; ))} &lt;/View&gt; );
} Во время загрузки показывается индикатор (ActivityIndicator).
При ошибке — сообщение об ошибке.
При успехе — отображаются данные.
Такой подход обеспечивает предсказуемое поведение интерфейса и улучшает пользовательский опыт.
Не забывайте вызывать setLoading(false) в блоке finally, чтобы скрыть индикатор даже при ошибке.
Избегайте хранения только одного состояния (например, status: 'idle' | 'loading' | 'success' | 'error') без дополнительных данных — это усложняет рендеринг.
Для повторной загрузки (например, по кнопке «Повторить») вынесите логику в отдельную функцию и вызывайте её при необходимости.
]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№26/обработка-асинхронного-состояния.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №26/Обработка асинхронного состояния.md</guid><pubDate>Fri, 24 Apr 2026 09:48:39 GMT</pubDate></item><item><title><![CDATA[useReducer для сложной логики состояния]]></title><description><![CDATA[Хук useReducer — это альтернатива useState для случаев, когда логика обновления состояния становится сложной: много подсостояний, взаимозависимые значения или множество возможных действий. Он основан на концепции редюсера из Flux/Redux и хорошо подходит для управления состоянием корзины, формы с валидацией, истории навигации и других сценариев.Функция useReducer принимает два аргумента:
редюсер (функцию, которая описывает, как состояние меняется в ответ на действия),
начальное состояние.
Она возвращает текущее состояние и функцию dispatch, которая отправляет действия в редюсер:const [state, dispatch] = useReducer(reducer, initialState);
Редюсер — это чистая функция, принимающая текущее состояние и действие (action), и возвращающая новое состояние:type Action = | { type: 'ADD_ITEM'; payload: string } | { type: 'REMOVE_ITEM'; payload: number }; type State = { items: string[];
}; function cartReducer(state: State, action: Action): State { switch (action.type) { case 'ADD_ITEM': return { ...state, items: [...state.items, action.payload] }; case 'REMOVE_ITEM': return { ...state, items: state.items.filter((_, index) =&gt; index !== action.payload), }; default: return state; }
}
import { useReducer } from 'react';
import { View, Text, Button } from 'react-native'; export default function CartScreen() { const [state, dispatch] = useReducer(cartReducer, { items: [] }); return ( &lt;View&gt; &lt;Text&gt;Товаров: {state.items.length}&lt;/Text&gt; &lt;Button title="Добавить товар" onPress={() =&gt; dispatch({ type: 'ADD_ITEM', payload: 'Новый товар' })} /&gt; {state.items.map((item, index) =&gt; ( &lt;Button key={index} title={`Удалить ${item}`} onPress={() =&gt; dispatch({ type: 'REMOVE_ITEM', payload: index })} /&gt; ))} &lt;/View&gt; );
} Централизованная логика обновления состояния.
Легче тестировать и отлаживать: каждое действие явно описано.
Упрощает управление состоянием с несколькими подполями.
Используйте useReducer, если:
состояние содержит несколько связанных значений,
следующее состояние зависит от предыдущего,
у вас есть сложная логика обновления (например, форма с полями, зависящими друг от друга),
вы хотите улучшить читаемость кода за счёт декларативного описания изменений.
В простых случаях (одиночные значения, независимые флаги) достаточно useState.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№26/usereducer-для-сложной-логики-состояния.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №26/useReducer для сложной логики состояния.md</guid><pubDate>Fri, 24 Apr 2026 09:47:32 GMT</pubDate></item><item><title><![CDATA[useContext для глобального состояния]]></title><description><![CDATA[Хук useContext позволяет передавать данные через дерево компонентов без явной передачи пропсов на каждом уровне. Это особенно полезно в мобильных приложениях, где одни и те же данные (например, тема интерфейса или статус авторизации) нужны во многих экранах.Контекст создаётся с помощью функции createContext. Ей можно передать значение по умолчанию — оно будет использовано, если компонент окажется вне провайдера:import { createContext } from 'react'; type Theme = { darkMode: boolean;
}; const ThemeContext = createContext&lt;Theme&gt;({ darkMode: false });
Чтобы сделать данные доступными для дочерних компонентов, нужно обернуть часть дерева компонентов в &lt;ThemeContext.Provider&gt;. Значение передаётся через пропс value:import { useState } from 'react'; export default function App() { const [darkMode, setDarkMode] = useState(false); return ( &lt;ThemeContext.Provider value={{ darkMode }}&gt; {/* Весь ваш навигатор или корневой экран */} &lt;MainScreen /&gt; &lt;/ThemeContext.Provider&gt; );
}
В любом вложенном компоненте можно получить доступ к данным контекста с помощью хука useContext:import { useContext } from 'react';
import { View, Text } from 'react-native'; function SettingsScreen() { const { darkMode } = useContext(ThemeContext); return ( &lt;View style={{ backgroundColor: darkMode ? '#000' : '#fff' }}&gt; &lt;Text style={{ color: darkMode ? '#fff' : '#000' }}&gt; Темный режим: {darkMode ? 'включён' : 'выключен'} &lt;/Text&gt; &lt;/View&gt; );
}
Этот подход подходит для:
переключения темы приложения,
хранения языка интерфейса,
отслеживания состояния авторизации (например, isAuthenticated),
передачи конфигурации API или настроек пользователя.
Однако не стоит злоупотреблять контекстом. Если данные нужны только в одном или двух компонентах, лучше передавать их через пропсы. Контекст наиболее эффективен, когда одни и те же данные используются на разных уровнях вложенности.Контекст не предназначен для высокочастотных обновлений (например, анимаций или быстрого ввода текста). При каждом изменении значения в провайдере все компоненты, подписанные на этот контекст, будут перерисовываться. Поэтому рекомендуется передавать через контекст только стабильные данные или разбивать контексты на мелкие (например, отдельно для темы, отдельно для авторизации).]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№26/usecontext-для-глобального-состояния.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №26/useContext для глобального состояния.md</guid><pubDate>Fri, 24 Apr 2026 09:46:25 GMT</pubDate></item><item><title><![CDATA[useState в мобильных приложениях]]></title><description><![CDATA[Хук useState — это основной способ управления локальным состоянием компонента в React и React Native. Он позволяет сохранять и обновлять данные, которые могут меняться во время взаимодействия пользователя с приложением: текст в поле ввода, состояние переключателя, видимость элемента и так далее.Функция useState принимает начальное значение и возвращает массив из двух элементов:
текущее значение состояния,
функцию для его обновления.
Пример базового использования:import { useState } from 'react';
import { View, Text, Button } from 'react-native'; export default function CounterScreen() { const [count, setCount] = useState(0); return ( &lt;View&gt; &lt;Text&gt;Счётчик: {count}&lt;/Text&gt; &lt;Button title="Увеличить" onPress={() =&gt; setCount(count + 1)} /&gt; &lt;/View&gt; );
}
Поля ввода часто связаны с состоянием через useState. При каждом изменении текста состояние обновляется:const [email, setEmail] = useState(''); // ...
&lt;TextInput value={email} onChangeText={setEmail} placeholder="Введите email"
/&gt;
Для управления отображением модальных окон, индикаторов загрузки или ошибок удобно использовать булевы значения:const [isLoading, setIsLoading] = useState(false);
const [isModalVisible, setIsModalVisible] = useState(false);
Если нужно отобразить динамический список (например, заметки или комментарии), его можно хранить в состоянии:const [items, setItems] = useState&lt;string[]&gt;([]); // Добавление элемента
const addItem = (text: string) =&gt; { setItems([...items, text]);
};
Важно помнить: при обновлении объектов или массивов в состоянии всегда создаётся новый экземпляр (например, с помощью оператора расширения ...), чтобы React мог корректно определить, что состояние изменилось.В React Native поведение useState ничем не отличается от веб-версии React. Однако интерфейсные элементы (вроде TextInput, Switch, Modal) требуют явной привязки к состоянию, так как они не поддерживают двустороннюю привязку «из коробки».Например, для переключателя (Switch) нужно вручную обрабатывать событие изменения:const [isEnabled, setIsEnabled] = useState(false); // ...
&lt;Switch value={isEnabled} onValueChange={setIsEnabled}
/&gt;
Такой подход обеспечивает предсказуемость и контроль над данными в приложении.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№26/usestate-в-мобильных-приложениях.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №26/useState в мобильных приложениях.md</guid><pubDate>Fri, 24 Apr 2026 09:26:26 GMT</pubDate></item><item><title><![CDATA[Практические рекомендации]]></title><description><![CDATA[При разработке интерфейсов в React Native важно учитывать особенности платформы и избегать распространённых ошибок. Следующие рекомендации помогут создавать стабильные, производительные и поддерживаемые экраны.Абсолютное позиционирование (position: 'absolute') нарушает поток компоновки и усложняет адаптацию под разные размеры экранов. Используйте его только когда другие методы (например, Flexbox) не решают задачу — например, для всплывающих элементов или кастомных индикаторов.Вместо абсолютного позиционирования предпочтительнее использовать:
flexDirection, justifyContent, alignItems
Отступы (margin, padding)
Вложенные контейнеры с flex
Избыточная вложенность компонентов View снижает производительность и усложняет чтение кода. Старайтесь свести количество уровней вложенности к минимуму. Часто можно объединить стили или перестроить layout, чтобы убрать промежуточный контейнер.Плохо:&lt;View&gt; &lt;View style={styles.outer}&gt; &lt;View style={styles.inner}&gt; &lt;Text&gt;Текст&lt;/Text&gt; &lt;/View&gt; &lt;/View&gt;
&lt;/View&gt;
Хорошо:&lt;View style={[styles.outer, styles.inner]}&gt; &lt;Text&gt;Текст&lt;/Text&gt;
&lt;/View&gt;
Как уже отмечалось, Image требует явного width и height. Аналогично, если View должен занимать пространство, но не участвует в flex-контексте, ему тоже нужны размеры. При использовании flex: 1 размеры вычисляются автоматически, но только если родительский контейнер имеет ненулевой размер (часто — за счёт собственного flex: 1).Проверяйте, что корневой элемент экрана имеет style={{ flex: 1 }}, иначе дочерние элементы могут не отображаться.Это улучшает читаемость и производительность. Динамические стили (зависящие от состояния) можно комбинировать через массив:&lt;View style={[styles.base, isActive &amp;&amp; styles.active]} /&gt;
Размеры в пикселях в React Native являются «логическими» (device-independent pixels), но всё равно могут выглядеть по-разному на экранах с разной плотностью. Используйте Flexbox вместо фиксированных координат, чтобы интерфейс адаптировался автоматически.React Native — это не веб. Отсутствуют:
Каскадирование стилей
Наследование текстовых свойств вне Text
Глобальные стили
Псевдоклассы и медиазапросы
Проектируйте интерфейс с учётом этих ограничений с самого начала.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№25/практические-рекомендации.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №25/Практические рекомендации.md</guid><pubDate>Fri, 24 Apr 2026 08:57:46 GMT</pubDate></item><item><title><![CDATA[Работа с изображениями]]></title><description><![CDATA[В React Native изображения отображаются с помощью компонента Image. Важной особенностью является то, что все изображения должны иметь явно заданные размеры — без указания width и height изображение не отобразится.Для подключения изображений из папки проекта используется функция require(). Путь должен быть статическим — нельзя использовать переменные или шаблонные строки внутри require.Пример:&lt;Image source={require('./assets/icon.png')} style={{ width: 48, height: 48 }}
/&gt;
Особенности:
Файл должен существовать на момент сборки.
Поддерживаются форматы PNG, JPG, WebP (в зависимости от платформы).
Имя файла чувствительно к регистру.
Для загрузки изображений из интернета используется объект с ключом uri:&lt;Image source={{ uri: 'https://example.com/photo.jpg' }} style={{ width: 200, height: 200 }}
/&gt;
Особенности:
Не требуется указывать расширение.
Изображение загружается асинхронно — пока оно не загружено, ничего не отображается.
Можно добавить обработку ошибок через проп onError, но базовый Image не показывает placeholder по умолчанию.
React Native не может определить размер изображения до его загрузки (особенно для сетевых), поэтому всегда нужно задавать width и height в стилях. Это касается как локальных, так и сетевых изображений.Если размеры динамические, их можно вычислить заранее или использовать onLoad, чтобы получить реальные размеры после загрузки, но это требует дополнительного состояния.Для продвинутых сценариев (например, автоматическое масштабирование, кэширование, placeholder) рекомендуется использовать сторонние библиотеки, такие как react-native-fast-image. Однако в рамках базового курса достаточно стандартного Image.&lt;View style={{ flexDirection: 'row', padding: 12, alignItems: 'center' }}&gt; &lt;Image source={require('./assets/avatar.jpg')} style={{ width: 50, height: 50, borderRadius: 25 }} /&gt; &lt;View style={{ marginLeft: 12 }}&gt; &lt;Text style={{ fontSize: 16 }}&gt;Иван Петров&lt;/Text&gt; &lt;Text style={{ color: '#666' }}&gt;Разработчик&lt;/Text&gt; &lt;/View&gt;
&lt;/View&gt;
В этом примере аватар имеет фиксированный размер и скруглённые углы (borderRadius: 25 при размере 50×50 даёт круг).]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№25/работа-с-изображениями.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №25/Работа с изображениями.md</guid><pubDate>Fri, 24 Apr 2026 08:56:18 GMT</pubDate></item><item><title><![CDATA[Flexbox в React Native]]></title><link>материалы/подтемы/секция-3.-react-native/тема-№25/flexbox-в-react-native.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №25/Flexbox в React Native.md</guid><pubDate>Fri, 17 Apr 2026 11:16:49 GMT</pubDate></item><item><title><![CDATA[Стилизация]]></title><description><![CDATA[В React Native стили задаются не через строки или CSS-файлы, а через объекты JavaScript. Это обеспечивает типобезопасность (особенно в TypeScript), предотвращает конфликты имён и улучшает производительность.Каждое свойство стиля записывается в виде пары ключ–значение внутри объекта. Такой объект передаётся в проп style компонента:&lt;View style={{ padding: 16, backgroundColor: '#f0f0f0' }}&gt; &lt;Text style={{ fontSize: 18, color: '#333' }}&gt;Привет, мир!&lt;/Text&gt;
&lt;/View&gt;
Обратите внимание:
Значения без единиц измерения (например, padding: 16) интерпретируются как пиксели.
Цвета указываются в форматах #rgb, #rrggbb, rgb(), rgba() или по имени ('red').
Имена свойств пишутся в camelCase: backgroundColor, а не background-color.
Для оптимизации производительности рекомендуется объявлять стили с помощью StyleSheet.create(). Это позволяет React Native сериализовать стили один раз при загрузке модуля, а не при каждом рендере.Пример:import { StyleSheet, View, Text } from 'react-native'; const styles = StyleSheet.create({ container: { flex: 1, padding: 16, backgroundColor: '#fff', }, title: { fontSize: 20, fontWeight: 'bold', color: '#000', },
}); // Использование
&lt;View style={styles.container}&gt; &lt;Text style={styles.title}&gt;Заголовок&lt;/Text&gt;
&lt;/View&gt;
Использование StyleSheet.create() также помогает избежать ошибок — некоторые неверные значения будут вызывать предупреждения в режиме разработки.React Native поддерживает ограниченный набор CSS-свойств. Основные из них:
Layout: width, height, flex, flexDirection, justifyContent, alignItems
Отступы: margin, marginTop, padding, paddingHorizontal и т.д.
Фон: backgroundColor
Текст: fontSize, color, fontWeight, textAlign, lineHeight
Границы: borderWidth, borderColor, borderRadius
Важно помнить, что в React Native отсутствуют:
Псевдоклассы (:hover, :active)
Медиазапросы
Свойства вроде float, display: block/inline
Относительные единицы (em, rem, % для большинства свойств)
position: absolute с процентными значениями (размеры должны быть в пикселях или через flex)
Все позиционирование строится на основе Flexbox или абсолютного позиционирования с фиксированными координатами (top, left, right, bottom в пикселях).Если нужно применить несколько наборов стилей, можно передать массив в проп style:&lt;View style={[styles.container, { marginTop: 20 }]}&gt; {/* ... */}
&lt;/View&gt;
Это особенно полезно для условного применения стилей:&lt;View style={[styles.base, isActive &amp;&amp; styles.active]}&gt;
Такой подход безопасен: если условие ложно, false будет проигнорирован.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№25/стилизация.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №25/Стилизация.md</guid><pubDate>Fri, 17 Apr 2026 11:14:13 GMT</pubDate></item><item><title><![CDATA[Основные компоненты]]></title><description><![CDATA[React Native предоставляет набор базовых компонентов, из которых строятся все экраны мобильного приложения. Эти компоненты отображаются как нативные элементы на iOS и Android, в отличие от HTML-элементов в вебе.Компонент View — это основной контейнерный элемент. Он не отображает содержимое сам по себе, но группирует другие компоненты и применяет к ним стили. По функциональности он ближе всего к &lt;div&gt; в HTML, но имеет ряд особенностей:
Не может содержать текст напрямую — для этого используется Text.
Поддерживает большинство layout-свойств: flex, padding, margin, backgroundColor и т.д.
Является блочным элементом по умолчанию.
Пример:&lt;View style={{ padding: 16, backgroundColor: '#fff' }}&gt; &lt;Text&gt;Заголовок&lt;/Text&gt;
&lt;/View&gt;
Компонент Text предназначен исключительно для отображения текста. Важно помнить:
Текст можно размещать только внутри Text.
Другие Text могут быть вложенными — это позволяет применять разные стили к частям строки.
Не поддерживает layout-свойства вроде width, height, margin — только текстовые (fontSize, color, fontWeight и т.п.).
Пример:&lt;Text style={{ fontSize: 18 }}&gt; Обычный текст &lt;Text style={{ fontWeight: 'bold' }}&gt;жирный фрагмент&lt;/Text&gt;
&lt;/Text&gt;
Компонент Image отображает изображения — как локальные, так и сетевые. Основные особенности:
Обязательно требует явного указания размеров (width и height) для корректного отображения.
Для локальных изображений используется require().
Для сетевых — объект с ключом uri.
Пример:// Локальное изображение
&lt;Image source={require('./assets/logo.png')} style={{ width: 100, height: 100 }} /&gt; // Сетевое изображение
&lt;Image source={{ uri: 'https://example.com/image.jpg' }} style={{ width: 200, height: 200 }} /&gt;
Оба компонента позволяют прокручивать содержимое, но используются в разных сценариях.ScrollView подходит для небольших списков или контента фиксированной длины. Он рендерит всё содержимое сразу, что может повлиять на производительность при большом объёме данных.FlatList оптимизирован для длинных списков: он рендерит только видимые элементы и переиспользует их при прокрутке (техника «virtualization»). Требует указания data и renderItem.Пример FlatList:&lt;FlatList data={['Элемент 1', 'Элемент 2', 'Элемент 3']} renderItem={({ item }) =&gt; &lt;Text&gt;{item}&lt;/Text&gt;} keyExtractor={(item, index) =&gt; index.toString()}
/&gt;
Компонент TextInput создаёт поле для ввода текста. Поддерживает стандартные свойства: value, onChangeText, placeholder, keyboardType и другие.Пример:&lt;TextInput placeholder="Введите имя" value={name} onChangeText={setName}
/&gt;
Для обработки нажатий используются интерактивные компоненты.Button — простой компонент с ограниченной кастомизацией. Принимает title и onPress.TouchableOpacity и Pressable дают больше контроля над внешним видом. При нажатии TouchableOpacity слегка затемняет содержимое, а Pressable позволяет полностью управлять состоянием (нажат/не нажат).Примеры:&lt;TouchableOpacity onPress={() =&gt; console.log('Нажато!')}&gt; &lt;View style={{ padding: 12, backgroundColor: '#007AFF' }}&gt; &lt;Text style={{ color: '#fff' }}&gt;Кнопка&lt;/Text&gt; &lt;/View&gt;
&lt;/TouchableOpacity&gt;
&lt;Pressable onPress={() =&gt; console.log('Нажато!')} onPressIn={() =&gt; console.log('Палец коснулся')} onPressOut={() =&gt; console.log('Палец оторван')} style={({ pressed }) =&gt; ({ opacity: pressed ? 0.6 : 1, padding: 12, backgroundColor: '#007AFF', borderRadius: 8, })}
&gt; &lt;Text style={{ color: '#fff', textAlign: 'center' }}&gt; Нажми меня &lt;/Text&gt;
&lt;/Pressable&gt;
]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№25/основные-компоненты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №25/Основные компоненты.md</guid><pubDate>Fri, 17 Apr 2026 11:12:53 GMT</pubDate></item><item><title><![CDATA[Тема №25. Компоненты и стили в React Native]]></title><description><![CDATA[В этой теме вы изучите основные нативные компоненты React Native и систему стилизации, отличающуюся от веба. Научитесь создавать интерфейсы с использованием View, Text, Image и других элементов, а также применять стили через JavaScript-объекты. Это фундамент для построения экранов мобильных приложений.
<a data-href="Основные компоненты" href="материалы/подтемы/секция-3.-react-native/тема-№25/основные-компоненты.html" class="internal-link" target="_self" rel="noopener nofollow">Основные компоненты</a>
<br><a data-href="Стилизация" href="материалы/подтемы/секция-3.-react-native/тема-№25/стилизация.html" class="internal-link" target="_self" rel="noopener nofollow">Стилизация</a>
<br><a data-href="Flexbox в React Native" href="материалы/подтемы/секция-3.-react-native/тема-№25/flexbox-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Flexbox в React Native</a>
<br><a data-href="Работа с изображениями" href="материалы/подтемы/секция-3.-react-native/тема-№25/работа-с-изображениями.html" class="internal-link" target="_self" rel="noopener nofollow">Работа с изображениями</a>
<br><a data-href="Практические рекомендации" href="материалы/подтемы/секция-3.-react-native/тема-№25/практические-рекомендации.html" class="internal-link" target="_self" rel="noopener nofollow">Практические рекомендации</a>
(пусто)<br><a data-href="Тема №26. Управление состоянием в React Native" href="лекции/секция-3.-react-native/тема-№26.-управление-состоянием-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №26. Управление состоянием в React Native</a>]]></description><link>лекции/секция-3.-react-native/тема-№25.-компоненты-и-стили-в-react-native.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №25. Компоненты и стили в React Native.md</guid><pubDate>Fri, 17 Apr 2026 11:06:29 GMT</pubDate></item><item><title><![CDATA[Основные ограничения]]></title><description><![CDATA[React Native предоставляет мощный инструмент для кроссплатформенной разработки, но имеет ряд принципиальных ограничений по сравнению с веб-разработкой на React. Эти ограничения связаны с тем, что мобильная среда кардинально отличается от браузерной.В React Native нет DOM, а значит недоступны привычные веб-объекты:
window
document
navigator (в полном объёме)
localStorage, sessionStorage
Попытка использовать их вызовет ошибку выполнения. Например, код:console.log(window.innerWidth); // Ошибка: window is not defined
не сработает, потому что мобильное приложение не работает внутри браузера.Для задач, решаемых в вебе через стандартные API, в React Native используются альтернативы: Хранение данных: вместо localStorage применяется AsyncStorage (или более современные решения вроде expo-sqlite или MMKV).
import AsyncStorage from '@react-native-async-storage/async-storage'; await AsyncStorage.setItem('token', 'abc123');
const token = await AsyncStorage.getItem('token'); Сетевые запросы: fetch и XMLHttpRequest работают, так как они реализованы в JavaScript-движке (Hermes или JSC). Геолокация, камера, сенсоры: доступны через специализированные библиотеки, например, из Expo SDK (expo-location, expo-camera). Стилизация в React Native основана на подмножестве CSS, но с важными отличиями:
Поддерживается только Flexbox как основной механизм компоновки.
Нет каскада, наследования и селекторов — стили применяются только к конкретному компоненту.
Многие CSS-свойства отсутствуют: float, position: fixed, z-index (частично), медиа-запросы.
Все размеры по умолчанию задаются в логических пикселях (points), а не в физических.
Пример того, что не работает:// Нельзя так:
&lt;Text style={{ color: 'inherit' }}&gt;Текст&lt;/Text&gt; // нет наследования
&lt;View className="container" /&gt; // нет class / CSS-файлов
Вместо этого всё оформляется через объекты стилей:// Правильно:
&lt;Text style={{ color: '#333', fontSize: 16 }}&gt;Текст&lt;/Text&gt;
Эти ограничения делают разработку более предсказуемой, но требуют переосмысления подходов, привычных в вебе.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№24/основные-ограничения.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №24/Основные ограничения.md</guid><pubDate>Fri, 17 Apr 2026 11:03:58 GMT</pubDate></item><item><title><![CDATA[Первое приложение]]></title><description><![CDATA[Создание первого приложения в React Native — простой процесс, особенно при использовании Expo. Ниже описаны шаги от инициализации проекта до его запуска на устройстве или эмуляторе.Ранее для создания проектов использовалась команда npx create-react-native-app, но сейчас официально рекомендуется использовать Expo CLI через npx create-expo-app. Эта команда создаёт готовый к запуску проект с минимальной конфигурацией.Чтобы создать проект с поддержкой TypeScript, выполните:npx create-expo-app MyFirstApp --template typescript
Это создаст папку MyFirstApp с базовой структурой приложения.После создания вы увидите следующие ключевые файлы:
App.tsx — главный компонент приложения. Именно он отображается при запуске.
package.json — содержит зависимости и скрипты (например, start, android, ios).
app.json или app.config.js — конфигурация Expo: название приложения, иконка, ориентация и др.
tsconfig.json — настройки TypeScript (если выбран шаблон с TS).
Папка node_modules — все установленные зависимости.
Пример содержимого App.tsx:import { StatusBar } from 'expo-status-bar';
import { StyleSheet, Text, View } from 'react-native'; export default function App() { return ( &lt;View style={styles.container}&gt; &lt;Text&gt;Моё первое приложение на React Native!&lt;/Text&gt; &lt;StatusBar style="auto" /&gt; &lt;/View&gt; );
} const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', },
});
Этот код отобразит центрированный текст на белом фоне.После перехода в папку проекта (cd MyFirstApp) вы можете запустить приложение несколькими способами.
Запустите сервер разработки:
npx expo start Откроется веб-интерфейс Metro.
Установите приложение Expo Go на смартфон (из App Store или Google Play).
Отсканируйте QR-код из терминала или веб-панели камерой телефона.
Приложение загрузится и будет автоматически обновляться при сохранении файлов.
Если у вас установлен Android Studio (для Windows/Linux/macOS) или Xcode (только macOS), можно запустить эмулятор напрямую:npm run android
# или
npm run ios
Эти команды определены в package.json и вызывают expo run:android или expo run:ios. Они соберут нативное приложение и установят его в эмулятор.
Примечание: при первом запуске сборка может занять несколько минут. Последующие запуски будут быстрее благодаря кэшированию.
После успешного запуска вы увидите ваше приложение на экране — это означает, что среда настроена корректно и можно переходить к дальнейшему изучению компонентов и стилей.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№24/первое-приложение.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №24/Первое приложение.md</guid><pubDate>Fri, 17 Apr 2026 11:00:13 GMT</pubDate></item><item><title><![CDATA[Установка среды разработки]]></title><description><![CDATA[Для разработки на React Native требуется настроить окружение, включающее как общие инструменты (Node.js), так и платформо-специфичные компоненты (Android SDK, Xcode). Однако существует два основных подхода: с использованием Expo CLI и React Native CLI. Для новичков рекомендуется начинать с Expo.Независимо от выбранного инструмента, вам понадобятся:
Node.js (версия 18 или новее) — для запуска JavaScript-сборки
npm или yarn — менеджер пакетов
Git — используется многими инструментами под капотом
Для запуска на реальных устройствах или эмуляторах дополнительно нужны:
Android: Android Studio с установленным Android SDK и эмулятором
iOS (только на macOS): Xcode с симулятором iOS Важно: если вы работаете на Windows или Linux, запуск iOS-приложений невозможен — только Android.
Для обучения и прототипирования Expo — лучший выбор. Он позволяет писать код, мгновенно видеть изменения на устройстве (через Expo Go) и не беспокоиться о сборке APK/IPA.
Установите Expo CLI глобально:
npm install -g @expo/cli Создайте новый проект:
npx create-expo-app MyFirstApp Перейдите в папку проекта:
cd MyFirstApp Запустите сервер разработки:
npx expo start После этого откроется веб-панель Metro. Вы можете:
Запустить эмулятор Android/iOS (если установлен)
Отсканировать QR-код камерой смартфона с установленным приложением Expo Go (доступно в App Store и Google Play) Примечание: все команды выше работают без предварительной установки Android Studio или Xcode при использовании Expo Go на физическом устройстве.
Если в будущем потребуется доступ к нативным модулям, можно выполнить prebuild или перейти на bare workflow, но это выходит за рамки вводной темы и курса в целом.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№24/установка-среды-разработки.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №24/Установка среды разработки.md</guid><pubDate>Fri, 17 Apr 2026 10:58:26 GMT</pubDate></item><item><title><![CDATA[Как работает React Native]]></title><description><![CDATA[React Native работает за счёт взаимодействия между JavaScript-кодом и нативной частью мобильного приложения. В отличие от веб-приложений, где браузер интерпретирует HTML и CSS, в React Native UI строится из настоящих нативных компонентов, управляемых через JavaScript.Основной элемент архитектуры — мост (Bridge). Это асинхронный канал связи между двумя средами:
JavaScript-поток: здесь выполняется ваш код на JS/TS, включая логику компонентов, состояние и эффекты.
Нативный поток: здесь работают UI-компоненты операционной системы (например, UIView на iOS или View на Android).
Когда вы изменяете состояние в компоненте, React Native не обновляет DOM. Вместо этого он формирует «инструкции» (diff-дерево), отправляет их через мост, и нативная сторона создаёт или обновляет соответствующие нативные виджеты.
Примечание: в новых версиях React Native (начиная с 0.68+) появилась архитектура Fabric, которая устраняет мост и позволяет синхронизировать потоки напрямую. Но для начала достаточно понимать классическую модель с мостом.
В React Native нет HTML. Все элементы интерфейса — это обёртки над нативными компонентами:
&lt;View&gt; → контейнер (аналог &lt;div&gt;)
&lt;Text&gt; → текстовый элемент (обязателен для отображения текста)
&lt;Image&gt; → изображение
&lt;ScrollView&gt;, &lt;FlatList&gt; → прокручиваемые списки
Пример:import { View, Text } from 'react-native'; export default function App() { return ( &lt;View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}&gt; &lt;Text&gt;Привет из React Native!&lt;/Text&gt; &lt;/View&gt; );
}
Этот код создаст нативное окно с центрированным текстом — без единого пикселя WebView.Стилизация в React Native напоминает inline-стили в вебе, но с ограничениями:
Свойства записываются в camelCase (backgroundColor, а не background-color)
Нет наследования стилей: каждый &lt;Text&gt; должен иметь собственные стили
Поддерживается только часть CSS: flexbox, padding/margin, цвета, шрифты, тени — да; медиа-запросы, псевдоклассы, селекторы — нет
Стили объявляются как объекты или с помощью StyleSheet.create() для оптимизации
Пример:import { StyleSheet, Text, View } from 'react-native'; const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', padding: 20, }, title: { fontSize: 24, fontWeight: 'bold', },
}); export default function App() { return ( &lt;View style={styles.container}&gt; &lt;Text style={styles.title}&gt;Заголовок&lt;/Text&gt; &lt;/View&gt; );
}
Такой подход обеспечивает предсказуемость и производительность, так как стили компилируются в нативные представления заранее.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№24/как-работает-react-native.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №24/Как работает React Native.md</guid><pubDate>Fri, 17 Apr 2026 10:51:36 GMT</pubDate></item><item><title><![CDATA[Что такое React Native]]></title><description><![CDATA[React Native — это фреймворк с открытым исходным кодом, разработанный Meta (ранее Facebook), который позволяет создавать мобильные приложения для iOS и Android с использованием JavaScript или TypeScript и знакомой модели компонентов из React.Основная идея React Native — писать один код на языке, известном веб-разработчикам, но при этом получать приложение, которое выглядит и ведёт себя как нативное. Это достигается за счёт того, что компоненты React Native не рендерятся в HTML-элементы DOM, а транслируются в настоящие нативные UI-компоненты операционной системы: UIButton на iOS или android.widget.Button на Android.
Единая кодовая база для двух платформ. Большая часть логики и интерфейса может быть общей, что снижает время и стоимость разработки.
Знакомый синтаксис для тех, кто уже знает React. Используются те же принципы: компоненты, состояние, эффекты.
Доступ к нативным возможностям через модули (камера, геолокация, сенсоры и др.), хотя иногда требуется написание дополнительного нативного кода.
Большое сообщество и экосистема, включая библиотеки для навигации, хранения данных, анимаций и тестирования.
В веб-приложении на React компоненты рендерятся в DOM: &lt;div&gt;, &lt;p&gt;, &lt;img&gt; и стилизуются с помощью CSS. В React Native этого нет:
Вместо &lt;div&gt; используется &lt;View&gt;
Вместо &lt;p&gt; или &lt;span&gt; — &lt;Text&gt;
Вместо &lt;img&gt; — &lt;Image&gt;
Стилизация происходит не через CSS-файлы, а через объекты с camelCase-свойствами, например: const styles = { container: { flex: 1, backgroundColor: 'white', padding: 16 }
}; Нет доступа к таким веб-API, как window, document, localStorage — они заменяются на мобильные аналоги.
React Native не использует WebView (в отличие от гибридных решений вроде Cordova). Он взаимодействует с нативной платформой напрямую, что обеспечивает лучшую производительность и внешний вид.]]></description><link>материалы/подтемы/секция-3.-react-native/тема-№24/что-такое-react-native.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 3. React Native/Тема №24/Что такое React Native.md</guid><pubDate>Fri, 17 Apr 2026 10:49:19 GMT</pubDate></item><item><title><![CDATA[Тема №24. Введение в React Native]]></title><description><![CDATA[В этой теме вы познакомитесь с React Native — фреймворком для создания "нативных" мобильных приложений на основе React. Поймёте, как он работает, чем отличается от веб-React и зачем используется в мобильной разработке. Это первый шаг к построению реальных приложений для iOS и Android.
<a data-href="Что такое React Native" href="материалы/подтемы/секция-3.-react-native/тема-№24/что-такое-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое React Native</a>
<br><a data-href="Как работает React Native" href="материалы/подтемы/секция-3.-react-native/тема-№24/как-работает-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Как работает React Native</a>
<br><a data-href="Установка среды разработки" href="материалы/подтемы/секция-3.-react-native/тема-№24/установка-среды-разработки.html" class="internal-link" target="_self" rel="noopener nofollow">Установка среды разработки</a>
<br><a data-href="Первое приложение" href="материалы/подтемы/секция-3.-react-native/тема-№24/первое-приложение.html" class="internal-link" target="_self" rel="noopener nofollow">Первое приложение</a>
<br><a data-href="Основные ограничения" href="материалы/подтемы/секция-3.-react-native/тема-№24/основные-ограничения.html" class="internal-link" target="_self" rel="noopener nofollow">Основные ограничения</a>
(пусто)<br><a data-href="Тема №25. Компоненты и стили в React Native" href="лекции/секция-3.-react-native/тема-№25.-компоненты-и-стили-в-react-native.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №25. Компоненты и стили в React Native</a>]]></description><link>лекции/секция-3.-react-native/тема-№24.-введение-в-react-native.html</link><guid isPermaLink="false">Лекции/Секция 3. React Native/Тема №24. Введение в React Native.md</guid><pubDate>Fri, 17 Apr 2026 10:48:34 GMT</pubDate></item><item><title><![CDATA[Обработка ошибок]]></title><description><![CDATA[При работе с API важно корректно обрабатывать все возможные ошибки. Функция fetch ведёт себя особым образом: она выбрасывает исключение только при сетевых сбоях (например, отсутствии интернета или недоступности сервера), но не считает ошибкой HTTP-статусы 4xx или 5xx. Это означает, что даже ответ с кодом 404 или 500 будет успешно разрешён как промис, и программист обязан проверить статус вручную.
Ошибка сети — запрос не дошёл до сервера (нет подключения, DNS не разрешился и т.п.). Ошибка сервера — запрос дошёл, но сервер вернул статус 4xx/5xx. Ошибка парсинга — сервер вернул данные в неожиданном формате (например, HTML вместо JSON).
Все три случая требуют отдельной обработки.async function fetchUser(id: number): Promise&lt;User&gt; { try { const response = await fetch(`/api/user/${id}`); // Проверка HTTP-статуса if (!response.ok) { throw new Error(`Server returned ${response.status}: ${response.statusText}`); } // Попытка распарсить JSON const rawData: unknown = await response.json(); // Проверка структуры (упрощённо) if ( typeof rawData === 'object' &amp;&amp; rawData !== null &amp;&amp; 'id' in rawData &amp;&amp; 'name' in rawData ) { return rawData as User; } else { throw new Error('Invalid data structure'); } } catch (error) { // Обработка сетевой ошибки или ошибки парсинга if (error instanceof Error) { console.error('Fetch error:', error.message); throw error; // или обработать по-другому (показать уведомление и т.п.) } throw new Error('Unknown error occurred'); }
} Всегда проверяйте response.ok после fetch, если ожидаете успешный результат.
Оборачивайте вызов response.json() в try/catch, так как он выбросит ошибку, если тело ответа не является валидным JSON.
Используйте внешний catch для перехвата сетевых ошибок (например, TypeError: Failed to fetch).
Не полагайтесь на то, что сервер всегда вернёт ожидаемый формат — даже при статусе 200.
Такой подход обеспечивает устойчивость приложения к реальным условиям работы: потере соединения, изменениям в API или временным сбоям сервера.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22-1/обработка-ошибок.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22 1/Обработка ошибок.md</guid><pubDate>Fri, 17 Apr 2026 10:43:36 GMT</pubDate></item><item><title><![CDATA[Типизация ответов API]]></title><description><![CDATA[При работе с API в TypeScript важно не только получить данные, но и правильно описать их структуру. Это позволяет избежать ошибок на этапе разработки и сделать код более надёжным и читаемым.Первый шаг — создать интерфейс, описывающий ожидаемую структуру данных от сервера. Например, если API возвращает информацию о пользователе:interface User { id: number; name: string; email: string;
}
Этот интерфейс можно использовать для типизации переменных, параметров функций и возвращаемых значений.Метод response.json() возвращает промис с типом any, что отключает проверку типов. Чтобы восстановить безопасность, явно указывают ожидаемый тип:const response = await fetch('/api/user/1');
const user: User = await response.json();
Теперь при обращении к user.name TypeScript знает, что это строка, а user.id — число. Если попытаться обратиться к несуществующему полю, например user.username, компилятор выдаст ошибку.Без типов легко допустить ошибку, особенно если структура ответа меняется или отличается от документации. Например, сервер может вернуть:{ "id": 1, "username": "alex" }
а в коде ожидается:interface User { name: string; }
Если не использовать типизацию, обращение к user.name завершится undefined, и ошибка проявится только во время выполнения. С интерфейсом TypeScript предупредит об этом ещё до запуска.На практике нельзя полностью доверять серверу. Даже при наличии интерфейса реальный ответ может отличаться. Поэтому в production-коде рекомендуется сначала считать ответ типа unknown, а затем проверить его структуру.Пример безопасного парсинга:const response = await fetch('/api/user/1');
const rawData: unknown = await response.json(); if ( typeof rawData === 'object' &amp;&amp; rawData !== null &amp;&amp; 'id' in rawData &amp;&amp; 'name' in rawData &amp;&amp; typeof (rawData as any).id === 'number' &amp;&amp; typeof (rawData as any).name === 'string'
) { const user: User = rawData as User; console.log(user.name);
} else { throw new Error('Invalid user data received from server');
}
Такой подход называется проверкой времени выполнения (runtime validation). Он сочетается со статической типизацией и обеспечивает защиту как на этапе разработки, так и при работе приложения.Для упрощения таких проверок в реальных проектах часто используют библиотеки вроде Zod или io-ts, но в рамках курса достаточно ручной проверки через условия и приведение типов.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22-1/типизация-ответов-api.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22 1/Типизация ответов API.md</guid><pubDate>Fri, 17 Apr 2026 10:41:28 GMT</pubDate></item><item><title><![CDATA[Отправка запросов]]></title><description><![CDATA[Отправка HTTP-запросов — ключевая задача при взаимодействии с API. В JavaScript и TypeScript для этого чаще всего используется встроенная функция fetch. Она доступна как в браузере, так и в современных версиях Node.js (начиная с v18). Существуют и другие инструменты, например, библиотека Axios, которая предлагает более удобный API, автоматическое преобразование данных и лучшую поддержку отмены запросов. Однако в рамках этого курса мы используем только fetch, чтобы изучить базовые принципы работы с сетью без зависимости от сторонних библиотек.Функция fetch принимает два аргумента:
URL эндпоинта (обязательно)
Объект с настройками запроса (опционально)
Она возвращает промис, который разрешается в объект Response.Простой GET-запрос:const response = await fetch('https://api.example.com/users');
Второй аргумент — объект с параметрами:const response = await fetch('/api/profile', { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer token123' }, body: JSON.stringify({ name: 'Alex' })
});
Основные опции:
method — HTTP-метод: 'GET', 'POST', 'PUT', 'DELETE' и др.
headers — заголовки запроса. Можно передать как обычный объект или экземпляр класса Headers.
Пример с объектом (чаще используется):headers: { 'Content-Type': 'application/json', 'Accept': 'application/json'
}
Пример с классом Headers (полезно при динамическом добавлении):const headers = new Headers();
headers.append('Content-Type', 'application/json');
headers.append('Authorization', 'Bearer xyz'); // затем в fetch:
fetch(url, { headers });
Оба подхода эквивалентны. Использование объекта проще и читаемее, поэтому он предпочтителен в большинстве случаев.
body — тело запроса. Допустимые типы: строка, FormData, URLSearchParams, Blob, ArrayBuffer.
Объект Response содержит метаданные и методы для чтения тела ответа:
response.ok — true, если статус ответа в диапазоне 200–299.
response.status — числовой код статуса (например, 200, 404, 500).
response.json() — парсит тело ответа как JSON и возвращает промис с результатом.
response.text() — возвращает тело как строку.
response.blob() — возвращает тело как бинарный объект (полезно для изображений, файлов).
Пример обработки:const response = await fetch('/api/user/1'); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`);
} const user = await response.json();
console.log(user.name);
Для отправки структурированных данных используется JSON:const userData = { name: 'Alex', email: 'alex@example.com' }; const response = await fetch('/api/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(userData)
});
Заголовок Content-Type: application/json обязателен, чтобы сервер корректно интерпретировал тело запроса.При работе с файлами или формами используется FormData:const formData = new FormData();
formData.append('email', 'alex@example.com');
formData.append('avatar', fileInput.files[0]); // File из &lt;input type="file"&gt; const response = await fetch('/api/upload', { method: 'POST', body: formData // Content-Type НЕ указывается — браузер установит его автоматически
});
Если вы укажете Content-Type вручную при использовании FormData, запрос может сломаться, так как браузер не сможет добавить необходимый boundary.Иногда API требует данные в формате HTML-форм:const data = { username: 'alex', password: 'secret' };
const params = new URLSearchParams(data); const response = await fetch('/login', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: params.toString()
});
Этот подход встречается реже, но полезен при интеграции с legacy-системами или простыми серверами.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22-1/отправка-запросов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22 1/Отправка запросов.md</guid><pubDate>Fri, 17 Apr 2026 10:40:46 GMT</pubDate></item><item><title><![CDATA[Тема №22. Типизация в React с TypeScript]]></title><description><![CDATA[В этой теме вы научитесь применять TypeScript в React-проектах — типизировать компоненты, пропсы, состояние и хуки. Поймёте, как типы помогают избежать ошибок при передаче данных между компонентами, и как использовать типизацию для повышения надёжности интерфейса в мобильных приложениях на React Native.
<a data-href="Типизация props в React" href="материалы/подтемы/секция-2.-react/тема-№22/типизация-props-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация props в React</a>
<br><a data-href="Типизация состояния (useState) в TypeScript" href="материалы/подтемы/секция-2.-react/тема-№22/типизация-состояния-(usestate)-в-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация состояния (useState) в TypeScript</a>
<br><a data-href="Типизация хуков в React" href="материалы/подтемы/секция-2.-react/тема-№22/типизация-хуков-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация хуков в React</a>
<br><a data-href="Типизация событий в React" href="материалы/подтемы/секция-2.-react/тема-№22/типизация-событий-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация событий в React</a> <br><a data-href="Практика №13. Социальная сеть - Часть 2. Миграция на TypeScript" href="задания/секция-2.-react/практика-№13.-социальная-сеть-часть-2.-миграция-на-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №13. Социальная сеть - Часть 2. Миграция на TypeScript</a>
<br><a data-href="Тема №23. Запросы к API в TypeScript" href="лекции/секция-2.-react/тема-№23.-запросы-к-api-в-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №23. Запросы к API в TypeScript</a>]]></description><link>лекции/секция-2.-react/тема-№22.-типизация-в-react-с-typescript.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №22. Типизация в React с TypeScript.md</guid><pubDate>Fri, 17 Apr 2026 10:26:23 GMT</pubDate></item><item><title><![CDATA[Тема №19. Асинхронность в JavaScript]]></title><description><![CDATA[В этой теме вы изучите асинхронное выполнение кода в JavaScript — механизм, позволяющий выполнять длительные операции (например, запросы к серверу, чтение файлов, таймеры) без блокировки основного потока. Поймёте, как работают коллбэки, промисы и async/await, и как правильно обрабатывать результаты асинхронных действий. Это фундамент для работы с API, загрузки данных и управления состоянием в мобильных приложениях.
<a data-href="Что такое асинхронность" href="материалы/подтемы/секция-2.-react/тема-№19/что-такое-асинхронность.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое асинхронность</a>
<br><a data-href="Коллбэки" href="материалы/подтемы/секция-2.-react/тема-№19/коллбэки.html" class="internal-link" target="_self" rel="noopener nofollow">Коллбэки</a>
<br><a data-href="Промисы (Promise)" href="материалы/подтемы/секция-2.-react/тема-№19/промисы-(promise).html" class="internal-link" target="_self" rel="noopener nofollow">Промисы (Promise)</a>
<br><a data-href="Async и await" href="материалы/подтемы/секция-2.-react/тема-№19/async-и-await.html" class="internal-link" target="_self" rel="noopener nofollow">Async и await</a>
<br><a data-href="Разница между await и then()" href="материалы/подтемы/секция-2.-react/тема-№19/разница-между-await-и-then().html" class="internal-link" target="_self" rel="noopener nofollow">Разница между await и then()</a>
<br><a data-href="Асинхронность и React" href="материалы/подтемы/секция-2.-react/тема-№19/асинхронность-и-react.html" class="internal-link" target="_self" rel="noopener nofollow">Асинхронность и React</a>
(пусто)<br><a data-href="Тема №20. Основы TypeScript" href="лекции/секция-2.-react/тема-№20.-основы-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №20. Основы TypeScript</a>]]></description><link>лекции/секция-2.-react/тема-№19.-асинхронность-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №19. Асинхронность в JavaScript.md</guid><pubDate>Fri, 17 Apr 2026 10:25:50 GMT</pubDate></item><item><title><![CDATA[Тема №17. Hooks в React]]></title><description><![CDATA[В этой теме вы изучите Hooks — функции, позволяющие использовать состояние и другие возможности React в функциональных компонентах. Поймёте, как работают основные встроенные хуки, когда и зачем их применять, а также принципы их использования: правила вызова, зависимостей и побочных эффектов. Это фундамент для написания чистого, переиспользуемого и эффективного кода в React-приложениях.
<a data-href="Что такое Hooks" href="материалы/подтемы/секция-2.-react/тема-№17/что-такое-hooks.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое Hooks</a>
<br><a data-href="Правила использования Hooks" href="материалы/подтемы/секция-2.-react/тема-№17/правила-использования-hooks.html" class="internal-link" target="_self" rel="noopener nofollow">Правила использования Hooks</a>
<br><a data-href="useEffect" href="материалы/подтемы/секция-2.-react/тема-№17/useeffect.html" class="internal-link" target="_self" rel="noopener nofollow">useEffect</a>
<br><a data-href="useContext" href="материалы/подтемы/секция-2.-react/тема-№17/usecontext.html" class="internal-link" target="_self" rel="noopener nofollow">useContext</a>
<br><a data-href="Пользовательские Hooks" href="материалы/подтемы/секция-2.-react/тема-№17/пользовательские-hooks.html" class="internal-link" target="_self" rel="noopener nofollow">Пользовательские Hooks</a> <br><a data-href="Практика №11. Игра-кликер" href="задания/секция-2.-react/практика-№11.-игра-кликер.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №11. Игра-кликер</a>
<br><a data-href="Тема №18. Routers в React" href="лекции/секция-2.-react/тема-№18.-routers-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №18. Routers в React</a>]]></description><link>лекции/секция-2.-react/тема-№17.-hooks-в-react.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №17. Hooks в React.md</guid><pubDate>Fri, 17 Apr 2026 10:25:37 GMT</pubDate></item><item><title><![CDATA[Форматы данных]]></title><description><![CDATA[Форматы данных определяют, как информация структурирована при передаче между клиентом и сервером. В веб- и мобильной разработке на TypeScript чаще всего используются JSON и FormData. XML встречается редко и упоминается только для общего понимания.JSON — это лёгкий текстовый формат для обмена данными, основанный на синтаксисе объектов JavaScript. Он стал стандартом де-факто для веб-API благодаря простоте, читаемости и нативной поддержке в JavaScript и TypeScript.Структура JSON включает:
Объекты: { "ключ": "значение" }
Массивы: [1, 2, 3] или [{"id": 1}, {"id": 2}]
Примитивы: строки ("text"), числа (42), логические значения (true, false), null
Пример корректного JSON:{ "id": 101, "name": "Maria", "isActive": true, "tags": ["user", "premium"]
}
В JavaScript/TypeScript объект преобразуется в JSON с помощью JSON.stringify(), а JSON-строка парсится в объект через JSON.parse(). При работе с fetch метод response.json() автоматически вызывает JSON.parse().XML — это текстовый формат, использующий теги для структурирования данных, похожий на HTML. Пример:&lt;user&gt; &lt;id&gt;101&lt;/id&gt; &lt;name&gt;Maria&lt;/name&gt; &lt;isActive&gt;true&lt;/isActive&gt;
&lt;/user&gt;
Хотя XML поддерживает строгую валидацию через XSD-схемы и метаданные, он громоздок и неудобен для обработки в JavaScript. Современные приложения почти не используют XML. Его знание требуется только при интеграции с устаревшими системами.FormData — это специальный объект в JavaScript, предназначенный для отправки данных в формате multipart/form-data. Он используется, когда нужно передать файлы (например, изображения) вместе с текстовыми полями.Создание и использование:const formData = new FormData();
formData.append('email', 'user@example.com');
formData.append('avatar', file); // file — объект File из input[type="file"]
При отправке через fetch заголовок Content-Type не указывается вручную — среда выполнения автоматически установит его со значением multipart/form-data; boundary=....FormData применяется при работе с формами, содержащими файлы, например, при загрузке аватара пользователя через HTML-форму в веб-приложении.Иногда встречаются:
application/x-www-form-urlencoded — формат HTML-форм, где данные кодируются как key1=value1&amp;key2=value2. Используется редко в API, чаще в legacy-системах.
Plain text или бинарные форматы (например, image/png) — при загрузке или скачивании файлов напрямую.
В рамках курса основное внимание уделяется JSON и FormData, так как они покрывают подавляющее большинство сценариев работы с API в приложениях на React.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22-1/форматы-данных.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22 1/Форматы данных.md</guid><pubDate>Fri, 17 Apr 2026 10:23:34 GMT</pubDate></item><item><title><![CDATA[Другие виды server-client API]]></title><description><![CDATA[Помимо классических HTTP-интерфейсов (REST, RPC), существуют и другие способы взаимодействия между клиентом и сервером. Они решают специфические задачи, такие как передача данных в реальном времени или эффективная работа с графами данных.WebSocket — это протокол, обеспечивающий постоянное двустороннее соединение между клиентом и сервером поверх TCP. В отличие от HTTP, где каждое взаимодействие состоит из запроса и ответа, WebSocket позволяет обеим сторонам отправлять сообщения в любое время без необходимости устанавливать новое соединение.Основное применение: чаты, онлайн-игры, биржевые котировки, совместное редактирование документов.
Особенность: требует отдельного серверного стека (не обрабатывается обычными REST-роутами).
Язык подключения: ws:// или wss:// (защищённый).Server-Sent Events — это технология, при которой сервер может отправлять обновления клиенту по уже установленному HTTP-соединению. В отличие от WebSocket, SSE — это односторонний канал: данные идут только от сервера к клиенту.Преимущества:
Работает поверх стандартного HTTP/HTTPS
Автоматически восстанавливает соединение при разрыве
Поддерживается большинством браузеров
Проще в реализации на сервере
Используется для уведомлений, лент событий, обновления статусов.
Клиентская часть в браузере: объект EventSource.GraphQL — это язык запросов и среда выполнения, разработанная Facebook*. Вместо множества фиксированных эндпоинтов клиент отправляет запрос к одному URL, описывая точную структуру данных, которые ему нужны.Преимущества:
Клиент получает ровно то, что запрашивает (нет over-fetching или under-fetching)
Документированность через интроспекцию
Возможность агрегировать данные из нескольких источников
GraphQL может использовать как HTTP (для запросов и мутаций), так и WebSocket/SSE (для подписок на изменения).*Признана в России очень плохой организациейgRPC — это высокопроизводительный RPC-фреймворк от Google, использующий HTTP/2 и Protocol Buffers в качестве формата сериализации. Он обеспечивает строгую типизацию и генерацию кода для клиента и сервера.Применяется в микросервисных архитектурах, где важны скорость и надёжность.
Менее удобен для браузерных клиентов (требует прокси или WebAssembly), но хорошо подходит для мобильных приложений и backend-to-backend взаимодействий.SOAP (Simple Object Access Protocol) — старый протокол на основе XML, популярный в корпоративных системах 2000-х годов. Использует строгие схемы (WSDL) и поддерживает сложные функции: безопасность, транзакции, маршрутизация.Сегодня почти не используется в мобильной и веб-разработке из-за громоздкости и сложности по сравнению с REST и JSON.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22-1/другие-виды-server-client-api.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22 1/Другие виды server-client API.md</guid><pubDate>Fri, 17 Apr 2026 10:18:03 GMT</pubDate></item><item><title><![CDATA[Что такое API]]></title><description><![CDATA[Интерфейс прикладного программирования (API - Application Programming Interface) — это набор правил и точек взаимодействия, через которые одна программа может использовать функции или данные другой программы. В контексте веб-разработки и мобильных приложений под API обычно понимают веб-API: совокупность URL-адресов (эндпоинтов), к которым клиент может отправлять HTTP-запросы для получения или изменения данных.Веб-API работает по принципу «запрос — ответ». Клиент (приложение) отправляет запрос на определённый адрес, указывая метод (GET, POST и т.д.), заголовки и, при необходимости, тело запроса. Сервер обрабатывает этот запрос и возвращает ответ — как правило, в формате JSON.Примеры типичных эндпоинтов:
GET /api/users — получить список пользователей
POST /api/login — отправить учётные данные для входа
PUT /api/profile — обновить профиль пользователя
Большинство современных веб-API следуют стилю проектирования REST (Representational State Transfer). REST не является протоколом, а скорее набором рекомендаций: использование стандартных HTTP-методов, отсутствие состояния между запросами, ресурсно-ориентированная структура URL. Хотя в этой теме мы не углубляемся в REST, важно понимать, что большинство API, с которыми вы будете работать, будут REST-подобными.В мобильных и веб приложениях API особенно важен, потому что само приложение не хранит данные локально в полном объёме. Вместо этого оно запрашивает их у сервера через API, отображает пользователю и отправляет обратно изменения. Это позволяет синхронизировать данные между устройствами и централизованно управлять бизнес-логикой.
Работает поверх HTTP/HTTPS
Использует стандартные методы: GET (чтение), POST (создание), PUT/PATCH (обновление), DELETE (удаление)
Обычно возвращает данные в формате JSON
Требует аутентификации (часто через заголовок Authorization)
Документируется (например, с помощью Swagger или Postman)
Но, помимо классического HTTP(S)-API, существуют и <a data-tooltip-position="top" aria-label="Другие виды server-client API" data-href="Другие виды server-client API" href="материалы/подтемы/секция-2.-react/тема-№22-1/другие-виды-server-client-api.html" class="internal-link" target="_self" rel="noopener nofollow">другие виды API</a>.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22-1/что-такое-api.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22 1/Что такое API.md</guid><pubDate>Fri, 17 Apr 2026 10:14:27 GMT</pubDate></item><item><title><![CDATA[Практика №13. Социальная сеть - Часть 2. Миграция на TypeScript]]></title><description><![CDATA[Переписать одностраничное веб-приложение (SPA), разработанное в рамках задания №12, с использованием TypeScript вместо JavaScript. Проект должен по-прежнему быть основан на React + Vite, использовать статические mock-данные, и сохранять всю функциональность, реализованную ранее. Все компоненты, хуки, утилиты и маршруты должны быть типизированы. Репозиторий на GitHub должен называться: Group_LastName_task-13 (или, перенести прошлую версию на ветку "javascript" и продолжать работать в Group_LastName_task-12).Это не просто добавление расширения .ts — необходимо корректно использовать систему типов TypeScript для повышения надёжности и читаемости кода.(пусто)
Использовать ту же архитектуру, что и в задании №12.
Все файлы с логикой должны иметь расширение .tsx или .ts.
Разделение на компоненты, хуки, утилиты и типы должно быть сохранено или улучшено. Создать интерфейсы или типы для всех сущностей из ER-диаграммы: User
Post
Comment
Like
Friendship Использовать эти типы во всех компонентах, хуках и утилитах.
Все mock-данные должны быть импортированы с корректной типизацией (например, через as const или явное указание типа). Все пользовательские хуки (useAuth, usePosts, useComments и т.д.) должны быть полностью типизированы.
Функции-утилиты (поиск, фильтрация, обновление состояния) должны принимать и возвращать значения с чётко определёнными типами. Все маршруты и параметры (например, userId в URL) должны быть типизированы.
Использовать useParams, useNavigate и другие хуки с учётом типов. Состояния (useState, useReducer) должны иметь явно заданные типы.
Избегать использования any или unknown без веской причины. Всё, что работало в задании №12, должно работать и здесь: Авторизация/выход
Просмотр постов, профилей, комментариев
Создание/редактирование/удаление постов и комментариев
Лайки, заявки в друзья, поиск
Переключение темы (если была реализована)
Страница 404
При желании можно доработать то что не удалось в рамках №12 задания. Нужно минимально использовать // @ts-ignore или отключать проверки TypeScript без крайней необходимости.
Запрещено оставлять неявную типизацию (implicit any).
Разрешено использовать только те библиотеки, которые уже были в проекте №12 (включая react-router-dom).
2 практические сессии После сессии 1 дедлайн: 75% от максимального балла После сессии 2: 50% После сессии 3: 25%
После сессии 3: 25%
]]></description><link>задания/секция-2.-react/практика-№13.-социальная-сеть-часть-2.-миграция-на-typescript.html</link><guid isPermaLink="false">Задания/Секция 2. React/Практика №13. Социальная сеть - Часть 2. Миграция на TypeScript.md</guid><pubDate>Fri, 17 Apr 2026 09:40:35 GMT</pubDate></item><item><title><![CDATA[Практика №12. Социальная сеть - Часть 1. Верстка]]></title><description><![CDATA[Разработать одностраничное веб-приложение (SPA) на React с использованием Vite и JavaScript, имитирующее базовую социальную сеть. Все данные - статические (mock), без подключения к бэкенду. Структура проекта должна соответствовать стандартной архитектуре React + Vite. Репозиторий на GitHub должен называться: Group_LastName_task-12.
Заготовка проекта react-project.
(Материалы/Заготовки под практики/react-project.zip)
Для проектирования диаграмм: <a rel="noopener nofollow" class="external-link is-unresolved" href="https://mermaid.live" target="_self">https://mermaid.live</a>
<br>Для создания дизайна: <a rel="noopener nofollow" class="external-link is-unresolved" href="https://www.figma.com" target="_self">https://www.figma.com</a>
Примеры данных:
(`Материалы/Заготовки под практики/task_12-13_data_example.json)
Трилогия задания включает в себя разработку фронта упрощенной социальной сети используя React. В рамках этой части необходимо продумать и реализовать структуру сайта используя react-router-dom, ванильный JavaScript и React. Внешних подключений (в т.ч. к бэкэнду и БД) не предусмотрено, вместо этого необходимо использовать заготовленные заранее данные из JSON файлов (см. ресурсы/примеры данных). Дизайн, название и структуру сайта необходимо придумать самостоятельно, ниже будет пример.Написать хуки и набор утилит для реализации следующей функциональности для ролей:
Просматривать список постов с главной страницы;
Просматривать страницу любого пользователя;
Просматривать список постов от конкретного пользователя (в рамках страницы пользователя);
Просматривать список друзей пользователя;
Просматривать посты (в т.ч. количество лайков, список комментариев и их общее количество).
Искать пользователей по имени и никнейму;
Авторизоваться (без регистрации!). Редактировать свой профиль (фотографию, описание);
Создавать новые посты и редактировать свои старые;
Писать комментарии под постами;
Лайкать посты;
Удалять свои комментарии;
Удалять комментарии под своими постами;
Удалять свои посты;
Отправлять новые заявки в друзья;
Принимать и отклонять заявки от других пользователей;
Выходить из своего профиля.
На стороне "предположительного" бэкенда данные хранятся в следующем виде:
Необходимо использовать данные из предоставленного JSON (их можно редактировать) с учётом того что настоящий бэкенд может предоставлять другие эндпоинты.
Веб-приложение не должно менять данные внутри JSON, "обновление" данных, например добавление лайка, должно происходить только в рамках компонента.
Авторизация в будущем будет реализовано при помощи бэкэнда, поэтому проверки пароля не должно быть. Сессия должна храниться в браузере при помощи cookie файлов.
Все мутированные данные и состояния, кроме изменения темы, должны сбрасываться при перезагрузке страницы
Навигация между страницами осуществляется без перезагрузки страницы при помощи react-router-dom
Запрещено использовать внешние библиотеки и API кроме тех которые предоставлены в заготовленном проекте. Ресурсы, такие как: изображения, шрифты, аудио - должны быть доступны при офлайн запуске (находится в папке public)
Запрещено использовать глобальные переменные вне компонентов.
UX/UI должен быть удобным и визуально качественно проработаны (использовать css)
Структура проекта должна находится в разделенных файлах и в соответствующих директориях (все компоненты в одном файле нельзя!)
При реализации должна быть история коммитов
Необходимо добавить страницы вроде 404 Предоставление Figma макета сайта
Реализовать переключение темы (светлая/тёмная) в разделе «Настройки». Тема применяется ко всему приложению и сохраняется между перезагрузками страницы. Должны быть видны чёткие визуальные различия между темами (цвет фона, текста, карточек).
5 практические сессии После сессии 1 дедлайн: 75% от максимального балла После сессии 2: 50% После сессии 3: 25%
После сессии 3: 25%
]]></description><link>задания/секция-2.-react/практика-№12.-социальная-сеть-часть-1.-верстка.html</link><guid isPermaLink="false">Задания/Секция 2. React/Практика №12. Социальная сеть - Часть 1. Верстка.md</guid><pubDate>Fri, 17 Apr 2026 09:35:38 GMT</pubDate></item><item><title><![CDATA[Приведение типов]]></title><description><![CDATA[Приведение типов (type assertion) в TypeScript — это механизм, с помощью которого разработчик явно указывает компилятору, какого типа значение на самом деле является. Это не влияет на выполнение кода (типы исчезают при транспиляции), но помогает обойти ограничения вывода типов в ситуациях, когда программист знает больше, чем компилятор.Часто возникает при работе с DOM, API или динамическими структурами, где TypeScript не может точно определить тип:const element = document.getElementById("my-input");
// Тип element: HTMLElement | null element.value; // Ошибка: HTMLElement не имеет свойства value
Здесь мы знаем, что элемент — это &lt;input&gt;, но TypeScript видит только общий тип HTMLElement. Чтобы получить доступ к value, нужно уточнить тип.const input = &lt;HTMLInputElement&gt;document.getElementById("my-input");
Этот синтаксис не работает в JSX/TSX (например, в React), поэтому его избегают.const input = document.getElementById("my-input") as HTMLInputElement;
console.log(input.value); // теперь доступно
Этот вариант совместим с JSX и считается стандартом.Приведение типов не выполняет проверок во время выполнения. Оно говорит компилятору: «доверься мне». Если предположение неверно — ошибка проявится только при запуске:const elem = document.getElementById("some-div") as HTMLInputElement;
console.log(elem.value); // ошибка во время выполнения, если это не input
Поэтому приведение следует использовать осторожно и только тогда, когда вы уверены в типе.Иногда нужно наоборот — сделать тип менее специфичным. Например, для совместимости с функцией, принимающей общий тип:function logElement(el: HTMLElement) { console.log(el.tagName);
} const button = document.querySelector("button") as HTMLButtonElement;
logElement(button as HTMLElement); // безопасно: HTMLButtonElement ⊂ HTMLElement
В таких случаях приведение корректно, так как иерархия типов соблюдена.Если вы не уверены в типе, лучше использовать проверку вместо приведения:const el = document.getElementById("my-input");
if (el instanceof HTMLInputElement) { console.log(el.value); // безопасно, без приведения
}
Этот подход сохраняет безопасность TypeScript и предпочтителен при работе с неопределёнными данными. Но из-за того что instanceof не работает с обычными объектами, созданных через литерал {} а только с конструкторами (классами или функции-конструкторы) - в рамках этого предмета мы не будем использовать данный оператор.]]></description><link>материалы/подтемы/секция-2.-react/тема-№20/приведение-типов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №20/Приведение типов.md</guid><pubDate>Fri, 17 Apr 2026 09:25:40 GMT</pubDate></item><item><title><![CDATA[Вывод и явное указание типов]]></title><description><![CDATA[TypeScript может определять типы автоматически или принимать их от разработчика. Эти два подхода — вывод типов и явное указание — дополняют друг друга и используются в зависимости от контекста.Когда вы объявляете переменную и сразу присваиваете ей значение, TypeScript автоматически определяет её тип:let message = "Hello"; // тип: string
let count = 42; // тип: number
let isActive = true; // тип: boolean
Вывод работает не только для переменных, но и для возвращаемых значений функций:function add(a: number, b: number) { return a + b; // тип возврата: number
}
Этот механизм позволяет писать меньше кода без потери безопасности: типы проверяются, но не загромождают синтаксис.Иногда TypeScript не может вывести тип — например, если переменная объявлена без начального значения или получает данные из внешнего источника:let userId; // тип: any (небезопасно!)
userId = fetchFromAPI(); // ошибка возможна
Чтобы избежать этого, тип указывают явно:let userId: string;
userId = fetchUserId(); // компилятор знает: ожидается строка
Явное указание также используется в сигнатурах функций для параметров и возвращаемого значения:function greet(name: string): string { return "Hello, " + name;
}
Это делает контракт функции понятным без чтения её тела.
Используйте вывод типов, когда значение известно сразу — это делает код короче и чище.
Используйте явное указание, когда: переменная инициализируется позже,
функция принимает или возвращает данные, тип которых важен для интерфейса,
вы работаете с внешними данными (например, API),
хотите усилить читаемость и защиту от ошибок. Явное указание типов не «переопределяет» вывод — оно лишь задаёт ожидания заранее. Если присвоить значение несовместимого типа, компилятор выдаст ошибку.]]></description><link>материалы/подтемы/секция-2.-react/тема-№20/вывод-и-явное-указание-типов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №20/Вывод и явное указание типов.md</guid><pubDate>Fri, 17 Apr 2026 09:18:34 GMT</pubDate></item><item><title><![CDATA[Тема №20. Основы TypeScript]]></title><description><![CDATA[В этой теме вы познакомитесь с TypeScript как языком, расширяющим JavaScript статической типизацией. Поймёте, зачем он нужен, как он соотносится с JavaScript и почему его используют в крупных проектах. Вы узнаете, как TypeScript транспилируется в JavaScript, и научитесь писать базовый типизированный код без углубления в сложные конструкции.
<a data-href="Что такое TypeScript" href="материалы/подтемы/секция-2.-react/тема-№20/что-такое-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое TypeScript</a>
<br><a data-href="Настройка проекта с TypeScript" href="материалы/подтемы/секция-2.-react/тема-№20/настройка-проекта-с-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Настройка проекта с TypeScript</a>
<br><a data-href="Базовые типы в TypeScript" href="материалы/подтемы/секция-2.-react/тема-№20/базовые-типы-в-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Базовые типы в TypeScript</a>
<br><a data-href="Вывод и явное указание типов" href="материалы/подтемы/секция-2.-react/тема-№20/вывод-и-явное-указание-типов.html" class="internal-link" target="_self" rel="noopener nofollow">Вывод и явное указание типов</a>
<br><a data-href="Приведение типов" href="материалы/подтемы/секция-2.-react/тема-№20/приведение-типов.html" class="internal-link" target="_self" rel="noopener nofollow">Приведение типов</a>
(пусто)<br><a data-href="Тема №21. Типизация структур данных в TypeScript" href="лекции/секция-2.-react/тема-№21.-типизация-структур-данных-в-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №21. Типизация структур данных в TypeScript</a>]]></description><link>лекции/секция-2.-react/тема-№20.-основы-typescript.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №20. Основы TypeScript.md</guid><pubDate>Fri, 17 Apr 2026 09:18:24 GMT</pubDate></item><item><title><![CDATA[Базовые типы в TypeScript]]></title><description><![CDATA[TypeScript предоставляет систему типов, которая позволяет явно указывать или автоматически выводить типы переменных, параметров функций и возвращаемых значений. Это помогает избежать ошибок и делает код понятнее.Основные примитивные типы в TypeScript совпадают с соответствующими значениями в JavaScript:
string — текстовые данные number — числа (все числа в JS/TS имеют тип number, целые и дробные) boolean — логические значения (true / false) null — отсутствие значения (явный null) undefined — значение по умолчанию для неинициализированных переменных Пример:let name: string = "Alice";
let age: number = 30;
let isActive: boolean = true;
TypeScript обычно выводит эти типы автоматически, поэтому явное указание часто избыточно:let name = "Alice"; // TypeScript выводит: string
Тип any отключает проверку типов. Переменная типа any может принимать любое значение и использоваться в любом контексте:let data: any = "text";
data = 42; // допустимо
data.toUpperCase(); // допустимо, но может вызвать ошибку во время выполнения
Использование any нарушает преимущества TypeScript и рекомендуется только при миграции старого кода или работе с динамическими данными, когда тип невозможно определить.Тип unknown представляет значение, тип которого неизвестен. В отличие от any, он безопасен: TypeScript требует проверки перед использованием:let data: unknown = "text"; // Ошибка: нельзя вызывать методы на unknown без проверки
// data.toUpperCase(); if (typeof data === "string") { console.log(data.toUpperCase()); // теперь безопасно
}
unknown — предпочтительная замена any при работе с внешними данными (например, ответами от API).Тип void означает, что функция ничего не возвращает:function logMessage(message: string): void { console.log(message);
}
Если функция не имеет оператора return или содержит return; без значения, её тип возвращаемого значения — void.Тип never используется для функций, которые никогда не завершаются нормально — например, всегда выбрасывают ошибку или зацикливаются:function throwError(message: string): never { throw new Error(message);
} function infiniteLoop(): never { while (true) {}
}
Тип never также возникает в случае исчерпывающей проверки типов (например, в switch), но это выходит за рамки базового уровня.]]></description><link>материалы/подтемы/секция-2.-react/тема-№20/базовые-типы-в-typescript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №20/Базовые типы в TypeScript.md</guid><pubDate>Fri, 17 Apr 2026 09:16:32 GMT</pubDate></item><item><title><![CDATA[task_12-13_data_example]]></title><link>материалы/заготовки-под-практики/task_12-13_data_example.html</link><guid isPermaLink="false">Материалы/Заготовки под практики/task_12-13_data_example.json</guid><pubDate>Wed, 11 Mar 2026 07:42:07 GMT</pubDate></item><item><title><![CDATA[Типизация событий в React]]></title><description><![CDATA[Типизация событий в React позволяет точно описывать объект события (event), который передаётся в обработчики. Это даёт доступ к правильным свойствам (например, e.target.value) и предотвращает ошибки при работе с формами, кликами и другими взаимодействиями.Все события в React обёрнуты в синтетические объекты, предоставляемые библиотекой. Их типы находятся в пространстве имён React. Пример:function handleChange(e: React.ChangeEvent&lt;HTMLInputElement&gt;) { console.log(e.target.value);
}
Здесь React.ChangeEvent&lt;HTMLInputElement&gt; говорит TypeScript, что:
событие — это изменение значения (change),
цель события — HTML-элемент типа &lt;input&gt;,
у e.target есть свойство value. React.ChangeEvent&lt;HTMLInputElement&gt; — для полей ввода.
React.FormEvent&lt;HTMLFormElement&gt; — для отправки формы.
React.MouseEvent&lt;HTMLButtonElement&gt; — для кликов по кнопке.
React.KeyboardEvent&lt;HTMLInputElement&gt; — для нажатий клавиш в поле ввода.
Пример обработчика клика:function handleClick(e: React.MouseEvent&lt;HTMLButtonElement&gt;) { e.preventDefault(); console.log('Кнопка нажата');
}
Если использовать общий тип any или не указывать тип вообще, IDE не сможет предложить автодополнение, а TypeScript не защитит от обращения к несуществующим свойствам:// Плохо:
function badHandler(e) { console.log(e.target.valu); // опечатка — ошибка не будет найдена
} // Хорошо:
function goodHandler(e: React.ChangeEvent&lt;HTMLInputElement&gt;) { console.log(e.target.valu); // ошибка на этапе компиляции
}
Если обработчик используется в нескольких местах, можно вынести тип:type InputChangeHandler = (e: React.ChangeEvent&lt;HTMLInputElement&gt;) =&gt; void; const handleChange: InputChangeHandler = (e) =&gt; { setValue(e.target.value);
};
Это особенно полезно в больших компонентах или при написании кастомных хуков.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22/типизация-событий-в-react.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22/Типизация событий в React.md</guid><pubDate>Thu, 19 Feb 2026 16:09:30 GMT</pubDate></item><item><title><![CDATA[Типизация хуков в React]]></title><description><![CDATA[Типизация хуков в React с TypeScript позволяет точно описывать данные, с которыми работают useRef, useContext и другие встроенные хуки. Это повышает надёжность кода и упрощает его поддержку.Хук useRef принимает generic-параметр, указывающий тип значения, хранящегося в .current:const inputRef = useRef&lt;HTMLInputElement&gt;(null);
Теперь при обращении к inputRef.current доступны только методы и свойства HTMLInputElement. Например:inputRef.current?.focus(); // TypeScript знает, что focus существует
Если не указать тип, .current будет иметь тип any | null, и проверки типов не будет.Для хранения обычных значений (не DOM-элементов) указывается нужный тип:const renderCount = useRef&lt;number&gt;(0);
renderCount.current += 1;
При использовании контекста необходимо указать тип значения, которое передаётся через Provider:interface Theme { primary: string; background: string;
} const ThemeContext = createContext&lt;Theme | null&gt;(null); // В компоненте:
const theme = useContext(ThemeContext); // тип Theme | null
Если не указать тип при создании контекста, TypeScript не сможет проверить корректность использования значений из контекста.
Примечание: если контекст всегда инициализирован (например, через createContext с дефолтным значением), можно не использовать | null.
Сам useEffect не требует явной типизации — он работает с функцией без возвращаемого значения. Однако зависимости (deps) должны соответствовать реальным используемым переменным. TypeScript не проверяет содержимое массива зависимостей напрямую, но поскольку все переменные внутри эффекта уже имеют строгие типы (из useState, props и т.д.), это обеспечивает косвенную безопасность.Все хуки, которые хранят или передают данные, должны иметь явно указанный тип. Это гарантирует:
корректную работу с DOM-элементами,
защиту от обращения к несуществующим свойствам,
чёткое понимание структуры данных при чтении кода.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№22/типизация-хуков-в-react.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22/Типизация хуков в React.md</guid><pubDate>Thu, 19 Feb 2026 16:02:00 GMT</pubDate></item><item><title><![CDATA[Типизация состояния (useState) в TypeScript]]></title><description><![CDATA[Типизация состояния в React с помощью хука useState позволяет явно указать, какие значения может принимать переменная состояния. Это предотвращает ошибки при присвоении несовместимых типов и улучшает читаемость кода.Хук useState — обобщённая (generic) функция. Тип состояния указывается в угловых скобках:const [count, setCount] = useState&lt;number&gt;(0);
Здесь TypeScript знает, что count всегда будет числом, а setCount принимает только число.Если начальное значение не позволяет однозначно определить тип (например, null), тип нужно указывать явно:const [user, setUser] = useState&lt;User | null&gt;(null);
Без явного указания TypeScript выведет тип как null, и позже нельзя будет присвоить объект типа User.Часто состояние может иметь несколько допустимых форм. Например, данные могут быть либо загружены, либо ещё нет:type LoadingState = 'idle' | 'loading' | 'success' | 'error'; const [status, setStatus] = useState&lt;LoadingState&gt;('idle');
Такой подход делает логику компонента более предсказуемой и защищённой от случайных значений.Для сложных структур также требуется явное указание:interface Todo { id: string; text: string; completed: boolean;
} const [todos, setTodos] = useState&lt;Todo[]&gt;([]);
Если не указать тип, TypeScript может вывести его как never[], и добавление элементов вызовет ошибку.Если передать начальное значение с чётким типом, дополнительная аннотация не нужна:const [name, setName] = useState(''); // тип string выводится автоматически
Однако при работе с React Native и особенно в крупных проектах рекомендуется указывать тип явно — это упрощает поддержку и рефакторинг.]]></description><link>материалы/подтемы/секция-2.-react/тема-№22/типизация-состояния-(usestate)-в-typescript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22/Типизация состояния (useState) в TypeScript.md</guid><pubDate>Thu, 19 Feb 2026 15:58:02 GMT</pubDate></item><item><title><![CDATA[Типизация props в React]]></title><description><![CDATA[Типизация props — это основа безопасной передачи данных между компонентами в React при использовании TypeScript. Она позволяет явно описать, какие данные ожидает компонент, и предотвращает ошибки на этапе разработки.Для описания структуры пропсов используется interface. Это особенно удобно, когда компонент принимает объект с несколькими полями:interface ButtonProps { title: string; onClick: () =&gt; void;
}
Здесь компонент ожидает строку title и функцию onClick, которая ничего не возвращает.После объявления интерфейса его нужно указать в параметрах функционального компонента:function Button({ title, onClick }: ButtonProps) { return &lt;button onClick={onClick}&gt;{title}&lt;/button&gt;;
}
Если пропс может отсутствовать, его помечают знаком вопроса:interface ButtonProps { title: string; onClick: () =&gt; void; disabled?: boolean;
}
Теперь disabled можно не передавать. При использовании внутри компонента TypeScript будет считать его типом boolean | undefined.Можно задать значение по умолчанию прямо в деструктуризации:function Button({ title, onClick, disabled = false }: ButtonProps) { return ( &lt;button disabled={disabled} onPress={onClick}&gt; {title} &lt;/button&gt; );
}
TypeScript корректно поймёт, что внутри функции disabled имеет тип boolean, даже если он был опциональным в интерфейсе.
Не используйте any для обхода типизации — это сводит на нет все преимущества TypeScript.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№22/типизация-props-в-react.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №22/Типизация props в React.md</guid><pubDate>Thu, 19 Feb 2026 15:55:20 GMT</pubDate></item><item><title><![CDATA[Обобщённые типы (Generics)]]></title><description><![CDATA[Обобщённые типы (generics) в TypeScript позволяют писать переиспользуемый и типобезопасный код, не привязываясь к конкретному типу данных. Они особенно полезны при работе с функциями, коллекциями и компонентами, которые должны работать с разными типами, сохраняя при этом точность типизации.Рассмотрим функцию, которая возвращает переданное ей значение:function identity(arg: any): any { return arg;
}
Такая функция компилируется, но теряет информацию о типе. Если передать строку, TypeScript не сможет гарантировать, что на выходе тоже строка — только any.Это нарушает принцип типовой безопасности.Generics решают эту проблему, позволяя «захватывать» тип аргумента и использовать его в аннотации возвращаемого значения.function identity&lt;T&gt;(arg: T): T { return arg;
}
Здесь &lt;T&gt; — это параметр типа. Он работает как переменная для типа. При вызове функции TypeScript выводит T автоматически:const output = identity("привет"); // T выведено как string
// output имеет тип string
Можно также указать тип явно:const output = identity&lt;string&gt;("привет");
Часто generics используются при работе с коллекциями. Например, функция, возвращающая длину массива:function getLength&lt;T&gt;(items: T[]): number { return items.length;
} const numbers = [1, 2, 3];
const count = getLength(numbers); // T = number, items: number[]
Функция работает с любым массивом, но сохраняет знание о том, какие элементы в нём лежат (даже если сама их не использует).Иногда нужно гарантировать, что generic-тип имеет определённые свойства. Для этого используется ограничение через extends.interface HasLength { length: number;
} function logLength&lt;T extends HasLength&gt;(arg: T): T { console.log(arg.length); return arg;
} logLength("текст"); // OK: у строки есть length
logLength([1, 2, 3]); // OK: у массива есть length
// logLength(42); // Ошибка: число не имеет length
Это позволяет безопасно использовать свойства внутри функции.Generics можно использовать не только в функциях, но и в определении типов:type ApiResponse&lt;T&gt; = { data: T; status: number;
}; interface Repository&lt;T&gt; { save(item: T): void; findById(id: string): T | null;
}
Пример использования:const userResponse: ApiResponse&lt;User&gt; = { data: { name: "Иван", email: "ivan@example.com" }, status: 200
};
Функция или тип может принимать несколько generic-параметров:function pair&lt;A, B&gt;(a: A, b: B): [A, B] { return [a, b];
} const result = pair("имя", 25); // тип: [string, number]
Порядок и имена параметров (A, B, T, U и т.д.) выбираются по смыслу или соглашению.]]></description><link>материалы/подтемы/секция-2.-react/тема-№21/обобщённые-типы-(generics).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №21/Обобщённые типы (Generics).md</guid><pubDate>Thu, 19 Feb 2026 14:10:44 GMT</pubDate></item><item><title><![CDATA[Тема №21. Типизация структур данных в TypeScript]]></title><description><![CDATA[В этой теме вы изучите, как описывать сложные структуры данных — объекты, массивы, функции — с помощью типов в TypeScript. Поймёте, как определять интерфейсы и типы, работать с коллекциями и использовать объединения и пересечения для точного описания допустимых значений. Это необходимо для корректной работы с API, пропсами и состоянием в React-приложениях.
<a data-href="Типизация объектов" href="материалы/подтемы/секция-2.-react/тема-№21/типизация-объектов.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация объектов</a>
<br><a data-href="Типизация массивов" href="материалы/подтемы/секция-2.-react/тема-№21/типизация-массивов.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация массивов</a>
<br><a data-href="Типизация функций" href="материалы/подтемы/секция-2.-react/тема-№21/типизация-функций.html" class="internal-link" target="_self" rel="noopener nofollow">Типизация функций</a>
<br><a data-href="Объединения и пересечения типов" href="материалы/подтемы/секция-2.-react/тема-№21/объединения-и-пересечения-типов.html" class="internal-link" target="_self" rel="noopener nofollow">Объединения и пересечения типов</a>
<br><a data-href="Обобщённые типы (Generics)" href="материалы/подтемы/секция-2.-react/тема-№21/обобщённые-типы-(generics).html" class="internal-link" target="_self" rel="noopener nofollow">Обобщённые типы (Generics)</a>
(пусто)<br><a data-href="Тема №22. Типизация в React с TypeScript" href="лекции/секция-2.-react/тема-№22.-типизация-в-react-с-typescript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №22. Типизация в React с TypeScript</a>]]></description><link>лекции/секция-2.-react/тема-№21.-типизация-структур-данных-в-typescript.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №21. Типизация структур данных в TypeScript.md</guid><pubDate>Thu, 19 Feb 2026 14:07:44 GMT</pubDate></item><item><title><![CDATA[Объединения и пересечения типов]]></title><description><![CDATA[Объединения и пересечения — это мощные инструменты TypeScript для комбинирования типов. Они позволяют точно описывать данные, которые могут принимать несколько форм или объединять свойства из разных источников.Объединение (union) означает, что значение может соответствовать одному из нескольких типов. Обозначается вертикальной чертой |.type ID = string | number; function printId(id: ID): void { console.log(`ID: ${id}`);
} printId("user_123"); // строка — допустимо
printId(42); // число — допустимо
Часто объединения используются с литералами для ограничения допустимых значений:type Status = "active" | "inactive" | "pending"; function updateStatus(status: Status): void { // ...
} updateStatus("active"); // OK
updateStatus("deleted"); // Ошибка: не входит в union
Такие типы делают код самодокументируемым и предотвращают ошибки при передаче недопустимых значений.Пересечение (intersection) создаёт тип, который объединяет все свойства из нескольких типов. Значение должно соответствовать всем указанным типам одновременно.interface User { name: string; email: string;
} interface Admin { role: string; permissions: string[];
} type AdminUser = User &amp; Admin; const admin: AdminUser = { name: "Алексей", email: "alex@example.com", role: "editor", permissions: ["read", "write"]
};
Пересечение особенно полезно при композиции пропсов в React-компонентах или при расширении базовых типов без наследования.Интерфейсы можно расширять через extends, но это работает только с другими интерфейсами. Пересечение работает с любыми типами — interface, type, примитивами и даже объединениями.type BaseProps = { className?: string };
type ButtonVariant = { variant: "primary" | "secondary" }; type ButtonProps = BaseProps &amp; ButtonVariant;
Это гибче, чем interface, особенно когда исходные типы определены как type.При работе с объединениями TypeScript требует убедиться, что операция допустима для всех возможных вариантов. Часто используется проверка типа через typeof или сравнение со строковыми литералами.function processValue(value: string | number): void { if (typeof value === "string") { console.log(value.toUpperCase()); } else { console.log(value.toFixed(2)); }
}
Без такой проверки TypeScript не позволит вызывать методы, специфичные только для одного из типов в объединении.]]></description><link>материалы/подтемы/секция-2.-react/тема-№21/объединения-и-пересечения-типов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №21/Объединения и пересечения типов.md</guid><pubDate>Thu, 19 Feb 2026 13:53:56 GMT</pubDate></item><item><title><![CDATA[Типизация функций]]></title><description><![CDATA[Типизация функций в TypeScript позволяет чётко определить, какие аргументы принимает функция и какое значение она возвращает. Это помогает избежать ошибок при вызове и упрощает поддержку кода.При объявлении функции после каждого параметра указывается его тип. После закрывающей скобки параметров — тип возвращаемого значения.function greet(name: string, age: number): string { return `Привет, ${name}! Тебе ${age} лет.`;
}
Если функция ничего не возвращает (например, только логирует данные), используется тип void:function logMessage(message: string): void { console.log(message);
}
Параметр можно сделать необязательным, добавив знак вопроса ? после его имени. Такой параметр может отсутствовать при вызове функции.function introduce(name: string, title?: string): string { if (title) { return `${name}, ${title}`; } return name;
} introduce("Анна"); // допустимо
introduce("Борис", "инженер"); // допустимо
Важно: опциональные параметры должны идти после обязательных.TypeScript позволяет задавать значения по умолчанию для параметров. В этом случае аннотация типа часто не требуется — компилятор выводит его автоматически.function createGreeting(name: string, greeting: string = "Привет"): string { return `${greeting}, ${name}!`;
}
Несмотря на наличие значения по умолчанию, тип параметра всё равно должен соответствовать возможным вызовам. Если вы передадите значение другого типа, возникнет ошибка.
Примечание: наличие значения по умолчанию делает параметр необязательным, даже без ?.
Стрелочные функции типизируются аналогично, но аннотация часто выносится отдельно или указывается в месте присваивания.const multiply = (a: number, b: number): number =&gt; a * b; // Или с явным типом переменной:
const divide: (x: number, y: number) =&gt; number = (x, y) =&gt; x / y;
Последний вариант редко используется напрямую, но полезен при описании типов коллбэков или пропсов.Иногда нужно описать форму функции без её реализации — например, для типа пропса или обратного вызова.type EventHandler = (event: string, payload: unknown) =&gt; void; const handleEvent: EventHandler = (event, data) =&gt; { console.log(`Событие: ${event}`, data);
};
Это особенно важно в React, где обработчики событий и коллбэки должны иметь строго определённую сигнатуру.]]></description><link>материалы/подтемы/секция-2.-react/тема-№21/типизация-функций.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №21/Типизация функций.md</guid><pubDate>Thu, 19 Feb 2026 13:52:59 GMT</pubDate></item><item><title><![CDATA[Типизация массивов]]></title><description><![CDATA[Типизация массивов в TypeScript позволяет точно указать, какие значения могут находиться внутри коллекции. Это предотвращает ошибки при работе с данными и делает код более предсказуемым.Самый распространённый способ описания массива — добавить [] после типа элемента. Например, массив строк описывается как string[].const names: string[] = ["Анна", "Борис", "Вера"];
const scores: number[] = [85, 92, 78];
Этот синтаксис читается как «массив значений типа string».TypeScript также поддерживает обобщённую (generic) форму записи: Array&lt;T&gt;, где T — тип элемента.const names: Array&lt;string&gt; = ["Анна", "Борис", "Вера"];
const scores: Array&lt;number&gt; = [85, 92, 78];
Обе формы эквивалентны. Однако в сообществе React и TypeScript чаще используется T[], так как она короче и проще для восприятия.Кортеж — это массив фиксированной длины, где каждый элемент имеет строго определённый тип. В отличие от обычного массива, порядок и типы элементов важны.type UserTuple = [string, number]; const user: UserTuple = ["Иван", 30]; // правильно
// const user2: UserTuple = [30, "Иван"]; // ошибка: типы не совпадают
// const user3: UserTuple = ["Иван"]; // ошибка: недостаточно элементов
Кортежи полезны, когда нужно вернуть из функции несколько значений разного типа или передать пару связанных данных.Хотя TypeScript не требует имён для элементов кортежа, их можно добавить в виде комментариев или использовать в современных версиях TS (4.0+) для лучшей документации:type UserData = [id: string, name: string, isActive: boolean]; const userData: UserData = ["u123", "Мария", true];
Это не влияет на типизацию, но улучшает понимание кода.Часто массив содержит объекты. В этом случае тип элемента — это интерфейс или алиас типа.interface Product { id: string; title: string; price: number;
} const products: Product[] = [ { id: "p1", title: "Ноутбук", price: 65000 }, { id: "p2", title: "Мышь", price: 1500 }
];
Такой подход обеспечивает безопасность при обращении к свойствам каждого элемента.]]></description><link>материалы/подтемы/секция-2.-react/тема-№21/типизация-массивов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №21/Типизация массивов.md</guid><pubDate>Thu, 19 Feb 2026 13:49:40 GMT</pubDate></item><item><title><![CDATA[Типизация объектов]]></title><description><![CDATA[Типизация объектов в TypeScript позволяет точно описать форму данных, с которыми работает приложение. Это особенно важно при работе с данными от сервера, состоянием компонентов и пропсами.Простейший способ описать объект — использовать литерал типа прямо в аннотации. Указываются имена свойств и их типы через двоеточие.const user: { name: string; age: number } = { name: "Алексей", age: 25
};
Такой подход работает для разовых случаев, но имеет существенный недостаток — литерал нельзя переиспользовать. Если нужно описать несколько объектов с одинаковой структурой, приходится копировать одно и то же описание.Представьте, что в приложении нужно работать с несколькими пользователями. Каждый раз писать { name: string; age: number } неудобно и приводит к дублированию кода. Для решения этой проблемы в TypeScript существуют два механизма — interface и type.Ключевое слово interface создаёт именованный контракт, описывающий структуру объекта. Это наиболее распространённый способ типизации объектов в TypeScript.interface User { name: string; email: string; age: number;
} const user1: User = { name: "Мария", email: "maria@example.com", age: 30
}; const user2: User = { name: "Иван", email: "ivan@example.com", age: 28
};
Интерфейсы можно расширять с помощью ключевого слова extends. Это позволяет создавать новые интерфейсы на основе существующих, добавляя дополнительные свойства.interface User { name: string; email: string;
} interface Admin extends User { role: string; permissions: string[];
} const admin: Admin = { name: "Администратор", email: "admin@site.com", role: "superuser", permissions: ["read", "write", "delete"]
};
Ключевое слово type создаёт псевдоним для любого типа данных, не только для объектов. С его помощью можно описывать примитивы, объединения, кортежи и сложные структуры.type User = { name: string; email: string; age: number;
}; const user: User = { name: "Елена", email: "elena@example.com", age: 22
};
Type может описывать не только объекты:type ID = string;
type Status = "active" | "inactive";
type Point = [number, number];
Оба подхода позволяют описывать объекты, но есть рекомендации по выбору.Используйте interface, когда:
Описываете форму объекта или класса
Планируете расширять тип через наследование
Работаете с пропсами компонентов в React
Используйте type, когда:
Нужно создать алиас для примитива или объединения типов
Описываете кортежи или другие сложные типы
Требуется выразить тип, который нельзя описать через интерфейс
В большинстве случаев для описания объектов данных предпочтительнее interface, так как он был создан специально для этой цели и поддерживает расширение.]]></description><link>материалы/подтемы/секция-2.-react/тема-№21/типизация-объектов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №21/Типизация объектов.md</guid><pubDate>Thu, 19 Feb 2026 13:41:31 GMT</pubDate></item><item><title><![CDATA[Практика №11. Игра-кликер]]></title><description><![CDATA[Разработать одностраничное веб-приложение «Кликер».
Оно обязано быть сделано при помощи React (vite), следовать правильному неймингу и иметь правильную структуру.
Приложение должно содержать игровое поле с персонажем, систему сбора монет, магазин улучшений и сохранение прогресса между сессиями. Репозиторий на GitHub должен называться: Group_LastName_task-11.<img alt="Pasted image 20260207130627.png" src="материалы/файлы/pasted-image-20260207130627.png" target="_self">Рекомендуется использовать заготовку из ресурсов.Заготовка проекта react-project.
(Материалы/Заготовки под практики/react-project.zip)
На главном экране отображается текущий баланс монет, количество монет за клик по персонажу и пассивный доход в секунду (изначально 1 и 0 соответственно).
По центру экрана расположен кликабельный персонаж (например, изображение или стилизованный блок). Каждый клик увеличивает баланс на текущее значение «монет за клик».
Ниже или рядом расположен магазин улучшений, содержащий как минимум 7 уникальных позиций. Каждая позиция имеет: Название,
Описание эффекта (например, «+3 монета за клик» или «+1 монеты в секунду»),
Цену в монетах. Улучшение можно приобрести только если баланс пользователя не меньше его цены. После покупки: Баланс уменьшается на стоимость улучшения,
Соответствующий параметр (монеты за клик или пассивный доход) увеличивается на указанную величину. Прогресс игры (баланс, значения параметров, состояние улучшений) должен автоматически сохраняться и восстанавливаться после перезагрузки страницы.
Должна быть кнопка «Сбросить прогресс», полностью удаляющая сохранённые данные и возвращающая игру к начальному состоянию.
Реализовать визуально привлекательный интерфейс: модальные окна для настроек и магазина, использовать тематическое оформление, анимации реакции на клик, эффекты при покупке улучшений или другие элементы, повышающие игровой опыт. Допускается использование CSS-стилей, SVG или встроенных изображений, но без внешних библиотек.5 практические сессии После сессии 1 дедлайн: 50% от максимального балла После сессии 2: 25% После сессии 3: 10%
]]></description><link>задания/секция-2.-react/практика-№11.-игра-кликер.html</link><guid isPermaLink="false">Задания/Секция 2. React/Практика №11. Игра-кликер.md</guid><pubDate>Sat, 07 Feb 2026 10:11:37 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20260207130627]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20260207130627.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20260207130627.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20260207130627.png</guid><pubDate>Sat, 07 Feb 2026 10:06:27 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Что такое TypeScript]]></title><description><![CDATA[TypeScript — это язык программирования, разработанный компанией Microsoft как надмножество JavaScript. Он добавляет к JavaScript статическую типизацию и другие возможности, которые помогают писать более надёжный и поддерживаемый код. Любая программа на JavaScript является корректной программой на TypeScript, что делает переход к нему постепенным и безопасным.В JavaScript типы переменных определяются во время выполнения (динамическая типизация). Это даёт гибкость, но может привести к ошибкам, которые проявляются только при запуске программы:function greet(name) { return "Hello, " + name.toUpperCase();
}
greet(); // вызов без аргумента → ошибка во время выполнения
TypeScript проверяет типы ещё до запуска программы (статическая типизация). Ошибки выявляются на этапе написания кода или сборки:function greet(name: string) { return "Hello, " + name.toUpperCase();
}
greet(); // ошибка компиляции: отсутствует обязательный аргумент
TypeScript не заменяет JavaScript. Наоборот, он полностью совместим с ним:
Любой JavaScript-файл можно переименовать в .ts — он останется рабочим.
Все существующие библиотеки JavaScript можно использовать в TypeScript.
TypeScript добавляет синтаксис для описания типов, но не меняет поведение самого языка.
Браузеры и среды выполнения (например, Node.js) понимают только JavaScript. Поэтому код на TypeScript должен быть преобразован (транспилирован) в JavaScript перед запуском. Это делает компилятор TypeScript (tsc):Исходный файл app.ts:const message: string = "Hello, TypeScript";
console.log(message);
После компиляции (tsc app.ts) получается app.js:var message = "Hello, TypeScript";
console.log(message);
Типы исчезают — они нужны только на этапе разработки.
Раннее обнаружение ошибок: многие ошибки находятся ещё до запуска программы.
Лучшее автодополнение: редакторы (VS Code, WebStorm и др.) предлагают точные подсказки благодаря информации о типах.
Самодокументируемый код: типы явно описывают, какие данные ожидаются и возвращаются.
Поддержка крупных проектов: упрощает рефакторинг и чтение чужого кода.
TypeScript особенно полезен в командной разработке и при создании сложных приложений, где важно минимизировать количество неожиданных ошибок.]]></description><link>материалы/подтемы/секция-2.-react/тема-№20/что-такое-typescript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №20/Что такое TypeScript.md</guid><pubDate>Wed, 04 Feb 2026 06:43:01 GMT</pubDate></item><item><title><![CDATA[Настройка проекта с TypeScript]]></title><description><![CDATA[Чтобы начать использовать TypeScript, необходимо настроить проект: установить компилятор, создать конфигурационный файл и (при необходимости) интегрировать TypeScript в существующий фреймворк, например React.TypeScript поставляется как пакет npm. Его можно установить глобально или локально в проекте. Рекомендуется устанавливать локально:npm install --save-dev typescript
После установки доступна команда npx tsc для запуска компилятора.Файл tsconfig.json управляет поведением компилятора TypeScript. Он указывает, какие файлы обрабатывать и как транспилировать код. Создать его можно командой:npx tsc --init
Эта команда генерирует базовый файл с закомментированными настройками. Основные опции:
target — версия JavaScript, в которую будет транспилироваться код (например, "ES2016", "ES2020").
outDir — папка, куда будут помещены скомпилированные .js-файлы.
strict — включает строгую проверку типов (рекомендуется всегда использовать).
Пример минимального tsconfig.json:{ "compilerOptions": { "target": "ES2020", "module": "commonjs", "strict": true, "outDir": "./dist", "rootDir": "./src" }, "include": ["src/**/*"]
}
После настройки можно компилировать проект командой:npx tsc
Для новых проектов на React проще всего использовать шаблоны с поддержкой TypeScript:
С Vite:
npm create vite@latest my-app -- --template react-ts С Create React App:
npx create-react-app my-app --template typescript Такие шаблоны уже содержат необходимые зависимости (typescript, @types/react, @types/node и др.) и готовый tsconfig.json.В уже существующем React-проекте можно добавить TypeScript вручную, но это требует установки типов и настройки сборки — поэтому для обучения предпочтительнее начинать с шаблонов.]]></description><link>материалы/подтемы/секция-2.-react/тема-№20/настройка-проекта-с-typescript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №20/Настройка проекта с TypeScript.md</guid><pubDate>Wed, 04 Feb 2026 06:39:28 GMT</pubDate></item><item><title><![CDATA[Асинхронность и React]]></title><description><![CDATA[В React асинхронные операции, такие как загрузка данных с сервера, должны выполняться в правильном месте жизненного цикла компонента. Неправильное использование асинхронности может привести к ошибкам, утечкам памяти или обновлению состояния в уже размонтированном компоненте.В функциональных компонентах асинхронный код запускается внутри хука useEffect. Это гарантирует, что операция выполнится в нужный момент — например, при монтировании компонента или при изменении зависимостей.import { useEffect, useState } from 'react'; function UserProfile({ userId }) { const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() =&gt; { const fetchUser = async () =&gt; { try { const response = await fetch(`/api/users/${userId}`); const data = await response.json(); setUser(data); } catch (error) { console.error('Ошибка загрузки пользователя:', error); } finally { setLoading(false); } }; fetchUser(); }, [userId]); // Зависимость: перезапускать при смене userId if (loading) return &lt;div&gt;Загрузка...&lt;/div&gt;; return &lt;div&gt;Имя: {user?.name}&lt;/div&gt;;
}
Следующий код недопустим:// Ошибка: нельзя использовать await вне async-функции
const data = await fetch('/api/data');
Компонент React — это обычная функция, и она должна синхронно возвращать JSX. Асинхронная логика должна быть изолирована внутри useEffect или вспомогательных функций.Если компонент размонтируется до завершения запроса, попытка обновить его состояние вызовет предупреждение. Чтобы этого избежать, можно использовать флаг:useEffect(() =&gt; { let isMounted = true; const fetchUser = async () =&gt; { const data = await fetch(`/api/users/${userId}`).then(r =&gt; r.json()); if (isMounted) { setUser(data); } }; fetchUser(); return () =&gt; { isMounted = false; // cleanup при размонтировании };
}, [userId]);
В большинстве случаев React Native подавляет такие ошибки, но хорошая практика — предотвращать их явно.При асинхронных операциях рекомендуется управлять тремя состояниями:
loading — идёт загрузка
data — успешный результат
error — произошла ошибка
Это улучшает UX и помогает избежать неопределённого поведения.
Все побочные эффекты (запросы, подписки, таймеры) — только в useEffect
Асинхронная функция внутри useEffect должна быть объявлена отдельно или как немедленно вызываемая стрелочная функция
Не забывайте указывать зависимости в массиве useEffect, чтобы избежать устаревших замыканий
Избегайте запуска асинхронных операций в обработчиках рендера (например, прямо в теле компонента)
Асинхронность в React требует дисциплины, но при правильном подходе делает приложения отзывчивыми и надёжными.]]></description><link>материалы/подтемы/секция-2.-react/тема-№19/асинхронность-и-react.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №19/Асинхронность и React.md</guid><pubDate>Wed, 04 Feb 2026 06:08:28 GMT</pubDate></item><item><title><![CDATA[Разница между await и then()]]></title><description><![CDATA[await и .then() — это два способа работы с промисами, но они отличаются по стилю, читаемости и поведению.С .then() код строится в виде цепочки:fetchData() .then(data =&gt; processData(data)) .then(result =&gt; saveResult(result)) .catch(error =&gt; console.error(error));
С await код выглядит как последовательный синхронный:try { const data = await fetchData(); const result = processData(data); await saveResult(result);
} catch (error) { console.error(error);
}
Второй вариант легче читать, особенно при наличии условий, циклов или нескольких переменных.При использовании .then() каждое значение доступно только внутри соответствующего колбэка. Чтобы использовать результат на следующем шаге, нужно возвращать его явно:fetchUser() .then(user =&gt; { return fetchPosts(user.id); // без return — undefined }) .then(posts =&gt; console.log(posts));
С await значения сохраняются в обычные переменные и доступны на любом этапе функции:const user = await fetchUser();
const posts = await fetchPosts(user.id);
console.log(posts);
С .then() ошибку ловит отдельный .catch() в конце цепочки. Если ошибка возникает в любом .then(), она передаётся дальше до .catch().С await используется стандартный try/catch, что позволяет обрабатывать ошибки точно так же, как в синхронном коде, и даже применять разные блоки catch для разных участков.Функция с .then() требует аккуратного возврата промиса, чтобы результат был доступен снаружи:function getUserData() { return fetchUser().then(user =&gt; { return { ...user, loadedAt: Date.now() }; });
}
С async/await возврат происходит естественно:async function getUserData() { const user = await fetchUser(); return { ...user, loadedAt: Date.now() };
}
Обе функции возвращают промис, но второй вариант проще понять.
При работе с параллельными операциями на верхнем уровне:
Promise.all([a(), b()]).then(([resA, resB]) =&gt; { ... }); В обработчиках событий, где неудобно создавать отдельную async-функцию:
button.addEventListener('click', () =&gt; fetchData().then(showData)); Однако даже в этих случаях можно использовать стрелочную async-функцию.Используйте async/await по умолчанию. Он делает код линейным, упрощает отладку и совместим со всеми возможностями JavaScript. Резервируйте .then() только для специфических случаев, где он действительно короче или удобнее.]]></description><link>материалы/подтемы/секция-2.-react/тема-№19/разница-между-await-и-then().html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №19/Разница между await и then().md</guid><pubDate>Wed, 04 Feb 2026 06:03:30 GMT</pubDate></item><item><title><![CDATA[Async и await]]></title><description><![CDATA[async/await — это синтаксический сахар над промисами, который позволяет писать асинхронный код так, будто он синхронный. Он делает код проще для чтения и отладки, сохраняя при этом все преимущества промисов.Функция, содержащая await, должна быть помечена ключевым словом async. Такая функция всегда возвращает промис:async function fetchData() { const response = await fetch('https://api.example.com/data'); const data = await response.json(); return data; // эквивалентно resolve(data)
}
Вызов этой функции:fetchData().then(data =&gt; console.log(data));
Или внутри другой async-функции:async function handleData() { const data = await fetchData(); console.log(data);
}
Ключевое слово await приостанавливает выполнение только внутри текущей async-функции, пока промис не завершится. При этом основной поток выполнения не блокируется — другие задачи продолжают работать.async function example() { console.log('Начало'); await new Promise(resolve =&gt; setTimeout(resolve, 1000)); console.log('Прошла секунда');
}
Вывод:Начало
(через 1 секунду) Прошла секунда
Ошибки в async/await обрабатываются с помощью стандартного try/catch:async function safeFetch() { try { const response = await fetch('https://api.example.com/data'); if (!response.ok) throw new Error('Сервер вернул ошибку'); const data = await response.json(); return data; } catch (error) { console.error('Не удалось загрузить данные:', error.message); throw error; // можно пробросить дальше, если нужно }
}
Это гораздо удобнее, чем .catch() в цепочках промисов, особенно при сложной логике.
await можно использовать только внутри функций, объявленных как async
Нельзя использовать await на верхнем уровне модуля (вне функции), если только не используется top-level await (поддержка зависит от окружения; в React Native — не рекомендуется)
async-функция всегда возвращает промис, даже если в ней нет await
Последовательно (медленно):async function loadSequentially() { const user = await fetchUser(); const posts = await fetchPosts(user.id); return { user, posts };
}
Параллельно (быстро):async function loadInParallel() { const userPromise = fetchUser(); const postsPromise = fetchPosts(); // предположим, что ID не нужен сразу const user = await userPromise; const posts = await postsPromise; return { user, posts };
}
Или с Promise.all:async function loadWithAll() { const [user, posts] = await Promise.all([fetchUser(), fetchPosts()]); return { user, posts };
}
Используйте async/await в большинстве случаев — он проще, читаемее и лучше сочетается с обычными конструкциями языка (if, for, try/catch). Избегайте смешивания .then() и await в одном блоке кода без веской причины.]]></description><link>материалы/подтемы/секция-2.-react/тема-№19/async-и-await.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №19/Async и await.md</guid><pubDate>Wed, 04 Feb 2026 05:58:49 GMT</pubDate></item><item><title><![CDATA[Промисы (Promise)]]></title><description><![CDATA[Промис (Promise) — это встроенный в JavaScript объект, который представляет результат асинхронной операции, которая может завершиться успешно или с ошибкой. Промисы были созданы для решения проблем коллбэков и обеспечения более читаемого и управляемого асинхронного кода.Любой промис может находиться в одном из трёх состояний:
pending — начальное состояние, операция ещё не завершена
fulfilled — операция завершилась успешно, значение доступно
rejected — операция завершилась с ошибкой, причина ошибки доступна
Состояние промиса меняется только один раз: из pending либо в fulfilled, либо в rejected. После этого оно остаётся неизменным.Промис создаётся с помощью конструктора new Promise(), которому передаётся функция-исполнитель (executor):const myPromise = new Promise((resolve, reject) =&gt; { // Имитация асинхронной операции setTimeout(() =&gt; { const success = true; if (success) { resolve('Данные получены'); } else { reject(new Error('Не удалось получить данные')); } }, 1000);
});
Функция получает два параметра:
resolve(value) — вызывается при успешном завершении
reject(error) — вызывается при ошибке
Для работы с результатом промиса используются методы:Вызывается, если промис выполнен успешно:myPromise.then((result) =&gt; { console.log(result); // 'Данные получены'
});
Вызывается, если промис отклонён:myPromise.catch((error) =&gt; { console.error(error.message); // 'Не удалось получить данные'
});
Вызывается в любом случае — как при успехе, так и при ошибке. Часто используется для очистки (например, скрыть индикатор загрузки):myPromise .then(console.log) .catch(console.error) .finally(() =&gt; console.log('Операция завершена'));
Метод .then() возвращает новый промис, что позволяет строить цепочки:fetchUserData() .then(user =&gt; fetchUserPosts(user.id)) .then(posts =&gt; processPosts(posts)) .then(result =&gt; console.log(result)) .catch(error =&gt; console.error('Ошибка:', error));
Каждый шаг может возвращать значение или другой промис. Если в цепочке возникает ошибка, выполнение переходит к ближайшему .catch().
Код становится линейным и читаемым
Ошибки обрабатываются централизованно через .catch()
Легко комбинировать несколько асинхронных операций
Избегается «ад коллбэков» Промисы не отменяются после создания
Нельзя узнать текущее состояние промиса напрямую (только через обработчики)
Если не вызвать .catch(), ошибка может остаться незамеченной (в современных средах такие ошибки логируются в консоль)
Промисы стали стандартом для асинхронных операций в JavaScript и лежат в основе более современного синтаксиса async/await.]]></description><link>материалы/подтемы/секция-2.-react/тема-№19/промисы-(promise).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №19/Промисы (Promise).md</guid><pubDate>Wed, 04 Feb 2026 05:54:03 GMT</pubDate></item><item><title><![CDATA[Коллбэки]]></title><description><![CDATA[Коллбэк (callback) — это функция, передаваемая в другую функцию как аргумент и вызываемая позже, когда завершится какая-то операция. Коллбэки были первым способом обработки асинхронных операций в JavaScript.Функция, принимающая коллбэк, вызывает его в нужный момент — например, после получения данных или истечения таймера. Это позволяет «подписаться» на завершение операции.function fetchData(callback) { setTimeout(() =&gt; { const data = { id: 1, name: 'Пример' }; callback(data); }, 1000);
} fetchData((result) =&gt; { console.log('Получены данные:', result);
});
Здесь fetchData имитирует задержку, а затем вызывает переданный коллбэк с данными.Когда нужно выполнить несколько асинхронных операций последовательно, код быстро становится вложенным и трудночитаемым:getData((a) =&gt; { getMoreData(a, (b) =&gt; { getEvenMoreData(b, (c) =&gt; { getFinalData(c, (d) =&gt; { console.log(d); }); }); });
});
Такой стиль усложняет понимание логики, отладку и рефакторинг.В коллбэках нет единого механизма обработки ошибок. Часто используется соглашение: первый аргумент — ошибка, второй — данные:fs.readFile('file.txt', (err, data) =&gt; { if (err) { console.error('Ошибка:', err); return; } console.log(data);
});
Но если забыть проверить err, ошибка может остаться незамеченной.Код перестаёт читаться сверху вниз. Вместо последовательных шагов появляются вложенные блоки, что затрудняет восприятие потока выполнения.Несмотря на недостатки, коллбэки всё ещё применяются:
В событиях: button.addEventListener('click', handler)
В некоторых API React Native (например, обратные вызовы в нативных модулях)
В устаревших библиотеках
Однако для новых проектов рекомендуется использовать промисы или async/await.]]></description><link>материалы/подтемы/секция-2.-react/тема-№19/коллбэки.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №19/Коллбэки.md</guid><pubDate>Wed, 04 Feb 2026 05:49:17 GMT</pubDate></item><item><title><![CDATA[Что такое асинхронность]]></title><description><![CDATA[Асинхронность — это способ выполнения кода, при котором длительные операции (например, запрос к серверу или таймер) не останавливают выполнение остальной программы. В JavaScript основной поток выполнения единственный, поэтому без асинхронности интерфейс «зависал» бы при каждой задержке.Если бы JavaScript был полностью синхронным, то при выполнении операции вроде fetch() весь интерфейс перестал бы отвечать, пока не пришёл ответ. Асинхронность позволяет продолжать взаимодействие с приложением: пользователь может кликать, скроллить и вводить данные, даже если фоновая задача ещё не завершена.
Запросы к API через fetch или axios
Чтение или запись в файловую систему (в средах, где это доступно)
Таймеры: setTimeout, setInterval
События: клики, ввод текста, загрузка изображений
JavaScript использует событийную петлю (event loop). Когда встречается асинхронная операция, она передаётся в браузерное API или среду выполнения (например, Node.js или React Native), а основной поток продолжает работу. Как только операция завершается, её результат помещается в очередь задач, и движок обрабатывает его, когда основной стек вызовов свободен.Это означает, что асинхронный код не выполняется параллельно, но он не блокирует выполнение других инструкций.console.log('Начало'); setTimeout(() =&gt; { console.log('Таймер сработал');
}, 1000); console.log('Конец');
Вывод:Начало
Конец
Таймер сработал
Строка 'Таймер сработал' появляется последней, потому что setTimeout — асинхронная функция. Она не ждёт, пока пройдёт секунда, а сразу возвращает управление, позволяя выполниться следующей строке.]]></description><link>материалы/подтемы/секция-2.-react/тема-№19/что-такое-асинхронность.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №19/Что такое асинхронность.md</guid><pubDate>Wed, 04 Feb 2026 05:47:07 GMT</pubDate></item><item><title><![CDATA[Тема №15. Хранение и передача данных в React]]></title><description><![CDATA[В этой теме вы изучите механизмы управления состоянием и передачи данных между компонентами в React — основу для построения интерактивных интерфейсов. Поймёте, как хранить данные внутри компонента с помощью хуков, как передавать их через свойства и как сохранять их между сессиями — что критично для обеспечения постоянства пользовательских настроек и кэширования информации.
<a data-href="Состояние и хук useState" href="материалы/подтемы/секция-2.-react/тема-№15/состояние-и-хук-usestate.html" class="internal-link" target="_self" rel="noopener nofollow">Состояние и хук useState</a>
<br><a data-href="Передача данных через props" href="материалы/подтемы/секция-2.-react/тема-№15/передача-данных-через-props.html" class="internal-link" target="_self" rel="noopener nofollow">Передача данных через props</a>
<br><a data-href="Хранение данных между сессиями" href="материалы/подтемы/секция-2.-react/тема-№15/хранение-данных-между-сессиями.html" class="internal-link" target="_self" rel="noopener nofollow">Хранение данных между сессиями</a>
(пусто)<br><a data-href="Тема №16. События и Ref в React" href="лекции/секция-2.-react/тема-№16.-события-и-ref-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №16. События и Ref в React</a>]]></description><link>лекции/секция-2.-react/тема-№15.-хранение-и-передача-данных-в-react.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №15. Хранение и передача данных в React.md</guid><pubDate>Tue, 20 Jan 2026 18:40:40 GMT</pubDate></item><item><title><![CDATA[Тема №16. События и Ref в React]]></title><description><![CDATA[В этой теме вы изучите обработку пользовательских событий и работу с референсами в React — ключевые механизмы для взаимодействия с DOM-элементами и управления состоянием, которое не требует перерисовки интерфейса. Поймёте, как реагировать на действия пользователя (клики, ввод, фокус) и когда использовать ref вместо состояния для доступа к элементам или их значениям.
<a data-href="Обработка событий в React" href="материалы/подтемы/секция-2.-react/тема-№16/обработка-событий-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Обработка событий в React</a>
<br><a data-href="Что такое Ref" href="материалы/подтемы/секция-2.-react/тема-№16/что-такое-ref.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое Ref</a>
<br><a data-href="Работа с формами" href="материалы/подтемы/секция-2.-react/тема-№16/работа-с-формами.html" class="internal-link" target="_self" rel="noopener nofollow">Работа с формами</a> <br><a data-href="Практика №10. Интерактивный счётчик с изменением темы" href="задания/секция-2.-react/практика-№10.-интерактивный-счётчик-с-изменением-темы.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №10. Интерактивный счётчик с изменением темы</a>
<br><a data-href="Тема №17. Hooks в React" href="лекции/секция-2.-react/тема-№17.-hooks-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №17. Hooks в React</a>]]></description><link>лекции/секция-2.-react/тема-№16.-события-и-ref-в-react.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №16. События и Ref в React.md</guid><pubDate>Tue, 20 Jan 2026 18:40:39 GMT</pubDate></item><item><title><![CDATA[Загрузка данных в маршрутах]]></title><description><![CDATA[Загрузка данных в маршрутах — это процесс получения информации (например, с API), необходимой для отображения конкретного экрана. В React Router v6 основной подход заключается в том, что каждый компонент маршрута отвечает за загрузку собственных данных.Наиболее распространённый способ — инициировать запрос при монтировании компонента, используя useEffect:// UserProfile.jsx
import { useEffect, useState } from 'react';
import { useParams } from 'react-router-dom'; function UserProfile() { const { userId } = useParams(); const [user, setUser] = useState(null); const [loading, setLoading] = useState(true); useEffect(() =&gt; { fetch(`/api/users/${userId}`) .then(res =&gt; res.json()) .then(data =&gt; { setUser(data); setLoading(false); }); }, [userId]); if (loading) return &lt;div&gt;Загрузка...&lt;/div&gt;; return &lt;div&gt;Имя: {user.name}&lt;/div&gt;;
}
Каждый маршрут сам управляет своим состоянием загрузки, ошибками и обновлением данных при изменении параметров (например, переходе от /user/1 к /user/2).Важно, чтобы данные загружались в том компоненте, который их использует. Например, если страница профиля отображает список постов пользователя, запрос к /api/users/:id/posts должен выполняться внутри UserProfile, а не в родительском компоненте. Это:
упрощает логику;
предотвращает передачу ненужных пропсов;
делает компоненты переиспользуемыми.
Начиная с версии 6.4, React Router предлагает новый подход — loader-функции, которые выполняются до рендеринга компонента. Они позволяют загружать данные на этапе маршрутизации, а не в самом компоненте:// routes.js
const userLoader = async ({ params }) =&gt; { const res = await fetch(`/api/users/${params.userId}`); return res.json();
}; &lt;Route path="/user/:userId" element={&lt;UserProfile /&gt;} loader={userLoader} /&gt;
Однако в рамках текущего курса мы фокусируемся на базовом подходе с useEffect, так как он:
работает во всех версиях React Router v6;
не требует дополнительной настройки роутера;
проще для понимания на начальном этапе. Не загружайте данные в родительском компоненте ради дочернего — это нарушает инкапсуляцию;
Обрабатывайте ошибки загрузки (например, показывайте сообщение при 404 от API);
Используйте userId из useParams() как зависимость в useEffect, чтобы обновлять данные при смене параметра.
Этот подход обеспечивает чёткое разделение ответственности и предсказуемое поведение при навигации.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/загрузка-данных-в-маршрутах.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Загрузка данных в маршрутах.md</guid><pubDate>Tue, 20 Jan 2026 18:35:05 GMT</pubDate></item><item><title><![CDATA[Обработка несуществующих маршрутов]]></title><description><![CDATA[Когда пользователь переходит по URL, который не соответствует ни одному из определённых маршрутов, приложение должно отображать страницу с сообщением об ошибке — обычно это страница «404 — Страница не найдена». React Router позволяет легко реализовать такой fallback-маршрут.В React Router для перехвата всех несуществующих путей используется специальный путь *. Он совпадает с любым URL, который не был обработан другими маршрутами.// App.jsx
import { Routes, Route } from 'react-router-dom';
import HomePage from './pages/HomePage';
import NotFound from './pages/NotFound'; function App() { return ( &lt;Routes&gt; &lt;Route path="/" element={&lt;HomePage /&gt;} /&gt; &lt;Route path="*" element={&lt;NotFound /&gt;} /&gt; &lt;/Routes&gt; );
}
Важно: маршрут с path="*" должен быть последним в списке, так как &lt;Routes&gt; выбирает первый совпадающий маршрут. Если поставить его выше, он будет перехватывать все запросы.Страница NotFound может содержать:
понятное сообщение для пользователя;
кнопку «На главную» или ссылку на основные разделы;
логотип или элементы бренда для сохранения узнаваемости.
Пример:// NotFound.jsx
import { Link } from 'react-router-dom'; function NotFound() { return ( &lt;div&gt; &lt;h1&gt;Страница не найдена&lt;/h1&gt; &lt;p&gt;К сожалению, такой страницы не существует.&lt;/p&gt; &lt;Link to="/"&gt;Вернуться на главную&lt;/Link&gt; &lt;/div&gt; );
} Всегда добавляйте маршрут * в конце — это улучшает пользовательский опыт и предотвращает пустой экран;
Не используйте * для других целей (например, динамических маршрутов) — только как fallback;
В реальных проектах страница 404 часто стилизуется в соответствии с общим дизайном приложения.
Такой подход делает приложение более надёжным и дружелюбным к пользователю.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/обработка-несуществующих-маршрутов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Обработка несуществующих маршрутов.md</guid><pubDate>Tue, 20 Jan 2026 18:33:41 GMT</pubDate></item><item><title><![CDATA[Программная навигация]]></title><description><![CDATA[Программная навигация — это способ изменять текущий URL и переключать экраны не через клик по &lt;Link&gt;, а из кода компонента. Это необходимо, когда переход должен происходить в ответ на действие пользователя (например, отправка формы) или системное событие (например, успешная авторизация).Для программной навигации в React Router v6 используется хук useNavigate(). Он возвращает функцию, которую можно вызвать для перехода на другой маршрут.import { useNavigate } from 'react-router-dom'; function LoginPage() { const navigate = useNavigate(); const handleLogin = () =&gt; { // имитация успешной авторизации navigate('/dashboard'); }; return ( &lt;button onClick={handleLogin}&gt; Войти &lt;/button&gt; );
}
navigate('/profile');
Добавляет новую запись в историю браузера (как обычный клик по ссылке).navigate('/home', { replace: true });
Полезно после логина или логаута, чтобы пользователь не мог вернуться назад на страницу входа кнопкой «Назад».navigate(-1);
Аналог кнопки «Назад» в браузере. Можно также использовать navigate(1) для перехода вперёд.
После успешной отправки формы (например, создания заказа);
При автоматическом перенаправлении (например, если пользователь не авторизован);
В обработчиках ошибок (например, переход на страницу 404 при отсутствии данных);
В модальных окнах или всплывающих уведомлениях, где нет возможности использовать &lt;Link&gt;.
Функция navigate должна вызываться только внутри компонента, обёрнутого в &lt;BrowserRouter&gt;. Вызов вне дерева маршрутизации приведёт к ошибке.Также не рекомендуется вызывать navigate напрямую в теле компонента (на этапе рендеринга), так как это может вызвать побочные эффекты. Используйте его только в обработчиках событий или внутри useEffect при определённых условиях.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/программная-навигация.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Программная навигация.md</guid><pubDate>Tue, 20 Jan 2026 18:30:43 GMT</pubDate></item><item><title><![CDATA[Вложенные маршруты]]></title><description><![CDATA[Вложенные маршруты позволяют строить иерархическую структуру экранов, где один маршрут отображается внутри другого. Это особенно полезно для создания интерфейсов с общей оболочкой — например, панель навигации или шапка остаются неизменными, а меняется только внутренний контент.В React Router v6 вложенные маршруты определяются через свойство children у компонента &lt;Route&gt;. Родительский маршрут задаёт общую разметку, а дочерние — то, что должно отображаться внутри.Для отображения дочерних маршрутов внутри родительского компонента используется специальный компонент &lt;Outlet /&gt;.Предположим, у нас есть раздел /dashboard, который содержит подразделы: /dashboard/overview и /dashboard/settings.// App.jsx
import { Routes, Route } from 'react-router-dom';
import DashboardLayout from './pages/DashboardLayout';
import Overview from './pages/Overview';
import Settings from './pages/Settings'; function App() { return ( &lt;Routes&gt; &lt;Route path="/dashboard" element={&lt;DashboardLayout /&gt;}&gt; &lt;Route index element={&lt;Overview /&gt;} /&gt; &lt;Route path="settings" element={&lt;Settings /&gt;} /&gt; &lt;/Route&gt; &lt;/Routes&gt; );
}
Обратите внимание:
дочерние маршруты указываются внутри родительского &lt;Route&gt;;
путь settings указан без слеша — он автоматически становится частью родительского пути: /dashboard/settings;
маршрут с index совпадает с точным путём родителя (/dashboard).
Внутри DashboardLayout нужно указать, куда вставлять дочерний контент:// DashboardLayout.jsx
import { Outlet } from 'react-router-dom'; function DashboardLayout() { return ( &lt;div&gt; &lt;nav&gt; &lt;Link to="/dashboard"&gt;Обзор&lt;/Link&gt; &lt;Link to="/dashboard/settings"&gt;Настройки&lt;/Link&gt; &lt;/nav&gt; &lt;main&gt; &lt;Outlet /&gt; {/* Сюда будет подставляться Overview или Settings */} &lt;/main&gt; &lt;/div&gt; );
}
Без &lt;Outlet /&gt; дочерние маршруты не отобразятся.
Избегается дублирование общей разметки (например, меню);
Логика навигации и структура приложения становятся нагляднее;
Поддерживается естественная иерархия URL.
Вложенные маршруты не требуют дополнительной настройки — всё работает за счёт объявления структуры в &lt;Routes&gt;. Однако родительский компонент обязан содержать &lt;Outlet /&gt;, иначе дочерние элементы не будут отображены.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/вложенные-маршруты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Вложенные маршруты.md</guid><pubDate>Tue, 20 Jan 2026 18:29:55 GMT</pubDate></item><item><title><![CDATA[Параметры маршрута]]></title><description><![CDATA[Параметры маршрута позволяют создавать динамические URL-адреса, в которых часть пути является переменной. Это необходимо, когда одна и та же страница отображает разные данные в зависимости от входного значения — например, профиль пользователя по ID или статья по уникальному slug.В React Router динамический сегмент пути обозначается двоеточием: :имяПараметра.Примеры:
/user/:id — путь к профилю пользователя с идентификатором id;
/product/:slug — страница товара по человекочитаемому имени.
Такой маршрут будет совпадать с любым значением на месте параметра:
/user/42 → id = "42"
/user/abc → id = "abc"
Чтобы получить значение параметра внутри компонента, используется хук useParams() из react-router-dom.// Маршрут
&lt;Route path="/user/:userId" element={&lt;UserProfile /&gt;} /&gt; // Компонент UserProfile.jsx
import { useParams } from 'react-router-dom'; function UserProfile() { const { userId } = useParams(); return &lt;div&gt;Профиль пользователя: {userId}&lt;/div&gt;;
}
Хук возвращает объект, ключи которого соответствуют именам параметров в пути. Все значения — строки.Параметры маршрута используются для:
отображения детальной информации (пользователь, товар, статья);
фильтрации контента (например, /category/:name);
создания универсальных шаблонов страниц.
Важно: если параметр необязательный или может отсутствовать, лучше использовать query-параметры (?id=123) или альтернативные маршруты, так как /user/:id не совпадёт с /user.React Router не проверяет тип или формат параметра. Например, /user/42 и /user/not-a-number оба будут переданы как строка. Валидацию и обработку ошибок нужно реализовывать в самом компоненте.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/параметры-маршрута.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Параметры маршрута.md</guid><pubDate>Tue, 20 Jan 2026 18:25:31 GMT</pubDate></item><item><title><![CDATA[Основные компоненты React Router]]></title><description><![CDATA[React Router предоставляет набор компонентов, которые вместе формируют систему навигации в приложении. Они работают только внутри контекста маршрутизатора и должны использоваться в определённой иерархии.Этот компонент создаёт корневой контекст маршрутизации, используя HTML5 History API (pushState, replaceState, popstate). Он должен оборачивать всё ваше приложение — обычно размещается в файле main.jsx или App.jsx.import { BrowserRouter } from 'react-router-dom';
import App from './App'; ReactDOM.createRoot(document.getElementById('root')).render( &lt;BrowserRouter&gt; &lt;App /&gt; &lt;/BrowserRouter&gt;
);
Без &lt;BrowserRouter&gt; другие компоненты React Router не будут работать.Компонент &lt;Routes&gt; просматривает все вложенные &lt;Route&gt; и отображает только один — тот, чей путь (path) совпадает с текущим URL. Это центральный механизм выбора компонента.Каждый &lt;Route&gt; определяет соответствие между путём и элементом:&lt;Route path="/about" element={&lt;AboutPage /&gt;} /&gt;
Важно: element принимает JSX, а не ссылку на компонент (не element={AboutPage}); пути без слеша в начале (about) считаются относительными; всегда используйте абсолютные пути: /about.
Пример использования:import { Routes, Route } from 'react-router-dom';
import HomePage from './pages/HomePage';
import AboutPage from './pages/AboutPage'; function App() { return ( &lt;Routes&gt; &lt;Route path="/" element={&lt;HomePage /&gt;} /&gt; &lt;Route path="/about" element={&lt;AboutPage /&gt;} /&gt; &lt;/Routes&gt; );
}
Компонент &lt;Link&gt; заменяет стандартный HTML-тег &lt;a&gt;. Он позволяет переходить по маршрутам без перезагрузки страницы.&lt;Link to="/about"&gt;О нас&lt;/Link&gt;
При клике на &lt;Link&gt; React Router обновляет URL и перерисовывает нужный компонент, но браузер не отправляет запрос на сервер.Это расширенная версия &lt;Link&gt;, которая автоматически добавляет CSS-класс (по умолчанию active), когда текущий URL совпадает с его to.&lt;NavLink to="/profile"&gt;Профиль&lt;/NavLink&gt;
Если пользователь находится на /profile, элемент получит класс active. Это удобно для подсветки текущего пункта меню.Можно кастомизировать имя активного класса:&lt;NavLink to="/settings" className={({ isActive }) =&gt; isActive ? 'nav-active' : 'nav-item'}
&gt; Настройки
&lt;/NavLink&gt;
Основные компоненты образуют следующую структуру:
&lt;BrowserRouter&gt; — окружает всё приложение;
&lt;Routes&gt; — содержит список маршрутов;
&lt;Route&gt; — связывает путь с компонентом;
&lt;Link&gt; / &lt;NavLink&gt; — обеспечивают навигацию между маршрутами.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/основные-компоненты-react-router.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Основные компоненты React Router.md</guid><pubDate>Tue, 20 Jan 2026 18:24:09 GMT</pubDate></item><item><title><![CDATA[React Router — основная библиотека]]></title><description><![CDATA[React Router — это официальная и наиболее распространённая библиотека маршрутизации для приложений на React. Она позволяет сопоставлять URL-адреса с компонентами, управлять историей навигации и реализовывать сложные сценарии вроде вложенных маршрутов или динамических параметров.Для использования React Router в проекте необходимо установить пакет react-router-dom. Это версия библиотеки, предназначенная для веб-приложений (в отличие от react-router-native для React Native).npm install react-router-dom
После установки вы можете импортировать необходимые компоненты и хуки из react-router-dom:import { BrowserRouter, Routes, Route, Link } from 'react-router-dom';
В рамках курса используется React Router v6 — текущая стабильная версия, которая значительно отличается от предыдущих (особенно v5). Основные изменения:
вместо пропса component теперь используется element;
обязательное использование &lt;Routes&gt; (ранее &lt;Switch&gt;);
упрощённый синтаксис для вложенных маршрутов;
новые хуки: useNavigate, useParams, useLocation.
Убедитесь, что в вашем проекте установлена именно версия 6.x, так как примеры из лекций не будут работать с более старыми версиями.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/react-router-—-основная-библиотека.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/React Router — основная библиотека.md</guid><pubDate>Tue, 20 Jan 2026 18:21:28 GMT</pubDate></item><item><title><![CDATA[Что такое маршрутизация]]></title><description><![CDATA[Маршрутизация — это механизм, который связывает URL-адрес в браузере с конкретным компонентом пользовательского интерфейса. В приложениях на React она позволяет показывать разные экраны (например, «Главная», «Профиль», «Настройки») без перезагрузки всей страницы.SPA (Single Page Application) — это одностраничное веб-приложение, в котором весь пользовательский интерфейс загружается один раз. При переходе между разделами контент обновляется динамически, а не через загрузку нового HTML-документа с сервера. Это делает навигацию быстрой и похожей на работу нативного приложения.В отличие от традиционных многостраничных сайтов (MPA), где каждый новый URL загружает отдельный HTML-файл, SPA управляет отображением контента целиком на стороне клиента. Маршрутизация в React реализует именно такую логику: она следит за изменением адреса в строке браузера и решает, какой компонент должен быть отображён.Без маршрутизации приложение может отображать только один статичный экран. Чтобы пользователь мог переходить между разделами — например, из списка товаров на страницу конкретного товара — требуется система, которая:
читает текущий путь (например, /product/123);
определяет, какой компонент соответствует этому пути;
отображает его в нужном месте интерфейса.
Маршрутизация также обеспечивает:
корректную работу кнопок «Назад» и «Вперёд» в браузере;
возможность делиться ссылками на конкретные экраны;
чёткую структуру навигации в коде.
В React для этих целей используется библиотека React Router.]]></description><link>материалы/подтемы/секция-2.-react/тема-№18/что-такое-маршрутизация.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №18/Что такое маршрутизация.md</guid><pubDate>Tue, 20 Jan 2026 18:16:44 GMT</pubDate></item><item><title><![CDATA[Пользовательские Hooks]]></title><description><![CDATA[Пользовательские хуки — это функции, созданные разработчиком на основе встроенных хуков React. Они позволяют извлекать и повторно использовать логику компонентов, не дублируя код. Любой пользовательский хук должен начинаться с префикса use, чтобы React распознавал его как хук и применял правила хуков.Часто в приложении возникает повторяющаяся логика: работа с локальным хранилищем, подписка на события, обработка состояния формы, кэширование данных. Вместо того чтобы писать один и тот же код в нескольких компонентах, вы выносите его в отдельную функцию-хук.Преимущества:
Логика изолирована и тестируема
Компоненты становятся чище и короче
Поведение легко переиспользовать
Этот хук инкапсулирует работу с localStorage и синхронизирует её с состоянием компонента:import { useState, useEffect } from 'react'; function useLocalStorage&lt;T&gt;(key: string, initialValue: T): [T, (value: T) =&gt; void] { const [storedValue, setStoredValue] = useState&lt;T&gt;(() =&gt; { try { const item = window.localStorage.getItem(key); return item ? JSON.parse(item) : initialValue; } catch (error) { console.error(`Ошибка при чтении ${key} из localStorage:`, error); return initialValue; } }); const setValue = (value: T) =&gt; { try { setStoredValue(value); window.localStorage.setItem(key, JSON.stringify(value)); } catch (error) { console.error(`Ошибка при записи ${key} в localStorage:`, error); } }; return [storedValue, setValue];
}
Использование:function App() { const [name, setName] = useLocalStorage('userName', 'Гость'); return &lt;input value={name} onChange={(e) =&gt; setName(e.target.value)} /&gt;;
}
Хук для отслеживания размеров окна браузера:import { useState, useEffect } from 'react'; function useWindowSize() { const [windowSize, setWindowSize] = useState({ width: window.innerWidth, height: window.innerHeight, }); useEffect(() =&gt; { const handleResize = () =&gt; { setWindowSize({ width: window.innerWidth, height: window.innerHeight, }); }; window.addEventListener('resize', handleResize); return () =&gt; window.removeEventListener('resize', handleResize); }, []); return windowSize;
}
Использование:function ResponsiveComponent() { const { width } = useWindowSize(); return &lt;div&gt;Ширина окна: {width}px&lt;/div&gt;;
} Имя всегда начинается с use
Может вызывать другие хуки (useState, useEffect, useContext и т.д.)
Не принимает JSX и не возвращает JSX — только данные и функции управления ими
Должен быть чистым по отношению к компоненту: не зависит от конкретного UI Если логика используется только в одном месте
Если она слишком специфична и не поддаётся обобщению
Если проще передать колбэк или использовать пропсы
Пользовательские хуки — мощный инструмент для абстракции поведения, но их следует применять осознанно, чтобы не усложнять архитектуру без необходимости.]]></description><link>материалы/подтемы/секция-2.-react/тема-№17/пользовательские-hooks.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №17/Пользовательские Hooks.md</guid><pubDate>Tue, 20 Jan 2026 18:10:27 GMT</pubDate></item><item><title><![CDATA[useContext]]></title><description><![CDATA[Хук useContext предоставляет способ читать данные из React-контекста без необходимости прокидывать пропсы через каждый уровень компонентного дерева. Это особенно полезно для глобальных данных, таких как тема приложения, язык интерфейса или информация о текущем пользователе.Контекст состоит из двух частей: Провайдер (Provider) — компонент, который передаёт значение вниз по дереву. Потребитель (Consumer) — любой компонент, который получает это значение с помощью useContext.
Сначала создаётся контекст:import { createContext } from 'react'; const ThemeContext = createContext('light'); // 'light' — значение по умолчанию
Затем обёртываем часть приложения в провайдер:&lt;ThemeContext.Provider value="dark"&gt; &lt;App /&gt;
&lt;/ThemeContext.Provider&gt;
Внутри любого дочернего компонента можно получить значение:import { useContext } from 'react'; function Button() { const theme = useContext(ThemeContext); return &lt;button className={theme}&gt;Кнопка&lt;/button&gt;;
}
useContext уместен, когда:
Данные нужны во многих компонентах на разных уровнях вложенности.
Изменение данных должно вызывать перерисовку всех зависимых компонентов.
Прокидывание пропсов становится громоздким («пропс-дриллинг»).
Типичные сценарии:
Темизация
Мультиязычность
Аутентификация
Глобальные настройки
Каждый раз, когда значение контекста изменяется, все компоненты, которые его используют, будут перерисованы — даже если они используют только часть данных. Чтобы избежать лишних рендеров:
Храните в контексте только связанные данные (не объединяйте всё в один глобальный объект).
Разбивайте контексты по смыслу: AuthContext, ThemeContext, LanguageContext.
Для сложных значений используйте useMemo, чтобы сохранять ссылочную стабильность.
Пример плохой практики:// Не делайте так
&lt;GlobalContext.Provider value={{ user, theme, lang, settings }}&gt;
Лучше:&lt;UserContext.Provider value={user}&gt;
&lt;ThemeContext.Provider value={theme}&gt;
Это позволяет компонентам подписываться только на то, что им действительно нужно.Значение по умолчанию (передаваемое в createContext) используется только если компонент не находится внутри соответствующего Provider. Оно не подходит для динамической инициализации — например, из localStorage. В таких случаях лучше управлять состоянием выше и передавать его в Provider.
Примечание: useContext не заменяет все остальные хуки. Он решает конкретную проблему — передачу данных «сквозь» дерево. Для локального состояния по-прежнему используйте useState или useReducer.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№17/usecontext.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №17/useContext.md</guid><pubDate>Tue, 20 Jan 2026 18:06:22 GMT</pubDate></item><item><title><![CDATA[useEffect]]></title><description><![CDATA[Хук useEffect позволяет выполнять побочные эффекты в функциональных компонентах. Побочные эффекты — это действия, которые влияют на внешнюю среду или не могут быть выполнены во время чистого рендеринга: например, запросы к API, подписки на события, прямые манипуляции с DOM, таймеры и работа с внешними системами.useEffect(() =&gt; { // код побочного эффекта return () =&gt; { // опциональная функция очистки };
}, [зависимости]);
Первый аргумент — функция, которая содержит логику эффекта.
Второй аргумент — массив зависимостей. Он управляет, когда эффект должен запускаться повторно.Если второй аргумент отсутствует, эффект выполняется после каждого рендера компонента.useEffect(() =&gt; { console.log('Компонент обновился');
});
Это может привести к избыточным вызовам и снижению производительности — используйте осторожно.Если передать пустой массив [], эффект выполнится один раз — при монтировании компонента. Это аналог componentDidMount в классах.useEffect(() =&gt; { fetchData();
}, []);
Если в массиве перечислены переменные, эффект будет перезапускаться при изменении любого из них.useEffect(() =&gt; { document.title = `Пользователь: ${name}`;
}, [name]);
React сравнивает значения зависимостей посредством строгого равенства (Object.is). Поэтому для объектов и массивов важно сохранять ссылочную стабильность (например, через useMemo или вынос в константу).Если функция внутри useffect возвращает другую функцию, React вызовет её:
перед следующим запуском эффекта (если зависимости изменились);
при размонтировании компонента.
Это используется для отмены подписок, таймеров, слушателей и других ресурсов.Пример:useEffect(() =&gt; { const handleResize = () =&gt; console.log('Окно изменено'); window.addEventListener('resize', handleResize); return () =&gt; { window.removeEventListener('resize', handleResize); };
}, []);
Без очистки возможны утечки памяти или ошибки при попытке взаимодействия с уже удалённым компонентом.
Загрузка данных при монтировании (fetch + useState)
Подписка на события браузера или внешние источники
Ручное обновление DOM вне React-потока
Логирование или аналитика
Важно: не помещайте в useEffect логику, которую можно выразить декларативно через JSX или состояние. Эффекты должны использоваться только тогда, когда без них невозможно достичь цели.]]></description><link>материалы/подтемы/секция-2.-react/тема-№17/useeffect.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №17/useEffect.md</guid><pubDate>Tue, 20 Jan 2026 18:03:42 GMT</pubDate></item><item><title><![CDATA[Правила использования Hooks]]></title><description><![CDATA[Hooks в React работают только при соблюдении двух строгих правил. Эти правила гарантируют, что React может правильно отслеживать состояние и эффекты между вызовами компонентов.Никогда не вызывайте хуки внутри условий, циклов, вложенных функций или тернарных операторов. Это нарушает порядок вызова хуков между рендерами, что приводит к ошибкам.Неправильно:if (condition) { const [state, setState] = useState(0);
}
Правильно:const [state, setState] = useState(0);
Если вам нужно условное поведение — применяйте его внутри тела хука или после его вызова, но не вокруг самого вызова.Хуки нельзя использовать в обычных JavaScript-функциях. Их можно вызывать только:
внутри функционального компонента React;
внутри другого пользовательского хука (который сам следует этим правилам).
Это обеспечивает, что вся логика, связанная с состоянием и эффектами, остаётся привязанной к компонентному дереву.Все хуки (встроенные и пользовательские) должны начинаться с префикса use. Это соглашение помогает React и разработчикам распознавать, что функция использует реактовые возможности и подчиняется правилам хуков.Примеры корректных имён:
useState
useEffect
useLocalStorage
useWindowSize
React предоставляет линтер-правило (eslint-plugin-react-hooks), которое автоматически проверяет соблюдение этих правил. Рекомендуется всегда включать его в проект.]]></description><link>материалы/подтемы/секция-2.-react/тема-№17/правила-использования-hooks.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №17/Правила использования Hooks.md</guid><pubDate>Tue, 20 Jan 2026 17:58:37 GMT</pubDate></item><item><title><![CDATA[Что такое Hooks]]></title><description><![CDATA[Hooks — это специальные функции, которые позволяют «подключать» возможности React к функциональным компонентам. Благодаря им вы можете использовать состояние (state), выполнять побочные эффекты (например, запросы к API), работать с референсами и другими возможностями, которые раньше были доступны только в классовых компонентах.До появления Hooks логика, связанная с состоянием или жизненным циклом, могла быть реализована только в классах. Это делало компоненты громоздкими, сложными для тестирования и переиспользования. Hooks решили эту проблему: теперь вся эта логика доступна в простых функциях, что упрощает структуру кода и способствует его повторному использованию.Основное назначение Hooks — отделить поведение от представления. Например, логика загрузки данных может быть вынесена в отдельный хук и использована в разных компонентах без дублирования кода.Важно помнить: Hooks не работают вне функциональных компонентов. Их нельзя вызывать в обычных функциях, условиях или циклах — только на верхнем уровне компонента или внутри других пользовательских хуков.Самые распространённые встроенные хуки — это useState, useEffect, useRef и useContext. Некоторые из них вы уже использовали; другие будут рассмотрены далее в этой теме.]]></description><link>материалы/подтемы/секция-2.-react/тема-№17/что-такое-hooks.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №17/Что такое Hooks.md</guid><pubDate>Tue, 20 Jan 2026 17:57:13 GMT</pubDate></item><item><title><![CDATA[Когда использовать Ref, а когда — State]]></title><description><![CDATA[Выбор между useRef и useState определяется одной простой идеей: нужно ли, чтобы изменение значения вызывало перерисовку компонента?Значение влияет на то, что пользователь видит. Например:
Текст в поле ввода, который отображается где-то ещё
Состояние кнопки (активна/неактивна)
Выбранная вкладка или тема интерфейса
Список задач, фильтры, ошибки валидации
const [count, setCount] = useState(0);
// При setCount(1) компонент перерисуется — это необходимо,
// если, например, вы показываете "Счётчик: 1"
useState — основной инструмент для управления данными, которые определяют внешний вид приложения.Значение нужно только для логики, но не влияет на отображение. Например:
Ссылка на DOM-элемент (для фокуса, прокрутки, измерения)
Хранение предыдущего значения пропса или состояния
Идентификатор таймера (setTimeout, setInterval)
Кэш дорогих вычислений
Счётчик попыток, логирование, технические данные
const timerIdRef = useRef(null);
// Изменение timerIdRef.current не должно перерисовывать UI —
// оно нужно только для остановки таймера позже Если вы используете значение внутри JSX ({value}), — это состояние.
Если вы используете значение только в функциях, эффектах или обработчиках, — это ref. Контролируемая форма: useState — потому что вы можете показывать ошибку, кнопку активировать/деактивировать, делать предпросмотр.
Неконтролируемая форма: useRef — если вы просто читаете данные при отправке и ничего не отображаете на основе ввода. Использовать ref для данных в JSX — компонент не обновится, даже если значение изменилось.
Использовать state для таймеров или DOM-ссылок — это вызовет лишние ререндеры и усложнит код.
В подавляющем большинстве случаев начинайте с useState. Переходите к useRef только тогда, когда убедитесь, что перерисовка не нужна и мешает производительности или логике.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/когда-использовать-ref,-а-когда-—-state.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Когда использовать Ref, а когда — State.md</guid><pubDate>Sat, 17 Jan 2026 09:40:11 GMT</pubDate></item><item><title><![CDATA[Неконтролируемые компоненты]]></title><description><![CDATA[Неконтролируемые компоненты — это элементы формы, значение которых управляется самим DOM, а не состоянием React. Вместо того чтобы синхронизировать каждое изменение с useState, вы позволяете браузеру хранить данные и читаете их только тогда, когда они нужны — например, при отправке формы.Для создания неконтролируемого компонента:
Используйте useRef, чтобы получить ссылку на DOM-элемент
Пропустите привязку value к состоянию
При необходимости прочитайте значение через ref.current.value
Пример:function UncontrolledInput() { const inputRef = useRef(null); function handleClick() { console.log('Текущее значение:', inputRef.current.value); } return ( &lt;&gt; &lt;input ref={inputRef} defaultValue="начальное значение" /&gt; &lt;button onClick={handleClick}&gt;Показать значение&lt;/button&gt; &lt;/&gt; );
}
Обратите внимание: вместо value используется defaultValue. Это задаёт начальное значение, но не блокирует дальнейший ввод пользователя.Неконтролируемые компоненты уместны в следующих случаях:
Большие формы, где управление каждым полем через состояние создаёт избыточную нагрузку
Интеграция со сторонними библиотеками, которые напрямую работают с DOM (например, редакторы кода или карты)
Одноразовый ввод, например, поиск или быстрая отправка данных без валидации
Производительность: если поле обновляется очень часто (например, рисование или аудиовизуализация) Нет автоматической синхронизации с состоянием — вы сами решаете, когда читать данные
Невозможно динамически изменить значение поля из кода (кроме как через ref.current.value = ..., что не рекомендуется)
Валидация возможна только в момент чтения (например, при отправке), а не в реальном времени
Неконтролируемые компоненты — допустимый, но менее распространённый подход. Используйте их осознанно, когда преимущества перевешивают потерю реактивности.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/неконтролируемые-компоненты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Неконтролируемые компоненты.md</guid><pubDate>Sat, 17 Jan 2026 09:39:28 GMT</pubDate></item><item><title><![CDATA[Контролируемые компоненты]]></title><description><![CDATA[Контролируемые компоненты — это элементы формы, значение которых управляется состоянием React. Вместо того чтобы позволять DOM хранить данные, React берёт управление на себя: каждое изменение обновляет состояние, а состояние определяет, что отображается.Для создания контролируемого компонента:
Создайте состояние с помощью useState
Привяжите значение поля к этому состоянию через value
Обновляйте состояние при каждом изменении через onChange
Пример текстового поля:function NameInput() { const [name, setName] = useState(''); return ( &lt;input value={name} onChange={(e) =&gt; setName(e.target.value)} placeholder="Введите имя" /&gt; );
}
Без value поле будет неконтролируемым. Без onChange оно станет «только для чтения» — пользователь не сможет его изменить.Контролируемые компоненты работают со всеми стандартными элементами формы:
&lt;input type="text"&gt;, &lt;input type="password"&gt; и т.д. — через value
&lt;textarea&gt; — также через value
&lt;select&gt; — через value (может быть строкой или массивом для множественного выбора)
&lt;input type="checkbox"&gt; и &lt;input type="radio"&gt; — через checked
Пример выпадающего списка:function CitySelect() { const [city, setCity] = useState('moscow'); return ( &lt;select value={city} onChange={(e) =&gt; setCity(e.target.value)}&gt; &lt;option value="moscow"&gt;Москва&lt;/option&gt; &lt;option value="spb"&gt;Санкт-Петербург&lt;/option&gt; &lt;/select&gt; );
} Полный контроль: вы всегда знаете текущее значение
Валидация в реальном времени: можно блокировать недопустимый ввод
Преобразование данных: например, приведение к верхнему регистру или форматирование номера телефона
Синхронизация: значение легко использовать в других частях приложения Требует больше кода, особенно для больших форм
Может снижать производительность при очень частых обновлениях (в таких случаях можно использовать useDeferredValue или оптимизировать)
Контролируемые компоненты — основной и рекомендуемый способ работы с формами в React, так как они соответствуют декларативной философии фреймворка.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/контролируемые-компоненты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Контролируемые компоненты.md</guid><pubDate>Sat, 17 Jan 2026 09:38:28 GMT</pubDate></item><item><title><![CDATA[Работа с формами]]></title><description><![CDATA[В React формы могут быть реализованы двумя основными способами: через контролируемые и неконтролируемые компоненты. Выбор между ними зависит от того, как вы управляете данными ввода — через состояние React или напрямую через DOM.В контролируемых компонентах значение поля ввода управляется состоянием React. Это означает, что:
Значение элемента задаётся через пропс value (или checked для чекбоксов)
Любое изменение обрабатывается через onChange, который обновляет состояние
React всегда «владеет» текущим значением
Пример:function ControlledForm() { const [name, setName] = useState(''); return ( &lt;form&gt; &lt;input value={name} onChange={(e) =&gt; setName(e.target.value)} placeholder="Введите имя" /&gt; &lt;p&gt;Вы ввели: {name}&lt;/p&gt; &lt;/form&gt; );
}
<a data-href="Контролируемые компоненты" href="материалы/подтемы/секция-2.-react/тема-№16/контролируемые-компоненты.html" class="internal-link" target="_self" rel="noopener nofollow">Контролируемые компоненты</a> — рекомендуемый подход в большинстве случаев, так как они:
Предсказуемы
Позволяют легко валидировать и преобразовывать ввод
Интегрируются с состоянием приложения
В неконтролируемых компонентах данные хранятся в самом DOM-элементе. React не управляет значением — вместо этого вы используете ref, чтобы прочитать его при необходимости.Пример:function UncontrolledForm() { const inputRef = useRef(null); function handleSubmit(e) { e.preventDefault(); console.log('Значение:', inputRef.current.value); } return ( &lt;form onSubmit={handleSubmit}&gt; &lt;input ref={inputRef} defaultValue="" /&gt; &lt;button type="submit"&gt;Отправить&lt;/button&gt; &lt;/form&gt; );
}
<br><a data-href="Неконтролируемые компоненты" href="материалы/подтемы/секция-2.-react/тема-№16/неконтролируемые-компоненты.html" class="internal-link" target="_self" rel="noopener nofollow">Неконтролируемые компоненты</a> полезны, когда:
Форма очень большая, и управление каждым полем через состояние избыточно
Интеграция с библиотеками, которые работают напрямую с DOM
Временные или одноразовые формы, где валидация не требуется
Выбор между ref и useState для форм зависит от цели: Используйте состояние (useState), если: Значение влияет на отображение (например, предварительный просмотр, кнопка активна/неактивна)
Требуется валидация в реальном времени
Данные нужны в других частях приложения Используйте ref, если: Значение нужно только в момент отправки
Вы работаете с большим количеством полей, и синхронизация состояния слишком затратна
Элемент используется для технических целей (например, фокусировка) Важно: даже в неконтролируемых формах можно комбинировать подходы — например, использовать ref для большинства полей, но state для кнопки «Отправить», которая должна быть недоступна, пока не заполнено обязательное поле.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/работа-с-формами.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Работа с формами.md</guid><pubDate>Sat, 17 Jan 2026 09:37:46 GMT</pubDate></item><item><title><![CDATA[Ограничения и рекомендации]]></title><description><![CDATA[Хотя useRef — мощный инструмент, его неправильное использование может привести к трудноуловимым ошибкам и нарушению принципов React. Вот ключевые ограничения и рекомендации.Изменение ref.current внутри тела компонента (не в эффектах или обработчиках) нарушает чистоту рендера:// Плохо
function BadComponent() { const ref = useRef(0); ref.current = ref.current + 1; // мутирует при каждом рендере return &lt;div&gt;{ref.current}&lt;/div&gt;;
}
Это приводит к непредсказуемому поведению, особенно при использовании строгого режима или будущих асинхронных рендереров.Правильно — обновлять ref.current только в useEffect, обработчиках событий или колбэках.Если значение должно отображаться в интерфейсе или влиять на то, что пользователь видит, используйте useState:// Избегайте
const countRef = useRef(0);
// ...и где-то: countRef.current += 1
// но в JSX: {countRef.current} — это работает, но нарушает реактивность // Правильно
const [count, setCount] = useState(0);
React не будет знать, что нужно обновить компонент, если вы измените только ref.React построен на декларативной модели: вы описываете, как должен выглядеть интерфейс, а не как его изменить. Прямое изменение DOM через ref:
Ломает предсказуемость
Усложняет тестирование
Может конфликтовать с обновлениями React
Используйте ref только тогда, когда нет другого способа: фокус, измерение размеров, работа с медиа, интеграция со сторонними библиотеками.Если вы попытаетесь передать ref в обычный функциональный компонент, React проигнорирует его:// Не сработает
function MyInput() { return &lt;input /&gt;;
}
// ...
&lt;MyInput ref={myRef} /&gt; // myRef.current будет null
Чтобы исправить, используйте forwardRef:// const MyInput = forwardRef((props, ref) =&gt; { return &lt;input ref={ref} {...props} /&gt;;
}); Используйте ref только для задач, которые невозможно решить через state и props.
Обновляйте ref.current вне фазы рендера.
Предпочитайте управляемые компоненты (useState + onChange) неконтролируемым (ref + value), если нет веской причины.
Помните: React — про данные, а не про DOM. Ref — исключение, а не правило.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/ограничения-и-рекомендации.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Ограничения и рекомендации.md</guid><pubDate>Sat, 17 Jan 2026 09:34:43 GMT</pubDate></item><item><title><![CDATA[Использование useRef для хранения значений]]></title><description><![CDATA[Хук useRef можно использовать не только для доступа к DOM-элементам, но и для хранения любых изменяемых значений, которые должны сохраняться между рендерами, но не должны вызывать перерисовку компонента.Значение, хранящееся в ref.current, остаётся неизменным в течение всего жизненного цикла компонента, если вы его явно не измените. При этом:
Изменение ref.current не запускает повторный рендер.
Значение доступно во всех обработчиках, эффектах и даже внутри замыканий без потери актуальности (в отличие от переменных в теле компонента).
Полезно для сравнения текущего и предыдущего состояния или пропса:function usePrevious(value) { const ref = useRef(); useEffect(() =&gt; { ref.current = value; }); return ref.current;
} function Counter({ count }) { const prevCount = usePrevious(count); return &lt;p&gt;Сейчас: {count}, было: {prevCount}&lt;/p&gt;;
}
Чтобы избежать создания новых таймеров при каждом рендере:function Timer() { const intervalRef = useRef(null); useEffect(() =&gt; { intervalRef.current = setInterval(() =&gt; { console.log('Тик'); }, 1000); return () =&gt; clearInterval(intervalRef.current); }, []); function stopTimer() { clearInterval(intervalRef.current); } return &lt;button onClick={stopTimer}&gt;Остановить&lt;/button&gt;;
}
Если вычисление зависит от внешних данных и не должно зависеть от ререндера:function ExpensiveComponent({ data }) { const cacheRef = useRef(null); if (!cacheRef.current || cacheRef.current.input !== data) { cacheRef.current = { input: data, output: heavyComputation(data) }; } return &lt;div&gt;{cacheRef.current.output}&lt;/div&gt;;
} useState — для данных, влияющих на UI (изменение → рендер).
useRef — для данных, нужных «внутри» логики, но не отображаемых напрямую.
Например, счётчик попыток авторизации, который не отображается, но используется в фоне — хороший кандидат для ref.
Не мутируйте ref.current во время рендера (например, внутри основного тела компонента). Это может привести к непредсказуемому поведению.
Значение в ref не сериализуется и не сохраняется при горячей перезагрузке (HMR), если не предусмотрена дополнительная логика.
Использование useRef для хранения значений — это способ сохранить "память" компонента без лишних ререндеров.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/использование-useref-для-хранения-значений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Использование useRef для хранения значений.md</guid><pubDate>Sat, 17 Jan 2026 09:33:03 GMT</pubDate></item><item><title><![CDATA[Использование useRef для DOM-элементов]]></title><description><![CDATA[Хук useRef позволяет получить прямую ссылку на реальный DOM-элемент, что бывает необходимо, когда стандартного управления через состояние недостаточно.Чтобы связать ref с DOM-элементом, передайте его в атрибут ref:const inputRef = useRef(null); return &lt;input ref={inputRef} type="text" /&gt;;
После монтирования компонента inputRef.current будет содержать настоящий HTML-элемент &lt;input&gt;.Автоматически установить фокус на поле ввода при открытии формы:function AutoFocusInput() { const inputRef = useRef(null); useEffect(() =&gt; { inputRef.current.focus(); }, []); return &lt;input ref={inputRef} /&gt;;
}
Иногда удобно прочитать значение поля напрямую, особенно в неконтролируемых компонентах:function Form() { const inputRef = useRef(null); function handleSubmit() { console.log('Значение:', inputRef.current.value); } return ( &lt;form onSubmit={(e) =&gt; { e.preventDefault(); handleSubmit(); }}&gt; &lt;input ref={inputRef} defaultValue="" /&gt; &lt;button type="submit"&gt;Отправить&lt;/button&gt; &lt;/form&gt; );
}
Пример с видео:function VideoPlayer() { const videoRef = useRef(null); function play() { videoRef.current.play(); } function pause() { videoRef.current.pause(); } return ( &lt;&gt; &lt;video ref={videoRef} src="movie.mp4" /&gt; &lt;button onClick={play}&gt;▶️&lt;/button&gt; &lt;button onClick={pause}&gt;⏸️&lt;/button&gt; &lt;/&gt; );
} ref.current становится доступен только после того, как React создаст соответствующий DOM-узел (обычно внутри useEffect).
Не пытайтесь читать или изменять ref.current во время рендера — это может привести к ошибкам.
Ref работает только с DOM-элементами и классовыми компонентами. Для функциональных компонентов требуется forwardRef.
Прямой доступ к DOM через useRef — мощный инструмент, но его следует использовать только тогда, когда невозможно обойтись state и props.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/использование-useref-для-dom-элементов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Использование useRef для DOM-элементов.md</guid><pubDate>Sat, 17 Jan 2026 09:31:31 GMT</pubDate></item><item><title><![CDATA[Что такое Ref]]></title><description><![CDATA[Ref (сокращение от reference) в React — это способ получить прямой доступ к DOM-элементу или сохранить значение, которое не вызывает перерисовку компонента при изменении. Ref особенно полезен, когда нужно работать с элементами вне обычного потока данных через props и state.Для создания ref используется хук useRef:const myRef = useRef(initialValue);
После этого myRef.current содержит текущее значение. При первом рендере myRef.current равно переданному начальному значению.Чтобы привязать ref к DOM-элементу, передайте его в атрибут ref:&lt;input ref={myRef} /&gt;
Теперь myRef.current будет ссылаться на настоящий DOM-элемент &lt;input&gt;.Основное отличие useRef от useState:
Изменение ref.current не вызывает повторный рендер компонента.
ref предназначен для хранения данных, которые нужны между рендерами, но не влияют на то, как компонент выглядит.
Это делает ref идеальным для:
Хранения ссылок на таймеры, интервалы или внешние объекты
Сохранения предыдущих значений props или state
Прямого взаимодействия с DOM (фокус, измерение размеров, воспроизведение видео)
Используйте ref, когда:
Нужно управлять фокусом, выделением текста или воспроизведением медиа
Требуется доступ к DOM-методам (например, scrollIntoView)
Необходимо хранить значение, которое не должно влиять на UI
Не используйте ref для данных, которые определяют внешний вид компонента — для этого подходит useState.<a data-href="Использование useRef для DOM-элементов" href="материалы/подтемы/секция-2.-react/тема-№16/использование-useref-для-dom-элементов.html" class="internal-link" target="_self" rel="noopener nofollow">Использование useRef для DOM-элементов</a><br>
<a data-href="Использование useRef для хранения значений" href="материалы/подтемы/секция-2.-react/тема-№16/использование-useref-для-хранения-значений.html" class="internal-link" target="_self" rel="noopener nofollow">Использование useRef для хранения значений</a><br>
<a data-href="Ограничения и рекомендации" href="материалы/подтемы/секция-2.-react/тема-№16/ограничения-и-рекомендации.html" class="internal-link" target="_self" rel="noopener nofollow">Ограничения и рекомендации</a>]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/что-такое-ref.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Что такое Ref.md</guid><pubDate>Sat, 17 Jan 2026 09:30:57 GMT</pubDate></item><item><title><![CDATA[onFocus и onBlur]]></title><description><![CDATA[События onFocus и onBlur позволяют отслеживать, когда элемент получает или теряет фокус. Они особенно полезны для полей ввода, кнопок и других интерактивных элементов.Событие onFocus срабатывает, когда пользователь переходит на элемент — например, кликает по полю ввода или перемещается к нему с помощью клавиши Tab.function InputWithFocus() { function handleFocus() { console.log('Поле получило фокус'); } return &lt;input onFocus={handleFocus} /&gt;;
}
Событие onBlur срабатывает, когда элемент теряет фокус — например, пользователь кликает вне поля или переключается на другой элемент.function InputWithBlur() { function handleBlur() { console.log('Поле потеряло фокус'); } return &lt;input onBlur={handleBlur} /&gt;;
}
Эти события часто используются вместе:
Для показа подсказок или ошибок при потере фокуса (валидация «на лету»)
Для скрытия/показа дополнительного интерфейса (например, календаря при фокусе на дате)
Для отслеживания активного поля в сложных формах
Пример: валидация email после того, как пользователь завершил ввод:function EmailInput() { const [email, setEmail] = useState(''); const [error, setError] = useState(''); function validate(value) { if (!value.includes('@')) { setError('Email должен содержать @'); } else { setError(''); } } return ( &lt;&gt; &lt;input value={email} onChange={(e) =&gt; setEmail(e.target.value)} onBlur={() =&gt; validate(email)} /&gt; {error &amp;&amp; &lt;span style={{ color: 'red' }}&gt;{error}&lt;/span&gt;} &lt;/&gt; );
} onFocus и onBlur не всплывают так же, как другие события, но React нормализует их поведение.
Эти события не срабатывают при программном изменении фокуса (например, через ref.current.focus()), если только не используется нативный DOM-метод напрямую.
Использование onBlur для валидации предпочтительнее, чем onChange, если проверка дорогая или должна происходить только после завершения ввода.
События onFocus и onBlur помогают создавать более отзывчивый и удобный интерфейс, реагирующий на этапы взаимодействия пользователя с элементами.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/onfocus-и-onblur.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/onFocus и onBlur.md</guid><pubDate>Sat, 17 Jan 2026 09:28:42 GMT</pubDate></item><item><title><![CDATA[onSubmit]]></title><description><![CDATA[Событие onSubmit срабатывает, когда пользователь отправляет форму — например, нажимает кнопку с type="submit" или вводит Enter в поле внутри формы.Обработчик onSubmit привязывается к элементу &lt;form&gt;:function Form() { function handleSubmit(event) { event.preventDefault(); // предотвращает перезагрузку страницы console.log('Форма отправлена'); } return ( &lt;form onSubmit={handleSubmit}&gt; &lt;input type="text" name="username" /&gt; &lt;button type="submit"&gt;Отправить&lt;/button&gt; &lt;/form&gt; );
}
Без вызова event.preventDefault() браузер выполнит стандартное действие — отправит форму и перезагрузит страницу, что в React-приложениях почти всегда нежелательно.В управляемых компонентах данные обычно берутся из состояния:function Form() { const [username, setUsername] = useState(''); function handleSubmit(event) { event.preventDefault(); console.log('Имя пользователя:', username); } return ( &lt;form onSubmit={handleSubmit}&gt; &lt;input type="text" value={username} onChange={(e) =&gt; setUsername(e.target.value)} /&gt; &lt;button type="submit"&gt;Отправить&lt;/button&gt; &lt;/form&gt; );
}
В неконтролируемых формах можно использовать ref для доступа к значениям напрямую.
Кнопка внутри формы по умолчанию имеет type="submit", если не указано иное. Чтобы избежать случайной отправки, явно указывайте type="button" для обычных кнопок.
Событие onSubmit всплывает, но его можно остановить с помощью event.stopPropagation(), если нужно изолировать обработку.
Отправка формы возможна не только через кнопку: нажатие Enter в текстовом поле также вызывает onSubmit.
Событие onSubmit — центральный механизм обработки пользовательского ввода в формах и основа для валидации, отправки данных на сервер и управления состоянием приложения.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/onsubmit.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/onSubmit.md</guid><pubDate>Sat, 17 Jan 2026 09:28:11 GMT</pubDate></item><item><title><![CDATA[onChange]]></title><description><![CDATA[Событие onChange срабатывает, когда пользователь изменяет значение элемента формы — например, вводит текст в поле, выбирает опцию в выпадающем списке или ставит галочку в чекбоксе.Обработчик onChange обычно используется вместе с управляемыми компонентами, где значение поля контролируется состоянием React:function InputField() { const [value, setValue] = useState(''); function handleChange(event) { setValue(event.target.value); } return &lt;input value={value} onChange={handleChange} /&gt;;
}
Каждый ввод обновляет состояние, и React немедленно отображает новое значение.В обработчик передаётся объект события. Чтобы получить текущее значение поля, используйте event.target.value:function handleChange(event) { console.log('Текущее значение:', event.target.value);
}
Для чекбоксов и радиокнопок значение находится в event.target.checked.function Checkbox() { const [checked, setChecked] = useState(false); function handleChange(event) { setChecked(event.target.checked); } return &lt;input type="checkbox" checked={checked} onChange={handleChange} /&gt;;
} onChange срабатывает при любом изменении, а не только при потере фокуса (в отличие от нативного DOM-события change в некоторых старых браузерах).
В React это событие нормализовано: оно работает одинаково для всех типов полей ввода.
Не используйте onChange без управления значением через value (или checked) — это приведёт к неконтролируемому поведению и предупреждениям в консоли.
Событие onChange — основа для создания интерактивных форм в React и ключевой элемент паттерна управляемых компонентов.]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/onchange.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/onChange.md</guid><pubDate>Sat, 17 Jan 2026 09:26:56 GMT</pubDate></item><item><title><![CDATA[onClick]]></title><description><![CDATA[Событие onClick срабатывает, когда пользователь нажимает на элемент — например, кнопку, ссылку или любой другой кликабельный компонент.Обработчик onClick передаётся как пропс в JSX-элемент:&lt;button onClick={handleClick}&gt;Нажми меня&lt;/button&gt;
Функция handleClick будет вызвана при каждом клике. Она может быть определена внутри компонента:function Button() { function handleClick() { console.log('Кнопка нажата'); } return &lt;button onClick={handleClick}&gt;Нажми&lt;/button&gt;;
}
Обработчик может принимать объект события как аргумент:function handleClick(event) { console.log(event.target); // элемент, по которому кликнули
}
Это позволяет получать информацию о контексте клика, например, значение кнопки или её атрибуты.Если нужно передать данные в обработчик, используйте стрелочную функцию:&lt;button onClick={() =&gt; handleDelete(id)}&gt;Удалить&lt;/button&gt;
Важно: не вызывайте функцию напрямую (onClick={handleDelete(id)}), иначе она выполнится сразу при рендере.
onClick работает на любом элементе, даже если он не интерактивный (например, &lt;div&gt;), но для доступности лучше использовать семантические теги (&lt;button&gt;) или добавлять role="button".
В мобильных браузерах onClick может иметь небольшую задержку; для мгновенного отклика иногда используют onTouchStart, но это редко требуется в современных приложениях.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/onclick.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/onClick.md</guid><pubDate>Sat, 17 Jan 2026 09:26:21 GMT</pubDate></item><item><title><![CDATA[Обработка событий в React]]></title><description><![CDATA[В React обработка событий — это механизм, позволяющий компонентам реагировать на действия пользователя: клики, ввод текста, отправку формы, фокус и другие взаимодействия. События в React похожи на события в DOM, но имеют несколько важных отличий.Имена событий в React пишутся в camelCase, а не в нижнем регистре, как в HTML. Например:
<a data-href="onClick" href="материалы/подтемы/секция-2.-react/тема-№16/onclick.html" class="internal-link" target="_self" rel="noopener nofollow">onClick</a> вместо onclick
<br><a data-href="onChange" href="материалы/подтемы/секция-2.-react/тема-№16/onchange.html" class="internal-link" target="_self" rel="noopener nofollow">onChange</a> вместо onchange
<br><a data-href="onSubmit" href="материалы/подтемы/секция-2.-react/тема-№16/onsubmit.html" class="internal-link" target="_self" rel="noopener nofollow">onSubmit</a> вместо onsubmit
Обработчик передаётся как функция, а не как строка:// Правильно
&lt;button onClick={handleClick}&gt;Нажми&lt;/button&gt; // Неправильно
&lt;button onClick={handleClick()}&gt;Нажми&lt;/button&gt;
Вызов handleClick() при передаче приведёт к немедленному выполнению функции при каждом рендере, а не при клике.React поддерживает стандартные события пользовательского взаимодействия:
<br><a data-href="onClick" href="материалы/подтемы/секция-2.-react/тема-№16/onclick.html" class="internal-link" target="_self" rel="noopener nofollow">onClick</a> — нажатие кнопки или другого элемента
<br><a data-href="onChange" href="материалы/подтемы/секция-2.-react/тема-№16/onchange.html" class="internal-link" target="_self" rel="noopener nofollow">onChange</a> — изменение значения в &lt;input&gt;, &lt;select&gt; или &lt;textarea&gt;
<br><a data-href="onSubmit" href="материалы/подтемы/секция-2.-react/тема-№16/onsubmit.html" class="internal-link" target="_self" rel="noopener nofollow">onSubmit</a> — отправка формы
<br><a data-href="onFocus и onBlur" href="материалы/подтемы/секция-2.-react/тема-№16/onfocus-и-onblur.html" class="internal-link" target="_self" rel="noopener nofollow">onFocus и onBlur</a> — получение и потеря фокуса
Пример обработки отправки формы:function Form() { function handleSubmit(event) { event.preventDefault(); // отменяет перезагрузку страницы console.log('Форма отправлена'); } return ( &lt;form onSubmit={handleSubmit}&gt; &lt;input type="text" /&gt; &lt;button type="submit"&gt;Отправить&lt;/button&gt; &lt;/form&gt; );
}
Обработчики получают в качестве аргумента объект события (event). Он содержит информацию о произошедшем действии и методы для управления поведением по умолчанию.Часто используемые методы:
event.preventDefault() — отменяет стандартное действие (например, отправку формы)
event.stopPropagation() — останавливает всплытие события вверх по дереву DOM
Пример:function handleClick(event) { event.stopPropagation(); console.log('Клик только на эту кнопку');
} Обработчики не вызываются автоматически — они срабатывают только при соответствующем пользовательском действии.
Функция-обработчик должна быть передана, а не вызвана.
Все события в React нормализованы: они работают одинаково во всех браузерах, даже если нативные события отличаются.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№16/обработка-событий-в-react.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №16/Обработка событий в React.md</guid><pubDate>Sat, 17 Jan 2026 09:24:49 GMT</pubDate></item><item><title><![CDATA[Тема №14. Работа со стилями, изображениями и файлами в React]]></title><description><![CDATA[В этой теме вы научитесь правильно подключать изображения, шрифты и другие ресурсы в React-приложении через импорт, поймёте, как работает сборщик (Webpack/Vite), почему файлы кажутся исчезающими после сборки и как избежать ошибок, связанных с неправильным путём. Это фундамент для создания стабильных, корректно собранных приложений — где всё отображается, как задумано.
<a data-href="Импорт функций и переменных JS" href="материалы/подтемы/секция-2.-react/тема-№14/импорт-функций-и-переменных-js.html" class="internal-link" target="_self" rel="noopener nofollow">Импорт функций и переменных JS</a>
<br><a data-href="Как React обрабатывает импорт файлов" href="материалы/подтемы/секция-2.-react/тема-№14/как-react-обрабатывает-импорт-файлов.html" class="internal-link" target="_self" rel="noopener nofollow">Как React обрабатывает импорт файлов</a>
<br><a data-href="Какие файлы можно импортировать" href="материалы/подтемы/секция-2.-react/тема-№14/какие-файлы-можно-импортировать.html" class="internal-link" target="_self" rel="noopener nofollow">Какие файлы можно импортировать</a>
<br><a data-href="Что делать с файлами в папке public" href="материалы/подтемы/секция-2.-react/тема-№14/что-делать-с-файлами-в-папке-public.html" class="internal-link" target="_self" rel="noopener nofollow">Что делать с файлами в папке public</a>
<br><a data-href="Работа со стилями и файлами" href="материалы/подтемы/секция-2.-react/тема-№14/работа-со-стилями-и-файлами.html" class="internal-link" target="_self" rel="noopener nofollow">Работа со стилями и файлами</a>
<br><a data-href="Практические ошибки и как их избежать" href="материалы/подтемы/секция-2.-react/тема-№14/практические-ошибки-и-как-их-избежать.html" class="internal-link" target="_self" rel="noopener nofollow">Практические ошибки и как их избежать</a>
(пусто)<br><a data-href="Тема №15. Хранение и передача данных в React" href="лекции/секция-2.-react/тема-№15.-хранение-и-передача-данных-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №15. Хранение и передача данных в React</a>]]></description><link>лекции/секция-2.-react/тема-№14.-работа-со-стилями,-изображениями-и-файлами-в-react.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №14. Работа со стилями, изображениями и файлами в React.md</guid><pubDate>Fri, 17 Oct 2025 16:16:37 GMT</pubDate></item><item><title><![CDATA[Практические ошибки и как их избежать]]></title><description><![CDATA[При работе с файлами и ресурсами в React-приложениях часто возникают ошибки, связанные с непониманием того, как сборщик (Webpack/Vite) обрабатывает зависимости. Большинство проблем проявляются только в продакшене, что усложняет отладку.Ошибка: &lt;img src="./assets/logo.png" /&gt;
Почему плохо:
Сборщик не видит зависимость → файл не копируется в сборку → изображение не загружается в продакшене.
Решение:
Всегда импортируйте: import logo from './assets/logo.png';
&lt;img src={logo} /&gt;
Ошибка: &lt;img src={require('./logo.png')} /&gt;
Почему плохо:
require — часть CommonJS, не поддерживается в Vite и не рекомендуется в современных проектах.
Решение:
Используйте ES-модули: import logo from './logo.png';.Ошибка:
Кладёте logo.png в public/ и используете &lt;img src="/logo.png" /&gt;.
Почему плохо: Нет хеширования → кэширование ломается при обновлении,
Сборщик не проверяет наличие файла → опечатка = 404 в продакшене,
Нарушается модульность компонентов.
Решение:
Используйте public/ только для favicon.ico, robots.txt, manifest.json. Остальное — через импорт из src/.
Ошибка: background: url('assets/bg.jpg');
Почему плохо:
Путь не относительный от CSS-файла → сборщик не находит файл.
Решение:
Всегда используйте относительные пути: background: url('../assets/images/bg.jpg');
Ошибка: const icon = `./icons/${name}.png`;
// или
import(`./icons/${name}.png`);
Почему плохо:
Сборщик не может определить, какие файлы нужны → либо ошибка, либо в бандл попадают все файлы из папки.
Решение:
Используйте маппинг или заранее импортируйте нужные файлы: const icons = { home: require('./icons/home.png'), user: require('./icons/user.png')
};
// или с import (в верхнем уровне модуля)
import homeIcon from './icons/home.png';
import userIcon from './icons/user.png'; Всегда проверяйте сборку: запускайте npm run build и открывайте build/ или dist/ локально.
Не полагайтесь на поведение dev-сервера: то, что работает в разработке, может сломаться в продакшене.
Используйте IDE-подсказки: если путь в import подсвечивается как ошибка — файл не найден.
Храните все ресурсы в src/, кроме тех, что явно требуют размещения в public/.
Понимание границ ответственности сборщика — ключ к стабильной работе с файлами в React.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/практические-ошибки-и-как-их-избежать.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Практические ошибки и как их избежать.md</guid><pubDate>Fri, 17 Oct 2025 16:16:01 GMT</pubDate></item><item><title><![CDATA[Импорт функций и переменных JS]]></title><description><![CDATA[Импорт функций и переменных из JavaScript-файлов — это основа модульной архитектуры в React. В отличие от статических ресурсов (изображений, шрифтов и т.д.), код импортируется и выполняется как часть приложения, а не как внешний ассет. Это достигается с помощью стандарта ES-модулей, поддерживаемого всеми современными сборщиками.В одном файле (например, utils.js) вы объявляете и экспортируете функции или переменные:// utils.js
export const API_URL = 'https://api.example.com';
export function formatDate(date) { return date.toLocaleDateString();
}
В компоненте или другом модуле вы импортируете их:import { API_URL, formatDate } from './utils'; function App() { return &lt;div&gt;Адрес API: {API_URL}&lt;/div&gt;;
} Именованный экспорт (export const x = ...) — позволяет экспортировать несколько значений из одного файла. Импортируется в фигурных скобках. Экспорт по умолчанию (export default function ...) — один экспорт на файл. Импортируется без скобок:
// logger.js
export default function log(message) { console.log('[APP]', message);
} // App.jsx
import log from './logger'; Когда вы импортируете JS-модуль:
Сборщик выполняет код файла (а не просто копирует его),
Значения становятся частью JavaScript-бандла,
Нет генерации хешей в именах — модуль встраивается в общий код,
Поддерживается tree-shaking: неиспользуемые именованные экспорты могут быть удалены из финальной сборки.
В отличие от изображений или JSON, вы не получаете строку с путём — вы получаете сами значения (функции, объекты, примитивы).
Вынос логики в утилиты (formatDate, validateEmail),
Централизованное хранение констант (API_URL, THEME_COLORS),
Разделение компонентов и бизнес-логики,
Создание переиспользуемых хуков (useLocalStorage, useDebounce).
Импорт JS-модулей — это не «работа с файлами» в смысле ресурсов, а основа структуры кода. Он не требует специальной обработки сборщиком, кроме объединения и оптимизации модулей.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/импорт-функций-и-переменных-js.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Импорт функций и переменных JS.md</guid><pubDate>Fri, 17 Oct 2025 16:14:59 GMT</pubDate></item><item><title><![CDATA[Работа со стилями и файлами]]></title><description><![CDATA[Стили в React-приложениях тесно связаны с обработкой файлов: CSS-файлы импортируются как зависимости, а ссылки на ресурсы внутри CSS (например, шрифты или фоновые изображения) также проходят через сборщик. Это обеспечивает целостность проекта — все ресурсы управляются единообразно.Глобальные стили подключаются через импорт в JavaScript:import './styles/global.css';
Сборщик обрабатывает этот файл, включает его в бандл и гарантирует, что стили применятся к приложению. Путь должен быть относительным (начинаться с ./ или ../).Для изоляции стилей компонентов используйте CSS-модули:import styles from './Button.module.css'; function Button() { return &lt;button className={styles.primary}&gt;Клик&lt;/button&gt;;
}
Имена классов автоматически хешируются, что предотвращает конфликты. Файл должен иметь расширение .module.css.Шрифты подключаются внутри CSS-файлов с помощью @font-face:/* src/styles/fonts.css */
@font-face { font-family: 'Inter'; src: url('../assets/fonts/Inter.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap;
}
Важно: путь в url() — относительный от CSS-файла к файлу шрифта. Сборщик распознаёт эту ссылку, копирует шрифт в папку сборки и подставляет корректный путь.Аналогично шрифтам, фоновые изображения указываются через url():.header { background-image: url('../assets/images/bg.jpg');
}
Сборщик обработает путь, скопирует изображение и заменит url() на хешированный путь. Это работает только если CSS импортирован в JavaScript. Если CSS подключён через &lt;link&gt; из public/, сборщик не увидит зависимость — изображение не попадёт в сборку.
Все ресурсы, используемые в CSS (url(...)), должны находиться в src/, а не в public/.
Не подключайте CSS через &lt;link href="/styles.css"&gt; в public/index.html, если этот CSS ссылается на локальные файлы — сборщик их проигнорирует.
Используйте относительные пути в url() — они разрешаются относительно расположения CSS-файла.
Такой подход обеспечивает, что стили и связанные с ними ресурсы обрабатываются как единая зависимость, что критично для корректной работы в продакшене.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/работа-со-стилями-и-файлами.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Работа со стилями и файлами.md</guid><pubDate>Fri, 17 Oct 2025 16:10:32 GMT</pubDate></item><item><title><![CDATA[Что делать с файлами в папке public]]></title><description><![CDATA[Папка public/ — это особое место в React-проекте: файлы в ней копируются в корень сборки без обработки, без хеширования и без анализа зависимостей. Они доступны по корневому пути (/filename.ext) и не проходят через сборщик (Webpack/Vite).Если у вас есть файл public/logo.png, обращайтесь к нему напрямую через корневой путь:&lt;img src="/logo.png" alt="Логотип" /&gt;
Обратите внимание: путь начинается с /, а не с ./. Это означает, что браузер запросит файл по адресу https://ваш-сайт.com/logo.png.Папка public/ предназначена только для файлов, которые не импортируются в JavaScript-код:
favicon.ico — иконка сайта,
robots.txt — инструкции для поисковых роботов,
manifest.json — метаданные для PWA,
sitemap.xml — карта сайта,
Статические файлы, доступные по прямой ссылке (например, public/docs/instruction.pdf).
Эти файлы должны быть доступны по фиксированному пути и не зависят от логики приложения.Не кладите в public/ изображения, шрифты, аудио или другие ресурсы, используемые в компонентах. Причины:
Сборщик не знает, что они нужны — не проверяет наличие, не удаляет неиспользуемые,
Нет хеширования → браузер может кэшировать старую версию навсегда,
Нарушается модульность: компонент зависит от глобального состояния файловой системы,
При переименовании файла — ошибка обнаружится только вручную, не на этапе сборки.
Например, &lt;img src="/assets/logo.png" /&gt; с файлом в public/assets/logo.png — плохая практика. Правильно: импортировать из src/assets/.Задайте себе вопрос: «Будет ли этот файл запрашиваться напрямую по URL, без участия React-кода?»
Если да — кладите в public/.
Если нет — импортируйте из src/.Использование public/ должно быть исключением, а не правилом.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/что-делать-с-файлами-в-папке-public.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Что делать с файлами в папке public.md</guid><pubDate>Fri, 17 Oct 2025 16:08:30 GMT</pubDate></item><item><title><![CDATA[env-файлы]]></title><description><![CDATA[.env-файлы в React-приложениях не импортируются напрямую, как обычные модули. Вместо этого они обрабатываются сборщиком (Webpack в Create React App, Vite в Vite-проектах) на этапе сборки, и их содержимое становится доступно через глобальную переменную process.env.Создайте файл .env в корне проекта (рядом с package.json):REACT_APP_API_URL=https://api.example.com
REACT_APP_VERSION=1.2.0
Важно: В Create React App переменные должны начинаться с REACT_APP_. В Vite — с VITE_ (или VITE_SOME_VAR), а в коде доступны как import.meta.env.VITE_SOME_VAR.
Пример для CRA:// .env
REACT_APP_API_URL=https://api.example.com
// Компонент
function App() { console.log(process.env.REACT_APP_API_URL); // "https://api.example.com" return null;
}
Пример для Vite:# .env
VITE_API_URL=https://api.example.com
// Компонент
function App() { console.log(import.meta.env.VITE_API_URL); // "https://api.example.com" return null;
}
Файл .env никогда не попадает в клиентский бандл. Сборщик читает его на этапе сборки, подставляет значения переменных в код (инлайнит их как строки), а сам файл игнорирует. Это сделано специально:
Чтобы избежать утечки чувствительных данных (хотя на клиенте всё равно видно),
Чтобы обеспечить статическую замену значений, что позволяет оптимизировать код.
Попытка написать import env from './.env' приведёт к ошибке — сборщик не обрабатывает .env как ресурс.Сборщики поддерживают разные файлы в зависимости от режима:
.env — общие значения для всех режимов,
.env.local — локальные переопределения (игнорируются в Git),
.env.development, .env.production — значения для конкретных режимов.
Приоритет: .env.local &gt; .env.development.local &gt; .env.development &gt; .env.
Никаких секретов: всё, что попадает в process.env или import.meta.env, будет видно в браузере. Используйте .env только для публичных данных (URL API, флаги функций, версии).
Только строки: значения всегда интерпретируются как строки. Для чисел или булевых значений преобразуйте вручную: const timeout = Number(process.env.REACT_APP_TIMEOUT).
Переменные должны быть объявлены явно: динамический доступ вроде process.env[variableName] не работает — сборщик не может определить, какие переменные нужны.
.env-файлы — удобный способ управлять конфигурацией между средами, но помните: они предназначены только для публичных, несекретных данных.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/env-файлы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/env-файлы.md</guid><pubDate>Fri, 17 Oct 2025 16:06:13 GMT</pubDate></item><item><title><![CDATA[Какие файлы можно импортировать]]></title><description><![CDATA[React-приложения, собранные с помощью Webpack или Vite, поддерживают импорт различных типов файлов напрямую в JavaScript- или TypeScript-код. Сборщик автоматически обрабатывает такие импорты: копирует файлы в папку сборки, генерирует корректные пути и, при необходимости, преобразует содержимое. Это позволяет работать с ресурсами как с модулями, обеспечивая предсказуемость и контроль над зависимостями.Сборщики по умолчанию распознают и обрабатывают следующие форматы:
Изображения: .png, .jpg, .jpeg, .gif, .webp SVG: как изображение или как React-компонент Шрифты: .woff, .woff2, .ttf Аудио и видео: .mp3, .wav, .ogg, .mp4, .webm JSON: .json Переменные окружения: .env (не импортируются напрямую, но доступны через process.env)
Каждый тип имеет свои особенности использования, которые подробно описаны на отдельных подстраницах:
<a data-href="Изображения" href="материалы/подтемы/секция-2.-react/тема-№14/изображения.html" class="internal-link" target="_self" rel="noopener nofollow">Изображения</a> <br><a data-href="SVG" href="материалы/подтемы/секция-2.-react/тема-№14/svg.html" class="internal-link" target="_self" rel="noopener nofollow">SVG</a> <br><a data-href="Шрифты" href="материалы/подтемы/секция-2.-react/тема-№14/шрифты.html" class="internal-link" target="_self" rel="noopener nofollow">Шрифты</a> <br><a data-href="Аудио и видео" href="материалы/подтемы/секция-2.-react/тема-№14/аудио-и-видео.html" class="internal-link" target="_self" rel="noopener nofollow">Аудио и видео</a> <br><a data-href="JSON-файлы" href="материалы/подтемы/секция-2.-react/тема-№14/json-файлы.html" class="internal-link" target="_self" rel="noopener nofollow">JSON-файлы</a> <br><a data-href="env-файлы" href="материалы/подтемы/секция-2.-react/тема-№14/env-файлы.html" class="internal-link" target="_self" rel="noopener nofollow">env-файлы</a>
]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/какие-файлы-можно-импортировать.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Какие файлы можно импортировать.md</guid><pubDate>Fri, 17 Oct 2025 16:02:36 GMT</pubDate></item><item><title><![CDATA[JSON-файлы]]></title><description><![CDATA[JSON-файлы в React-приложениях можно импортировать напрямую, как обычные JavaScript-модули. Сборщики (Webpack и Vite) по умолчанию поддерживают такой импорт: содержимое JSON автоматически парсится и становится доступным как обычный объект или массив в коде.Предположим, у вас есть файл src/config/settings.json:{ "apiUrl": "https://api.example.com", "features": ["darkMode", "notifications"], "version": "1.2.0"
}
Вы можете импортировать его в компоненте или модуле:import settings from './config/settings.json'; function App() { console.log(settings.apiUrl); // "https://api.example.com" return &lt;div&gt;Версия: {settings.version}&lt;/div&gt;;
}
Переменная settings — это уже готовый JavaScript-объект, не строка. Никакого дополнительного парсинга (JSON.parse) не требуется.
Типобезопасность: при использовании TypeScript типы можно автоматически выводить или задавать через декларации.
Статический анализ: сборщик видит зависимость, и если файл удалён или переименован, вы получите ошибку на этапе сборки.
Tree-shaking: если вы используете только часть данных, современные сборщики могут исключить неиспользуемые поля (в ограниченных случаях).
Кэширование и хеширование: как и другие ресурсы, JSON-файлы получают хеш в имени при сборке, что обеспечивает корректное кэширование. Конфигурации, которые известны на этапе сборки (не секреты!),
Статические данные: списки, переводы, моки для разработки,
Метаданные компонентов или страниц. Не храните секреты (API-ключи, пароли) в JSON-файлах — они попадут в клиентский бандл и будут видны любому.
Динамические данные (например, ответы от сервера) должны загружаться через fetch, а не через импорт.
Путь при импорте должен быть статическим: import data from ./data/${name}.json`` не сработает, так как сборщик не может определить имя файла во время сборки.
Импорт JSON — простой и надёжный способ включить структурированные статические данные в ваше React-приложение.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/json-файлы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/JSON-файлы.md</guid><pubDate>Fri, 17 Oct 2025 16:01:13 GMT</pubDate></item><item><title><![CDATA[Аудио и видео]]></title><description><![CDATA[Аудио- и видеофайлы (.mp3, .wav, .ogg, .mp4, .webm и др.) в React-приложениях импортируются так же, как изображения: через import. Сборщик (Webpack или Vite) копирует файл в папку сборки, добавляет хеш к имени и возвращает строку с корректным путём, который можно использовать в элементах &lt;audio&gt; и &lt;video&gt;.import clickSound from './assets/sounds/click.mp3';
import introVideo from './assets/videos/intro.mp4'; function MediaPlayer() { return ( &lt;&gt; &lt;audio controls src={clickSound} /&gt; &lt;video controls src={introVideo} width="640" /&gt; &lt;/&gt; );
}
Переменные clickSound и introVideo содержат абсолютные пути к скомпилированным файлам (например, /static/media/click.a1b2c3.mp3). Это гарантирует, что файлы будут включены в сборку и доступны в продакшене.Запись вида &lt;audio src="./assets/sounds/click.mp3" /&gt; не работает после сборки, потому что:
Сборщик не распознаёт строку как зависимость,
Файл не копируется в папку dist/ или build/,
В браузере возникает ошибка 404.
Только импорт через import делает файл частью зависимостей приложения.
Размер файлов: аудио и видео часто имеют большой объём. Сборщик может встроить очень маленькие файлы прямо в JavaScript-бандл (base64), но для больших файлов всегда создаётся отдельный ресурс. Уточните настройки assetSizeLimit в конфигурации сборщика, если нужно изменить это поведение.
Форматы: используйте современные и эффективные форматы: Аудио: .mp3 (широкая поддержка) или .ogg (лучшее сжатие),
Видео: .mp4 с кодеком H.264 (универсальный) или .webm (лучшее сжатие для веба). Загрузка по требованию: для больших видео рассмотрите ленивую загрузку или размещение на CDN, чтобы не увеличивать размер начальной сборки.
Путь к файлу: всегда используйте относительные пути при импорте (начинаются с ./ или ../).
Импорт через import — единственный надёжный способ подключить медиафайлы, управляемые сборщиком.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/аудио-и-видео.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Аудио и видео.md</guid><pubDate>Fri, 17 Oct 2025 15:59:33 GMT</pubDate></item><item><title><![CDATA[Шрифты]]></title><description><![CDATA[Шрифты в React-приложениях подключаются не напрямую в компонентах, а через CSS-файлы с использованием правила @font-face. Это стандартный веб-подход, который корректно интегрируется со сборщиками (Webpack, Vite): при импорте CSS-файла сборщик обнаруживает ссылки на шрифты, копирует их в папку сборки и подставляет правильные пути.
Поместите файл шрифта в папку проекта, например src/assets/fonts/Inter.woff2.
Создайте CSS-файл (например, src/styles/fonts.css) и опишите шрифт:
@font-face { font-family: 'Inter'; src: url('../assets/fonts/Inter.woff2') format('woff2'); font-weight: 400; font-style: normal; font-display: swap;
} Важно: путь в url() должен быть относительным от CSS-файла к файлу шрифта.
Импортируйте CSS в корневой компонент или точку входа:
import './styles/fonts.css'; Теперь шрифт зарегистрирован, и его можно использовать в любых стилях.
Сборщики по умолчанию обрабатывают:
.woff2 — современный, сжатый формат (рекомендуется как основной),
.woff — более старый, но широко поддерживаемый,
.ttf — TrueType, используется редко из-за большого размера.
Используйте .woff2 как основной формат. Для максимальной совместимости можно указать несколько источников:@font-face { font-family: 'MyFont'; src: url('../fonts/MyFont.woff2') format('woff2'), url('../fonts/MyFont.woff') format('woff'); font-weight: normal; font-style: normal;
}
В отличие от изображений, шрифты не используются как значения в JSX. Они применяются через CSS, поэтому импорт в JavaScript (import font from './font.woff2') бесполезен — вы получите строку с путём, но не сможете зарегистрировать шрифт в браузере. Единственный корректный способ — через @font-face в CSS.
Всегда указывайте font-display: swap; — это улучшает показатели Core Web Vitals, позволяя тексту отображаться сразу с резервным шрифтом, а затем подгружать кастомный.
Храните шрифты в src/assets/fonts/, чтобы они обрабатывались сборщиком и попадали в бандл.
Не кладите шрифты в public/, если только они не подключаются через CDN или не используются вне сборки (например, в email-шаблонах).
]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/шрифты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Шрифты.md</guid><pubDate>Fri, 17 Oct 2025 15:56:30 GMT</pubDate></item><item><title><![CDATA[SVG]]></title><description><![CDATA[SVG — масштабируемый векторный формат, особенно удобный в React благодаря двум способам импорта: как изображение и как React-компонент. Это даёт гибкость: можно либо просто вставить картинку, либо управлять её содержимым программно.Если вам нужно просто отобразить SVG-файл без изменения его содержимого:import logo from './logo.svg'; function App() { return &lt;img src={logo} alt="Логотип" /&gt;;
}
Сборщик обрабатывает файл как обычное изображение: копирует в папку сборки, добавляет хеш и возвращает путь. Такой подход подходит для сложных SVG или когда не требуется стилизация.Для простых иконок или логотипов, которые нужно стилизовать (менять цвет, размер, анимировать), используйте специальный синтаксис:import { ReactComponent as Logo } from './logo.svg'; function App() { return &lt;Logo fill="blue" width="100" height="40" /&gt;;
}
Здесь ReactComponent — это зарезервированное имя, распознаваемое сборщиком. В результате Logo становится полноценным React-компонентом, встроенным в JSX. Это позволяет:
Менять цвет через fill или stroke,
Управлять размерами через пропсы,
Применять CSS-классы или инлайновые стили,
Анимировать отдельные части через JavaScript. Как изображение: сложные SVG, внешние логотипы, когда не нужна интерактивность.
Как компонент: иконки, простые графические элементы, где важна гибкость стилей и интеграция с React-состоянием.
В большинстве современных шаблонов (Create React App, Vite с @vitejs/plugin-react) поддержка импорта SVG как компонента включена по умолчанию. Однако если вы настраиваете сборку вручную, потребуется соответствующий лоадер или плагин: Webpack: используется @svgr/webpack. В конфигурации нужно добавить правило:
{ test: /\.svg$/, use: ['@svgr/webpack', 'url-loader']
} Порядок важен: @svgr/webpack обрабатывает импорт с ReactComponent, а url-loader — обычные импорты. Vite: достаточно установить vite-plugin-svgr:
npm install -D vite-plugin-svgr И подключить в vite.config.js:
import svgr from 'vite-plugin-svgr'; export default { plugins: [svgr()]
}; После этого синтаксис import { ReactComponent as Icon } from './icon.svg' будет работать корректно. Без такой настройки попытка импорта как компонента вызовет ошибку: сборщик не распознает ReactComponent и вернёт только строку с путём.]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/svg.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/SVG.md</guid><pubDate>Fri, 17 Oct 2025 15:54:00 GMT</pubDate></item><item><title><![CDATA[Изображения]]></title><description><![CDATA[Изображения — один из самых частых типов ресурсов в веб-приложениях. В React-проектах, собранных с помощью Webpack или Vite, изображения (.png, .jpg, .jpeg, .gif, .webp) можно импортировать напрямую в компоненты. При импорте сборщик копирует файл в папку сборки, добавляет хеш к имени для эффективного кэширования и возвращает строку с корректным путём к изображению.import logo from './assets/logo.png'; function App() { return &lt;img src={logo} alt="Логотип" /&gt;;
}
Переменная logo содержит абсолютный путь к скомпилированному файлу (например, /static/media/logo.abcd1234.png). Этот путь безопасно использовать в атрибуте src.Запись вида &lt;img src="./assets/logo.png" /&gt; не работает в продакшене, потому что:
Сборщик не распознаёт строку как зависимость,
Файл не копируется в папку сборки,
В итоге браузер получает путь к несуществующему ресурсу.
Только импорт гарантирует, что изображение будет включено в бандл и доступно после сборки.
Храните изображения в папке src/assets/images/ или подобной — это упрощает навигацию и поддержку.
Используйте относительные пути при импорте (начинаются с ./ или ../).
Для иконок и простых графических элементов рассмотрите использование SVG как компонента — это даёт больше контроля над стилями.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/изображения.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Изображения.md</guid><pubDate>Fri, 17 Oct 2025 15:51:11 GMT</pubDate></item><item><title><![CDATA[Как React обрабатывает импорт файлов]]></title><description><![CDATA[React не работает напрямую с файлами — он делегирует эту задачу сборщику (Webpack или Vite). Когда вы пишете import logo from './assets/logo.png', сборщик копирует файл в папку сборки (dist/ или build/), переименовывает его, добавляя хеш для кэширования (например, logo.abcd1234.png), и возвращает в переменную logo строку с новым путём, например /static/media/logo.abcd1234.png. Этот путь — уже не относительная ссылка, а абсолютный URL к скомпилированному ресурсу. Именно поэтому использование строк напрямую в атрибутах, как &lt;img src="./assets/logo.png" /&gt;, приводит к проблемам: сборщик не распознаёт такие ссылки как зависимости, не включает файл в бандл, и в продакшене изображение просто не загружается.В режиме разработки многие файлы по относительным путям могут отображаться корректно благодаря встроенному серверу сборщика (Vite или Webpack Dev Server), который динамически разрешает статические ресурсы. Однако при сборке приложения (npm run build) сборщик включает в бандл только те файлы, которые явно импортированы в коде. Если вы используете строку напрямую в атрибуте, например &lt;img src="./logo.png" /&gt;, сборщик не распознаёт эту ссылку как зависимость и не копирует файл в папку сборки. В результате в продакшене изображение не загружается — оно «исчезает».Всегда импортируйте ресурсы, используемые в компонентах:import logo from './assets/logo.png';
// ...
&lt;img src={logo} alt="Логотип" /&gt;
Такой подход гарантирует, что сборщик:
увидит зависимость,
скопирует файл в папку сборки,
переименует его (обычно с хешем для кэширования),
подставит корректный путь в переменную logo.
Это не только предотвращает «исчезновение» файлов, но и обеспечивает контроль над используемыми ресурсами: неиспользуемые файлы не попадут в финальную сборку, что уменьшает её размер.Хеш в имени файла (например, logo.abcd1234.png) решает проблему кэширования в браузере. Когда файл попадает на сервер, браузер может сохранить его локально, чтобы не загружать повторно при следующем посещении. Если имя файла не меняется, браузер продолжит использовать старую версию даже после обновления контента на сервере. Сборщик генерирует хеш на основе содержимого файла: при любом изменении (даже одного пикселя) хеш меняется, и имя файла становится новым. Это заставляет браузер загрузить обновлённую версию, потому что путь теперь другой. Таким образом, хеширование обеспечивает:
долгосрочное кэширование (браузер кэширует файлы на годы, если имя не меняется),
мгновенное обновление при изменении контента (новое имя → новая загрузка).
]]></description><link>материалы/подтемы/секция-2.-react/тема-№14/как-react-обрабатывает-импорт-файлов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №14/Как React обрабатывает импорт файлов.md</guid><pubDate>Fri, 17 Oct 2025 15:47:57 GMT</pubDate></item><item><title><![CDATA[Тема №13. Основы React]]></title><description><![CDATA[В этой теме вы познакомитесь с библиотекой React — инструментом для создания пользовательских интерфейсов в веб-приложениях на JavaScript. Изучите ключевые концепции: компоненты, JSX и как создавать проекты React. Это фундамент для разработки интерфейсов в приложениях на React Native.
<a data-href="Что такое React" href="материалы/подтемы/секция-2.-react/тема-№13/что-такое-react.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое React</a>
<br><a data-href="JSX" href="материалы/подтемы/секция-2.-react/тема-№13/jsx.html" class="internal-link" target="_self" rel="noopener nofollow">JSX</a>
<br><a data-href="Компоненты" href="материалы/подтемы/секция-2.-react/тема-№13/компоненты.html" class="internal-link" target="_self" rel="noopener nofollow">Компоненты</a>
<br><a data-href="Создание и запуск React-проекта" href="материалы/подтемы/секция-2.-react/тема-№13/создание-и-запуск-react-проекта.html" class="internal-link" target="_self" rel="noopener nofollow">Создание и запуск React-проекта</a>
<br><a data-href="Типичная структура React-приложения" href="материалы/подтемы/секция-2.-react/тема-№13/типичная-структура-react-приложения.html" class="internal-link" target="_self" rel="noopener nofollow">Типичная структура React-приложения</a>
(пусто)<br><a data-href="Тема №14. Работа со стилями, изображениями и файлами в React" href="лекции/секция-2.-react/тема-№14.-работа-со-стилями,-изображениями-и-файлами-в-react.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №14. Работа со стилями, изображениями и файлами в React</a>]]></description><link>лекции/секция-2.-react/тема-№13.-основы-react.html</link><guid isPermaLink="false">Лекции/Секция 2. React/Тема №13. Основы React.md</guid><pubDate>Fri, 17 Oct 2025 15:37:28 GMT</pubDate></item><item><title><![CDATA[Cookies в React-приложениях]]></title><description><![CDATA[Cookies — это небольшие текстовые данные, хранящиеся в браузере и автоматически отправляемые на сервер с каждым HTTP-запросом к тому же домену. В React-приложениях они используются в первую очередь для аутентификации и сессионного управления, а не для хранения клиентского состояния.Когда сервер отвечает на запрос, он может установить cookie через заголовок Set-Cookie. Браузер сохраняет её и при последующих запросах к тому же домену автоматически добавляет в заголовок Cookie. Это позволяет серверу идентифицировать пользователя без передачи токена вручную.Пример:Set-Cookie: sessionId=abc123; Path=/; HttpOnly; Secure Размер: максимум 4 КБ на cookie.
Количество: обычно не более 50 cookies на домен.
Производительность: каждая cookie отправляется со всеми запросами к домену, даже для изображений или статики — это увеличивает объём трафика.
Доступ из JavaScript: если cookie помечена как HttpOnly, она недоступна через document.cookie — это мера защиты от XSS.
Чтение и запись через JavaScript возможна только для не-HttpOnly cookies:// Чтение
const cookies = document.cookie; // строка вида "key1=value1; key2=value2" // Запись
document.cookie = "theme=dark; path=/";
Однако синтаксис неудобен: нет встроенного парсера или метода удаления. В рамках курса мы не будем использовать сторонние библиотеки (например js-cookie), поэтому вот пример кастомного хука для удобной работы с cookies:function useCookie(key, defaultValue = '') { // Чтение при монтировании const [cookie, setCookie] = useState(() =&gt; { const match = document.cookie .split('; ') .find(row =&gt; row.startsWith(key + '=')); return match ? decodeURIComponent(match.split('=')[1]) : defaultValue; }); // Функция для записи const updateCookie = (value, days = 7) =&gt; { const expires = new Date(Date.now() + days * 864e5).toUTCString(); document.cookie = `${key}=${encodeURIComponent(value)}; expires=${expires}; path=/`; setCookie(value); }; // Функция для удаления const deleteCookie = () =&gt; { document.cookie = `${key}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/`; setCookie(defaultValue); }; return [cookie, updateCookie, deleteCookie];
}
Этот хук позволяет работать с cookie как с реактивным состоянием:const [theme, setTheme] = useCookie('theme', 'light');
// ...
setTheme('dark'); // сохранит в cookie и обновит состояние Аутентификация через сессии: сервер выдаёт сессионный ID, сохраняет его в HttpOnly cookie — клиент не видит токен, но запросы аутентифицируются автоматически.
Междоменные сценарии: если API и фронтенд на разных поддоменах, cookies с флагом Domain могут быть общими.
Совместимость с legacy-системами, где аутентификация завязана на cookies. Для хранения настроек UI, кэша или состояния приложения — используйте localStorage.
Для данных, не нужных серверу — зачем отправлять их с каждым запросом?
Для сложных структур — cookies работают только со строками и требуют ручной сериализации.
В большинстве современных React-приложений cookies используются только для аутентификации, управляемой сервером, а всё остальное хранится в localStorage или в состоянии приложения.]]></description><link>материалы/подтемы/секция-2.-react/тема-№15/cookies-в-react-приложениях.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №15/Cookies в React-приложениях.md</guid><pubDate>Fri, 17 Oct 2025 14:58:34 GMT</pubDate></item><item><title><![CDATA[localStorage и sessionStorage]]></title><description><![CDATA[localStorage и sessionStorage — это встроенные в браузер механизмы для хранения данных на стороне клиента. Оба предоставляют простой API для сохранения пар «ключ-значение», но отличаются по времени жизни и области видимости.localStorage сохраняет данные бессрочно — они остаются даже после закрытия браузера и перезагрузки компьютера. Это делает его идеальным для:
Сохранения пользовательских настроек (тема, язык, размер шрифта)
Кэширования данных API для ускорения загрузки
Хранения состояния форм между визитами
Основные методы:
localStorage.setItem(key, value) — сохраняет строку
localStorage.getItem(key) — возвращает строку или null
localStorage.removeItem(key) — удаляет запись
localStorage.clear() — очищает всё хранилище
Важно: localStorage хранит только строки. Для объектов и массивов используйте сериализацию:// Сохранение
localStorage.setItem('user', JSON.stringify({ name: 'Алиса' })); // Загрузка
const user = JSON.parse(localStorage.getItem('user') || '{}');
sessionStorage работает так же, как localStorage, но данные удаляются при закрытии вкладки (не браузера целиком). Это полезно для:
Восстановления формы после обновления страницы
Хранения временных данных, не нужных после ухода с сайта
API идентичен:sessionStorage.setItem('draft', text);
const draft = sessionStorage.getItem('draft');
Часто localStorage интегрируют с useState:function useLocalStorage(key, initialValue) { const [value, setValue] = useState(() =&gt; { const stored = localStorage.getItem(key); return stored ? JSON.parse(stored) : initialValue; }); useEffect(() =&gt; { localStorage.setItem(key, JSON.stringify(value)); }, [key, value]); return [value, setValue];
}
Такой кастомный хук позволяет работать с локальным хранилищем как с обычным состоянием.
Максимум ~5–10 МБ (зависит от браузера)
Доступ только в том же origin (протокол + домен + порт)
Не отправляются на сервер автоматически (в отличие от cookies)
Данные видны пользователю — никогда не храните секреты (пароли, токены доступа)
]]></description><link>материалы/подтемы/секция-2.-react/тема-№15/localstorage-и-sessionstorage.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №15/localStorage и sessionStorage.md</guid><pubDate>Fri, 17 Oct 2025 14:49:54 GMT</pubDate></item><item><title><![CDATA[Хранение данных между сессиями]]></title><description><![CDATA[Данные, хранящиеся в состоянии React-компонентов с помощью useState, теряются при перезагрузке страницы или перезапуске приложения. Чтобы сохранить информацию между сессиями — например, настройки пользователя, тему интерфейса или недозаполненную форму — необходимо использовать механизмы клиентского хранения данных.В вебе для этого доступны три основных инструмента:
<a data-href="localStorage и sessionStorage" href="материалы/подтемы/секция-2.-react/тема-№15/localstorage-и-sessionstorage.html" class="internal-link" target="_self" rel="noopener nofollow">localStorage и sessionStorage</a> <br><a data-href="Cookies в React-приложениях" href="материалы/подтемы/секция-2.-react/тема-№15/cookies-в-react-приложениях.html" class="internal-link" target="_self" rel="noopener nofollow">Cookies в React-приложениях</a>
Каждый из них имеет своё назначение, ограничения и сценарии применения.
localStorage — для всех клиентских данных, которые должны сохраняться между перезагрузками: настройки UI, кэш, offline-данные.
sessionStorage — для временных данных в рамках одной вкладки.
Cookies — только если сервер требует их для аутентификации или сессионного управления. Не используйте cookies для хранения сложных клиентских состояний.
]]></description><link>материалы/подтемы/секция-2.-react/тема-№15/хранение-данных-между-сессиями.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №15/Хранение данных между сессиями.md</guid><pubDate>Fri, 17 Oct 2025 14:48:22 GMT</pubDate></item><item><title><![CDATA[Передача данных через props]]></title><description><![CDATA[Передача данных через props — основной механизм обмена информацией между компонентами в React. Все данные передаются строго сверху вниз: от родительского компонента к дочернему. Это обеспечивает предсказуемость и упрощает отладку, так как источник данных всегда можно проследить по иерархии компонентов.Props (сокращение от «properties») — это аргументы, которые передаются в функциональный компонент, как параметры в обычную функцию. Они могут содержать любые типы данных: строки, числа, булевы значения, массивы, объекты, а также функции.В JSX props указываются как атрибуты:&lt;UserCard name="Алиса" age={30} /&gt;
Внутри компонента они доступны через параметр функции:function UserCard(props) { return &lt;div&gt;{props.name}, {props.age} лет&lt;/div&gt;;
}
Часто используется деструктуризация для удобства:function UserCard({ name, age }) { return &lt;div&gt;{name}, {age} лет&lt;/div&gt;;
}
Одна из ключевых практик — передача колбэков из родителя в дочерний компонент. Это позволяет дочернему компоненту запрашивать изменения состояния, не владея им напрямую.Пример:// Родитель
function App() { const [count, setCount] = useState(0); return &lt;CounterButton onIncrement={() =&gt; setCount(count + 1)} /&gt;;
} // Дочерний
function CounterButton({ onIncrement }) { return &lt;button onClick={onIncrement}&gt;+1&lt;/button&gt;;
}
Такой подход сохраняет единственный источник истины (single source of truth) и избегает прямого мутирования данных.Работа с props в React подчиняется строгим правилам, которые обеспечивают предсказуемость, читаемость и стабильность компонентного дерева. Эти правила — основа архитектуры React и помогают избежать распространённых ошибок.Дочерний компонент никогда не должен мутировать полученные props. Любая попытка присвоить значение напрямую (props.value = newValue) нарушает иммутабельность и может привести к неожиданному поведению. Если компоненту нужно «изменить» данные, он должен вызвать переданную функцию-колбэк, а не трогать props.Данные в React текут строго от родителя к дочернему компоненту. Нельзя «подтянуть» данные снизу вверх без явного механизма (например, колбэка). Это упрощает отладку: чтобы понять, откуда пришло значение, достаточно подняться по иерархии компонентов.Когда дочернему компоненту требуется инициировать изменение состояния, родитель должен передать функцию через props. Дочерний компонент вызывает её, но не управляет самим состоянием. Это сохраняет единый источник истины и изолирует логику управления данными.Передавайте только те данные, которые действительно нужны компоненту. Не передавайте весь объект состояния, если используется лишь одно поле. Это улучшает переиспользуемость, упрощает тестирование и снижает риск ненужных ререндеров.Чёткое определение ожидаемых props помогает другим разработчикам (и вам в будущем) понимать интерфейс компонента. В JavaScript это можно делать через JSDoc, в TypeScript — через интерфейсы или типы.]]></description><link>материалы/подтемы/секция-2.-react/тема-№15/передача-данных-через-props.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №15/Передача данных через props.md</guid><pubDate>Fri, 17 Oct 2025 14:43:28 GMT</pubDate></item><item><title><![CDATA[Передача функций как props]]></title><description><![CDATA[Передача функций через props — ключевой паттерн в React для обеспечения взаимодействия между компонентами при сохранении одностороннего потока данных. Поскольку дочерние компоненты не могут напрямую изменять состояние родителя, они вызывают переданные функции-колбэки, чтобы запросить изменение.Родительский компонент определяет функцию (обычно с использованием useState или других хуков) и передаёт её как prop:function Parent() { const [isVisible, setIsVisible] = useState(false); return ( &lt;TogglePanel onToggle={() =&gt; setIsVisible(!isVisible)} /&gt; );
}
Дочерний компонент получает эту функцию и вызывает её в ответ на событие:function TogglePanel({ onToggle }) { return &lt;button onClick={onToggle}&gt;Переключить&lt;/button&gt;;
}
Такой подход сохраняет единственный источник истины: состояние остаётся в том компоненте, которому оно принадлежит. Дочерний компонент лишь сигнализирует о намерении изменить данные, не зная и не контролируя их внутреннюю структуру. Это делает компоненты более переиспользуемыми и тестируемыми.Функции-props могут принимать аргументы, что особенно полезно в списках или формах:function TodoList({ todos, onDelete }) { return ( &lt;ul&gt; {todos.map(todo =&gt; ( &lt;li key={todo.id}&gt; {todo.text} &lt;button onClick={() =&gt; onDelete(todo.id)}&gt;Удалить&lt;/button&gt; &lt;/li&gt; ))} &lt;/ul&gt; );
} // В родителе
&lt;TodoList todos={todos} onDelete={(id) =&gt; setTodos(todos.filter(t =&gt; t.id !== id))} /&gt;
Здесь стрелочная функция () =&gt; onDelete(todo.id) оборачивает вызов, чтобы передать конкретный id.При каждом рендере родителя передаваемая функция создаётся заново, что может вызывать ненужные ререндеры дочерних компонентов. Для оптимизации используют useCallback:const handleToggle = useCallback(() =&gt; setIsVisible(v =&gt; !v), []);
return &lt;TogglePanel onToggle={handleToggle} /&gt;;
Это особенно актуально при использовании React.memo или в производительных сценариях.]]></description><link>материалы/подтемы/секция-2.-react/тема-№15/передача-функций-как-props.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №15/Передача функций как props.md</guid><pubDate>Fri, 17 Oct 2025 14:41:34 GMT</pubDate></item><item><title><![CDATA[Состояние и хук useState]]></title><description><![CDATA[Состояние в React — это данные, которые могут меняться со временем и напрямую влияют на то, как компонент отображается в интерфейсе. В отличие от обычных переменных, состояние «живёт» внутри компонента и сохраняется между рендерами. React отслеживает изменения состояния и автоматически обновляет DOM при его изменении, что лежит в основе интерактивности веб-приложений.Состояние позволяет компоненту реагировать на действия пользователя (например, клики, ввод текста), получать данные с сервера или изменять внешний вид в зависимости от условий. Без состояния компоненты были бы статичными — как обычный HTML.Важно помнить: состояние локально для конкретного компонента. Оно не сохраняется после перезагрузки страницы или перезапуска приложения — для долговременного хранения требуются дополнительные механизмы, такие как localStorage.Хук useState — основной способ добавления состояния в функциональные компоненты. Его синтаксис:const [state, setState] = useState(initialValue);
Здесь state — текущее значение состояния, а setState — функция для его обновления. Начальное значение (initialValue) может быть любого типа: строка, число, булево значение, массив, объект и даже null.Примеры инициализации:
useState(false) — для переключателей (например, темный режим)
useState('') — для текстовых полей
useState([]) — для списков
useState({ name: '', age: 0 }) — для объектов
Состояние в React обновляется только через функцию-сеттер (setState). Прямое присваивание (state = newValue) не сработает — React не узнает об изменении.Есть два способа обновления:
Прямое: setState(newValue) — когда новое значение не зависит от предыдущего.
Функциональное: setState(prev =&gt; prev + 1) — когда новое значение зависит от текущего. Это особенно важно при частых или асинхронных обновлениях.
React полагается на иммутабельность: вы не должны мутировать существующие объекты или массивы. Вместо этого создаёте новую копию с изменениями.Неправильно:user.name = 'Алиса';
setUser(user);
Правильно:setUser({ ...user, name: 'Алиса' });
Для массивов:setItems([...items, newItem]); // добавление
setItems(items.filter(item =&gt; item.id !== id)); // удаление
Это гарантирует, что React корректно определит, изменились ли данные, и выполнит повторный рендер.]]></description><link>материалы/подтемы/секция-2.-react/тема-№15/состояние-и-хук-usestate.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №15/Состояние и хук useState.md</guid><pubDate>Fri, 17 Oct 2025 14:34:50 GMT</pubDate></item><item><title><![CDATA[Типичная структура React-приложения]]></title><description><![CDATA[Структура React-приложения определяется инструментом сборки (например, Vite или Create React App), но вы можете организовать файлы как угодно. Однако со временем в сообществе сложились общепринятые практики, которые делают код читаемым, поддерживаемым и масштабируемым.Вот типичная структура всего проекта:my-app/
├── node_modules/ # Установленные зависимости (не редактируется вручную)
├── public/ # Статические файлы, которые копируются "как есть" в сборку
│ ├── index.html # Основной HTML-файл с контейнером для React (&lt;div id="root"&gt;)
│ ├── favicon.ico # Иконка вкладки браузера
│ └── ... # Другие файлы, доступные напрямую по пути (robots.txt, manifest.json и т.п.)
├── src/ # Исходный код приложения
│ ├── main.jsx # Точка входа: инициализация React и рендеринг корневого компонента
│ ├── App.jsx # Корневой компонент приложения
│ ├── components/ # Переиспользуемые UI-элементы: кнопки, карточки, инпуты
│ ├── pages/ # Крупные компоненты, представляющие отдельные экраны или разделы
│ ├── assets/ # Изображения, шрифты, иконки, используемые в компонентах
│ ├── styles/ # Глобальные CSS-файлы, переменные темы, общие стили
│ ├── hooks/ # Кастомные хуки (если используются)
│ └── utils/ # Вспомогательные функции: форматирование, валидация и т.п.
├── .gitignore # Файлы и папки, исключённые из системы контроля версий
├── package.json # Зависимости, скрипты запуска и метаданные проекта
├── vite.config.js # Конфигурация Vite (или webpack.config.js в CRA)
└── ... # Другие конфигурационные файлы (если есть)
Файлы из public/ не обрабатываются сборщиком. Они копируются в корень итоговой сборки без изменений. Например, public/favicon.ico будет доступен как /favicon.ico в браузере. Используйте эту папку только для файлов, которые должны сохранять точное имя и путь (например, манифест PWA или файлы для SEO).Вся логика приложения живёт в src/. Именно отсюда начинается сборка. Файлы вне src/ (кроме public/) обычно не участвуют в работе приложения напрямую.В React вы можете использовать два основных подхода к стилям:Хранятся в папке styles/ или подключаются напрямую в main.jsx или index.html. Они применяются ко всему приложению:/* src/styles/global.css */
body { margin: 0; font-family: sans-serif;
}
Такие стили полезны для сброса браузерных значений, настройки шрифтов или цветовой палитры.Часто каждый компонент имеет свой собственный CSS-файл, размещённый рядом с ним:components/
├── Button.jsx
└── Button.css
В компоненте стили импортируются как модуль:// Button.jsx
import './Button.css'; export function Button() { return &lt;button className="primary-button"&gt;Нажми&lt;/button&gt;;
}
Такой подход инкапсулирует стили внутри компонента, но классы всё ещё глобальны — если два компонента используют одинаковое имя класса, они могут конфликтовать.Чтобы избежать конфликтов имён, можно использовать CSS Modules. Для этого файл стилей называют с расширением .module.css:/* Button.module.css */
.btn { background: blue; color: white;
}
Импорт происходит как объект:// Button.jsx
import styles from './Button.module.css'; export function Button() { return &lt;button className={styles.btn}&gt;Нажми&lt;/button&gt;;
}
Сборщик автоматически генерирует уникальные имена классов (например, Button_btn__abc123), гарантируя изоляцию стилей.Чёткое разделение упрощает:
Поиск нужного файла.
Понимание ответственности каждой части кода.
Добавление новых экранов или компонентов без хаоса.
Совместную работу в команде.
Даже в небольших проектах полезно сразу придерживаться этой структуры — это экономит время при масштабировании.]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/типичная-структура-react-приложения.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/Типичная структура React-приложения.md</guid><pubDate>Fri, 17 Oct 2025 14:17:39 GMT</pubDate></item><item><title><![CDATA[Vite]]></title><description><![CDATA[Vite — это современный инструмент сборки, созданный Эваном Ю (автором Vue.js), который использует нативные ES-модули браузера для обеспечения мгновенного старта сервера разработки. Он стал популярной альтернативой Create React App благодаря скорости и простоте.Чтобы создать React-проект с Vite, выполните:npm create vite@latest my-app -- --template react
Эта команда:
Запрашивает имя проекта и шаблон.
Создаёт папку my-app с минимальной структурой.
Устанавливает зависимости для React и Vite.
Перейдите в папку проекта и запустите сервер:cd my-app
npm install
npm run dev
Приложение откроется по адресу, например, http://localhost:5173. Сервер запускается почти мгновенно, даже в крупных проектах.
Использует нативные ES-модули: не собирает весь проект при старте, а подгружает файлы по запросу.
Поддерживает горячую замену модулей (HMR) на уровне отдельных компонентов — изменения отображаются быстрее.
Включает встроенную поддержку TypeScript, JSX, CSS-модулей и PostCSS без дополнительной настройки.
Производит лёгкую и быструю production-сборку с помощью Rollup. Значительно быстрее запускается и перезагружается.
Меньше зависимостей и «мёртвого» кода в проекте.
Проще кастомизировать конфигурацию через файл vite.config.js.
Активно развивается и поддерживает современные веб-стандарты.
Vite подходит как для обучения, так и для коммерческой разработки, особенно когда важна скорость и гибкость.
В рамках этого курса - для выполнения заданий мы будем использовать Vite
]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/vite.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/Vite.md</guid><pubDate>Fri, 17 Oct 2025 14:09:57 GMT</pubDate></item><item><title><![CDATA[Create React App (CRA)]]></title><description><![CDATA[Create React App (CRA) — это официальный инструмент от команды React для быстрого старта проекта без необходимости настраивать сборку вручную. Он скрывает всю конфигурацию Webpack, Babel и других инструментов «под капотом», позволяя сразу писать код.Чтобы создать проект с помощью CRA, выполните в терминале:npx create-react-app my-app
Эта команда:
Скачивает необходимые зависимости.
Создаёт структуру проекта в папке my-app.
Настраивает скрипты для запуска, сборки и тестирования.
После создания перейдите в папку проекта и запустите сервер разработки:cd my-app
npm start
Браузер автоматически откроет приложение по адресу http://localhost:3000.
Всё настроено «из коробки»: поддержка JSX, импорт CSS, обработка изображений, линтер.
Подходит для обучения и небольших проектов.
Не требует знания Webpack или Babel. Большая и медленная сборка при росте проекта.
Сложно кастомизировать конфигурацию без «eject» (однократной команды, которая раскрывает всю конфигурацию, но делает её необратимой).
Медленный старт dev-сервера по сравнению с современными альтернативами.
CRA долгое время был стандартом, но сегодня многие разработчики выбирают более быстрые и гибкие инструменты, такие как Vite.]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/create-react-app-(cra).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/Create React App (CRA).md</guid><pubDate>Fri, 17 Oct 2025 14:07:12 GMT</pubDate></item><item><title><![CDATA[Создание и запуск React-проекта]]></title><description><![CDATA[Чтобы начать разработку на React, нужно создать проект с помощью инструмента сборки. Современные React-приложения не запускаются напрямую в браузере — они требуют транспиляции (например, преобразования JSX в обычный JavaScript), сборки модулей и запуска локального сервера для разработки.Существует несколько способов создать такой проект. Наиболее популярные — Create React App (CRA) и Vite. Оба автоматически настраивают окружение, но отличаются подходом, скоростью и гибкостью.Независимо от выбранного инструмента, после создания проекта вы получаете:
Локальный сервер разработки с поддержкой горячей перезагрузки (изменения в коде мгновенно отображаются в браузере без полной перезагрузки страницы).
Автоматическую транспиляцию JSX и современного JavaScript.
Готовую конфигурацию для запуска, сборки и тестирования. Убедитесь, что установлен Node.js (версия 18 или выше рекомендуется).
Выберите инструмент: CRA или Vite.
Выполните команду создания проекта в терминале.
Перейдите в папку проекта и запустите dev-сервер.
Детали по каждому инструменту вынесены в отдельные подстраницы.<a data-href="Create React App (CRA)" href="материалы/подтемы/секция-2.-react/тема-№13/create-react-app-(cra).html" class="internal-link" target="_self" rel="noopener nofollow">Create React App (CRA)</a><br>
<a data-href="Vite" href="материалы/подтемы/секция-2.-react/тема-№13/vite.html" class="internal-link" target="_self" rel="noopener nofollow">Vite</a>]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/создание-и-запуск-react-проекта.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/Создание и запуск React-проекта.md</guid><pubDate>Fri, 17 Oct 2025 14:06:23 GMT</pubDate></item><item><title><![CDATA[Компоненты]]></title><description><![CDATA[Компонент в React — это самостоятельная, переиспользуемая часть пользовательского интерфейса. Он инкапсулирует свою разметку (через JSX), логику и стили, и может использоваться как отдельный элемент в других частях приложения.Самый простой способ создать компонент — объявить функцию. Такие компоненты называются функциональными:function Button() { return &lt;button&gt;Нажми меня&lt;/button&gt;;
}
Функция-компонент должна возвращать JSX. Этот JSX описывает, что будет отображаться в DOM. Возвращаемое значение может быть одним элементом, фрагментом (&lt;&gt;...&lt;/&gt;) или даже null, если компонент ничего не должен рендерить.Имена компонентов всегда начинаются с заглавной буквы. Это правило позволяет React отличать пользовательские компоненты от встроенных HTML-тегов. Например:
&lt;div /&gt; — это HTML-элемент.
&lt;Button /&gt; — это компонент.
Если назвать компонент с маленькой буквы (button), React обработает его как обычный DOM-тег, и код не сработает как ожидается.Компоненты можно вкладывать друг в друга, создавая сложные интерфейсы из простых частей:function App() { return ( &lt;div&gt; &lt;Header /&gt; &lt;MainContent /&gt; &lt;Footer /&gt; &lt;/div&gt; );
}
Каждый из этих компонентов (Header, MainContent, Footer) может быть определён отдельно и использован в других местах.Разбиение интерфейса на мелкие компоненты упрощает разработку, тестирование и поддержку кода. Вместо одного большого файла с тысячей строк вы работаете с множеством маленьких, понятных и независимых блоков.]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/компоненты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/Компоненты.md</guid><pubDate>Fri, 17 Oct 2025 14:04:40 GMT</pubDate></item><item><title><![CDATA[JSX]]></title><description><![CDATA[JSX — это синтаксическое расширение JavaScript, которое позволяет писать HTML-подобный код внутри JavaScript-файлов. Оно используется в React для описания того, как должен выглядеть интерфейс.Хотя JSX выглядит как HTML, на самом деле это синтаксический сахар. Под капотом каждый JSX-элемент преобразуется в вызов функции React.createElement(). Например, запись:const element = &lt;h1&gt;Привет, мир!&lt;/h1&gt;;
на этапе сборки превращается в:const element = React.createElement('h1', null, 'Привет, мир!');
Это позволяет React эффективно создавать и управлять элементами интерфейса.Компонент должен возвращать один корневой элемент. Если нужно вернуть несколько соседних элементов, их следует обернуть в общий тег (например, &lt;div&gt;) или использовать фрагмент:// С фрагментом (рекомендуется, если не нужен лишний div)
return ( &lt;&gt; &lt;h1&gt;Заголовок&lt;/h1&gt; &lt;p&gt;Текст&lt;/p&gt; &lt;/&gt;
);
Чтобы вставить значение переменной или результат выражения в JSX, используйте фигурные скобки {}:function Welcome({ name }) { const isLoggedIn = true; return ( &lt;div&gt; &lt;h1&gt;Привет, {name}!&lt;/h1&gt; {isLoggedIn &amp;&amp; &lt;p&gt;Вы вошли в систему.&lt;/p&gt;} &lt;/div&gt; );
}
Внутри {} можно использовать любые JavaScript-выражения: переменные, вызовы функций, тернарные операторы. Но нельзя использовать if или for напрямую — для этого нужно выносить логику за пределы JSX.JSX не является обязательным для использования React, но он значительно упрощает чтение и написание компонентов, делая структуру интерфейса визуально похожей на HTML.]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/jsx.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/JSX.md</guid><pubDate>Fri, 17 Oct 2025 14:04:29 GMT</pubDate></item><item><title><![CDATA[Что такое React]]></title><description><![CDATA[React — это библиотека с открытым исходным кодом, созданная компанией Meta (ранее Facebook), для построения пользовательских интерфейсов. Она позволяет разбивать интерфейс на независимые, переиспользуемые части — компоненты — и управлять ими с помощью JavaScript.Основная цель React — сделать разработку UI предсказуемой и эффективной. Вместо того чтобы вручную обновлять DOM при каждом изменении данных, вы описываете, как должен выглядеть интерфейс в зависимости от текущего состояния. React сам определяет, какие части DOM нужно обновить, и делает это минимально необходимым способом.В традиционном императивном подходе (например, с чистым DOM API) вы пишете шаги: «найди элемент», «измени его текст», «добавь класс». В React вы говорите: «вот как должен выглядеть интерфейс при таких данных». Это упрощает рассуждение о коде и снижает количество ошибок.Каждый компонент в React — это изолированная единица интерфейса со своей логикой и внешним видом. Например, кнопка, карточка товара или целая форма могут быть компонентами. Их можно использовать многократно в разных частях приложения, передавая разные данные через пропсы.React использует виртуальный DOM — легковесную копию реального DOM в памяти. При изменении состояния React сначала обновляет виртуальный DOM, сравнивает его с предыдущей версией (процесс называется reconciliation), а затем применяет только те изменения, которые действительно нужны в браузере. Это делает обновления быстрыми и плавными.React не управляет состоянием приложения целиком (в отличие от фреймворков вроде Angular или Vue). Он фокусируется исключительно на слое представления (view layer), что делает его гибким и легко интегрируемым с другими инструментами.]]></description><link>материалы/подтемы/секция-2.-react/тема-№13/что-такое-react.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 2. React/Тема №13/Что такое React.md</guid><pubDate>Fri, 17 Oct 2025 14:02:09 GMT</pubDate></item><item><title><![CDATA[Pasted image 20240923235323]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20240923235323.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20240923235323.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20240923235323.png</guid><pubDate>Tue, 14 Oct 2025 09:42:58 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250912212732]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912212732.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912212732.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912212732.png</guid><pubDate>Tue, 14 Oct 2025 09:40:18 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250912205946]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912205946.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912205946.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912205946.png</guid><pubDate>Tue, 14 Oct 2025 09:40:17 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20240928222139]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20240928222139.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20240928222139.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20240928222139.png</guid><pubDate>Tue, 14 Oct 2025 09:40:10 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250912214624]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912214624.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912214624.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912214624.png</guid><pubDate>Tue, 14 Oct 2025 09:39:58 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[qrcod_72k5]]></title><description><![CDATA[<img src="материалы/файлы/qrcod_72k5.png" target="_self">]]></description><link>материалы/файлы/qrcod_72k5.html</link><guid isPermaLink="false">Материалы/Файлы/qrcod_72k5.png</guid><pubDate>Tue, 14 Oct 2025 09:39:51 GMT</pubDate><enclosure url="материалы/файлы/qrcod_72k5.png" length="0" type="image/png"/><content:encoded>&lt;figure&gt;&lt;img src="материалы/файлы/qrcod_72k5.png"&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250912214643]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912214643.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912214643.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912214643.png</guid><pubDate>Tue, 14 Oct 2025 09:39:49 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250917202240]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250917202240.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250917202240.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250917202240.png</guid><pubDate>Tue, 14 Oct 2025 09:39:46 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20240928221620]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20240928221620.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20240928221620.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20240928221620.png</guid><pubDate>Tue, 14 Oct 2025 09:39:46 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250912214611]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912214611.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912214611.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912214611.png</guid><pubDate>Tue, 14 Oct 2025 09:39:45 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Примитивные типы данных JavaScript]]></title><description><![CDATA[Примитивные типы данных — это базовые, неструктурированные значения в JavaScript, которые не содержат свойств или методов сами по себе и не могут быть изменены после создания. Главная особенность примитивов — они передаются по значению: при присваивании или передаче в функцию копируется само значение, а не ссылка на него. Это означает, что если вы присвоите примитивную переменную другой переменной и измените одну из них — другая останется неизменной. Примитивы также не имеют внутреннего состояния — их нельзя расширить, добавить свойства или переопределить. Они являются фундаментом для всех операций в JavaScript и лежат в основе хранения и обработки любых данных — от чисел в расчётах до текста в интерфейсе мобильного приложения.В JavaScript все числа — это числа с плавающей запятой по стандарту IEEE 754. Это значит, что даже целые числа хранятся как дробные, и из-за особенностей двоичного представления могут возникать небольшие погрешности при вычислениях (например, 0.1 + 0.2 !== 0.3). JavaScript не разделяет целые и вещественные числа — всё объединено в один тип number. Поддерживаются положительные, отрицательные, ноль, а также специальные значения Infinity, -Infinity и NaN (Not a Number).Строка в JavaScript — это последовательность символов, заключённая в одинарные ('), двойные (") или обратные кавычки (`). Обратные кавычки позволяют использовать шаблонные строки — вставлять переменные через ${} и писать многострочный текст без экранирования. Например: `Привет, ${name}!`. Строки неизменяемы — любое изменение создаёт новую строку, а не модифицирует существующую.Логический тип представляет два возможных значения: true и false. Используется для условий, сравнений, флагов состояний (например, загружено ли приложение, авторизован ли пользователь). В JavaScript есть понятие «ложных» и «истинных» значений — например, 0, "", null, undefined воспринимаются как false в булевом контексте, но сами по себе они не являются boolean.null — это специальное значение, которое программист присваивает намеренно, чтобы указать: «здесь ничего нет». Это не ошибка и не неопределённость — это осознанное обозначение отсутствия данных. Например, если пользователь не выбрал аватар, можно установить avatarUrl: null. Несмотря на поведение typeof null === 'object' (историческая ошибка языка), null — это примитив.undefined означает, что переменная была объявлена, но ей ещё не присвоено значение. Это автоматическое состояние, которое присваивается переменной при объявлении через let или const без инициализации. Также возвращается, если функция не возвращает значение, или свойство объекта не существует. Отличие от null: undefined — это результат отсутствия действия, а null — результат преднамеренного действия.<img alt="Pasted image 20240923235323.png" src="материалы/файлы/pasted-image-20240923235323.png" target="_self">Symbol — это новый примитивный тип, появившийся в ES6, предназначенный для создания уникальных ключей свойств объектов. Каждый символ, созданный через Symbol(), гарантированно уникален, даже если у них одинаковое описание. Используется редко в базовой разработке, но важен для внутренней работы библиотек и предотвращения коллизий имён свойств. Не нужно запоминать детали — достаточно знать, что он существует и используется для скрытия и защиты ключей.bigint — это тип для работы с целыми числами, превышающими предел Number.MAX_SAFE_INTEGER (около 9 квадриллионов). Чтобы создать bigint, нужно добавить букву n в конец числа: 123456789012345678901234567890n. Он нужен для точных расчётов — например, при работе с финансовыми данными, хешами, криптографией или большими идентификаторами. С bigint нельзя выполнять операции с обычными числами — требуется явное приведение.Оператор typeof в JavaScript используется для определения типа значения на момент выполнения. Он возвращает строку с названием типа данных. Это важный инструмент для отладки, валидации входных данных и безопасной работы с переменными, особенно когда тип неизвестен заранее — например, при получении данных из API или пользовательского ввода.typeof 42; // "number"
typeof 3.14; // "number"
typeof -0; // "number"
typeof Infinity; // "number"
typeof NaN; // "number" typeof "Привет"; // "string"
typeof ''; // "string"
typeof `Шаблон ${1 + 2}`; // "string" typeof true; // "boolean"
typeof false; // "boolean" typeof null; // "object" — историческая ошибка языка typeof undefined; // "undefined" typeof Symbol('id'); // "symbol" typeof 12345678901234567890n; // "bigint" typeof function() {}; // "function" typeof {}; // "object"
typeof []; // "object" — массивы тоже объекты typeof null возвращает "object" — это известная ошибка в спецификации JavaScript, которая осталась ради совместимости.
typeof всегда возвращает строку, даже если значение не существует (например, typeof undeclaredVariable вернёт "undefined" без ошибки).
Для проверки массивов или объектов typeof недостаточен — лучше использовать Array.isArray() или instanceof.
При работе с JSON-ответами API часто приходят данные неизвестного типа. Например, поле userId может быть числом или строкой. Перед использованием его стоит проверить:if (typeof userId === 'string') { // обработать как строку
} else if (typeof userId === 'number') { // обработать как число
}
Преобразование типов — это процесс изменения значения одного типа данных в другой. В JavaScript, как в языке с динамической типизацией, это происходит постоянно — иногда намеренно, а иногда автоматически, что может приводить к неожиданным результатам. Различают два вида преобразований: явное (когда разработчик сам управляет процессом) и неявное (когда язык делает это автоматически на основе контекста).Явное преобразование — это когда разработчик сознательно и намеренно превращает значение из одного типа в другой с помощью специальных функций или операторов. Это безопасный и предсказуемый способ, который рекомендуется использовать в production-коде.// Число → строка
String(42); // "42"
(42).toString(); // "42"
42 + ""; // "42" — это уже неявное, но можно использовать и явно // Строка → число
Number("123"); // 123
Number("3.14"); // 3.14
Number("abc"); // NaN — некорректная строка
parseInt("42px"); // 42 — преобразует до первого нецифрового символа
parseFloat("3.14abc"); // 3.14 // Строка → булево
Boolean("hello"); // true
Boolean(""); // false — пустая строка — ложь
Boolean("0"); // true — любая непустая строка — истина, даже "false" // Число → булево
Boolean(0); // false
Boolean(-1); // true
Boolean(1); // true
Boolean(NaN); // false
Boolean(Infinity); // true // Любое значение → булево через двойное отрицание
!!"text"; // true
!!0; // false
!!null; // false // Объект → строка
String({}); // "[object Object]"
JSON.stringify({}); // "{}" — для структурированного представления При получении данных из формы (input.value всегда строка).
При работе с API, где типы могут быть неточными.
При необходимости гарантировать поведение — например, чтобы +"5" не вызывало путаницы.
В тестах и валидации входных данных. ✅ Правило: Если вы не уверены в типе — приведите его явно. Это делает код понятнее и надёжнее.
Неявное преобразование — это когда JavaScript автоматически меняет тип значения, чтобы выполнить операцию. Оно происходит при использовании операторов +, -, *, /, ==, if(), while() и других в контекстах, требующих другого типа. Это мощный механизм, но он часто вызывает ошибки у новичков, потому что поведение не всегда очевидно.Если хотя бы один операнд — строка, то оба приводятся к строке:"5" + 3; // "53" — строка + число → конкатенация
5 + "3"; // "53"
"Привет" + 123; // "Привет123"
true + "!" // "true!"
Если оба операнда — числа — выполняется математическое сложение:5 + 3; // 8
0.1 + 0.2; // 0.30000000000000004 — особенность IEEE 754
Математическое сложение так-же происходит если среди операндов нет строк, в таком случае операнды преобразуются в числа:5 + true; // 6 = 5 + 1
false + Infinity; // Infinity - что тоже является числом // 0 + бесконечность
Эти операторы всегда пытаются привести операнды к числам:"5" - "3"; // 2 — строки превратились в числа
"10" * "2"; // 20
"15" / "3"; // 5
"abc" - 1; // NaN — нельзя преобразовать "abc" в число
true - 1; // 0 — true → 1
false * 5; // 0 — false → 0
Оператор == выполняет неявное приведение типов перед сравнением — это главный источник ошибок:"" == 0; // true — пустая строка → 0
"0" == 0; // true — "0" → 0
false == 0; // true — false → 0
null == undefined;// true — особое правило: они равны друг другу
0 == false; // true — false → 0
"1" == true; // true — "1" → 1, true → 1
[] == 0; // true — пустой массив → "" → 0
[1] == 1; // true — [1] → "1" → 1
[1,2] == "1,2"; // true — массив → строка "1,2"
{} == "[object Object]"; // false — объекты сравниваются по ссылке, но при приведении к строке — да, но тут логика сложнее ⚠️ Важно: null == undefined — единственное исключение, где два разных примитива считаются равными.
Любое значение приводится к булевому типу:if ("0") { console.log("Это правда!"); } // сработает — непустая строка → true
if (0) { console.log("Не сработает"); } // не сработает — 0 → false
if ([]) { console.log("Это правда!"); } // сработает — массив → true
if ({}) { console.log("Это правда!"); } // сработает — объект → true
if (null) { console.log("Не сработает"); } // не сработает — null → false
if (undefined) { console.log("Не сработает"); } // не сработает 📌 Эти 6 значений называются falsy — всё остальное — truthy.
// Начинающий разработчик ожидает:
"5" == 5; // true — логично?
"5" === 5; // false — теперь понятно! // А вот так:
[] == ![]; // true — почему?
// Разбор:
// ![] → false (пустой массив → true → отрицание → false)
// [] == false → "" == false → 0 == 0 → true // Или:
" \t\n" == 0; // true — строка с пробелами → пустая после trim → 0
Такие случаи ведут к багам, которые сложно отследить. Особенно в мобильных приложениях, где данные приходят из сети и могут быть неожиданного типа.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№4/примитивные-типы-данных-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №4/Примитивные типы данных JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:42 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Основные платформы мобильных приложений]]></title><description><![CDATA[Платформа мобильных приложений — это совокупность программного обеспечения, инструментов, стандартов и правил, которые определяют, как создаются, устанавливаются и работают мобильные приложения на конкретном устройстве. Это не просто операционная система (ОС), а целая экосистема: от ядра ОС и API-интерфейсов до магазинов приложений, систем подписок, политик безопасности и требований к разработчикам. Выбор платформы напрямую влияет на: доступные функции устройства (камера, GPS, биометрия); способы взаимодействия с пользователем; методы тестирования и отладки; стратегию монетизации и распространения; сроки и стоимость разработки. На сегодняшний день подавляющее большинство мобильных приложений создаётся для двух основных платформ — iOS и Android. Их доминирование обусловлено масштабами рынка, зрелостью инструментов и поддержкой со стороны крупнейших технологических компаний.iOS — экосистема Apple, работающая на устройствах iPhone, iPad и iPod touch. Закрытая, строго контролируемая платформа с единым стандартом качества, высокой безопасностью и стабильной производительностью. Основная аудитория — пользователи в развитых странах, с высоким уровнем дохода и лояльностью к бренду.Android — открытая операционная система от Google, используемая сотнями производителей (Samsung, Xiaomi, OnePlus, Motorola и др.). Обладает огромной фрагментацией устройств и версий, но обеспечивает максимальную доступность и гибкость для разработчиков и пользователей. Доминирует в развивающихся рынках и по объёму установленных устройств — более 70% глобального рынка смартфонов.Но, помимо iOS и Android, на протяжении истории мобильных технологий существовали и другие платформы, которые либо имели значительную долю рынка, либо обладали высоким потенциалом, но в итоге уступили место доминирующим системам.Windows Phone (Microsoft) — запущенная в 2010 году платформа, основанная на ядре Windows NT, предлагала уникальный пользовательский интерфейс с динамическими «живыми» плитками. Несмотря на техническую изящность и глубокую интеграцию с экосистемой Microsoft (Outlook, Office, OneDrive), она не смогла привлечь достаточное количество разработчиков. Отсутствие приложений, особенно популярных сервисов вроде Instagram или WhatsApp на ранних этапах, стало фатальным. Microsoft официально прекратила поддержку Windows Phone в 2017 году.BlackBerry OS / BlackBerry 10 — до середины 2000-х годов BlackBerry была синонимом корпоративной мобильности благодаря надёжной безопасности, физической клавиатуре и собственной сети Push Mail. Однако компания не сумела адекватно ответить на рост сенсорных экранов и экосистемы приложений. Попытка перезапуска с BlackBerry 10 в 2013 году, основанной на QNX, оказалась слишком поздней — к тому времени пользователи уже массово перешли на iOS и Android. В 2016 году BlackBerry перестала производить собственные устройства.Symbian — когда-то самая популярная мобильная ОС, особенно в Европе и Азии, Symbian использовалась Nokia, Samsung, Siemens и другими. Она доминировала на рынке до 2007 года, но её архитектура, унаследованная от эпохи кнопочных телефонов, не позволила эффективно адаптироваться к новым требованиям тачскринов и мультимедиа. После выхода iPhone и Android, Nokia в 2011 году перешла на Windows Phone, а Symbian была официально закрыта в 2014 году.WebOS (Palm, затем HP) — оригинальная и продвинутая система с многооконным интерфейсом, предшественник современных концепций многозадачности. Palm выпустила первые устройства на WebOS в 2009 году, а HP попыталась развивать платформу дальше, даже выпустив планшет TouchPad. Но недостаток приложений, маркетинговой поддержки и внутренние конфликты в HP привели к отказу от WebOS в 2011 году. Позже HP передала код проекта LG, который использовал его для своих смарт-телевизоров — но как мобильная ОС WebOS так и не возродилась.HarmonyOS (Huawei) — современный пример платформы, появившейся как ответ на геополитические ограничения. Разработанная Huawei в 2019 году после запрета Google на использование GMS (Google Mobile Services), HarmonyOS изначально позиционировалась как универсальная ОС для IoT-устройств, а позже — как замена Android на смартфонах. Хотя она технически совместима с Android-приложениями через App Pack, её глобальное распространение ограничено из-за отсутствия доступа к ключевым сервисам Google и западным приложениям. На сегодня — это важный региональный игрок (особенно в Китае), но не глобальная альтернатива iOS/Android.iOS и Android — две доминирующие мобильные платформы, отличающиеся не только архитектурой, но и философией разработки, подходом к безопасности, экосистеме и взаимодействию с пользователем. Их сравнение позволяет понять фундаментальные различия, которые влияют на процесс создания мобильных приложений.Языки программирования и инструменты разработки
iOS-приложения разрабатываются преимущественно на языке Swift (с 2014 года), а также на Objective-C — унаследованном от эпохи NeXTSTEP. Интегрированная среда разработки — Xcode, доступная исключительно на macOS. Это накладывает ограничения: разработка под iOS невозможна без устройства Apple или виртуальной машины с macOS.
Android-приложения пишутся на Kotlin (рекомендуемый язык с 2019 года) или Java (традиционный, но постепенно вытесняемый). Среда разработки — Android Studio, основанная на IntelliJ IDEA, работает на Windows, macOS и Linux, что обеспечивает большую доступность для разработчиков.Архитектура и управление ресурсами
iOS использует закрытую, унифицированную архитектуру: ограниченное количество моделей устройств с жёстко контролируемыми характеристиками (память, процессор, экран). Это позволяет оптимизировать приложения под конкретные аппаратные конфигурации, обеспечивая высокую производительность и стабильность.
Android, напротив, работает на тысячах устройств с разными процессорами, объёмами ОЗУ, плотностями пикселей и версиями ОС. Разработчику приходится учитывать фрагментацию — от старых смартфонов с Android 8 до новых с Android 14 — и применять адаптивные интерфейсы, проверять совместимость и использовать библиотеки поддержки (Android Support Library / AndroidX).Магазины приложений и политики распространения
Приложения для iOS распространяются исключительно через App Store — строго централизованный и контролируемый канал. Apple проводит ручную модерацию каждого приложения, требует соблюдения строгих гайдлайнов по дизайну, приватности и функциональности. Это повышает уровень безопасности для пользователей, но замедляет выпуск обновлений и ограничивает возможности монетизации (например, запрещены сторонние магазины и системы внутренних покупок вне App Store).
Android-приложения могут распространяться через Google Play, но также допускается установка из сторонних источников (APK-файлы). Google Play имеет автоматизированную модерацию, менее строгие требования, но более высокий риск распространения вредоносного ПО. Это делает Android более открытой, но требует от разработчика дополнительных мер по защите приложения и информированию пользователей о безопасности.Доля рынка и целевая аудитория
По количеству установленных устройств Android доминирует — около 70–75% глобального рынка смартфонов, особенно в Азии, Африке и Латинской Америке. При этом iOS занимает около 25–30%, но сосредоточена в странах с высоким уровнем дохода — США, Западная Европа, Япония, Австралия.
Это создаёт принципиально разные экономические модели: приложения для iOS чаще генерируют больше дохода на одного пользователя (высокий ARPU — Average Revenue Per User), тогда как Android обеспечивает больший охват аудитории, но с меньшей monetization. Для бизнес-приложений это означает выбор между качеством и количеством.Обновления и жизненный цикл устройств
Apple контролирует полный цикл — от железа до ПО — и обеспечивает массовые обновления ОС для устройств, выпущенных до 5–6 лет назад. Более 90% активных устройств iOS работают на последних двух версиях ОС.
Android-устройства получают обновления неравномерно: производители (Samsung, Xiaomi и др.) сами решают, какие модели поддерживают, а многие бюджетные устройства остаются на устаревших версиях (Android 8–10) годами. Это вынуждает разработчиков поддерживать совместимость с множеством версий API, увеличивая сложность тестирования и развертывания.Безопасность и приватность
iOS позиционируется как более безопасная платформа благодаря изолированной среде выполнения приложений (sandboxing), строгому контролю доступа к данным (персональные файлы, камера, микрофон), шифрованию данных на уровне ОС и обязательному использованию App Transport Security.
Android предоставляет аналогичные механизмы, но их реализация зависит от производителя. Многие OEM-производители добавляют собственные сервисы, фоновые процессы и права, которые могут компрометировать приватность. Кроме того, открытость Android делает его более уязвимым к вредоносным APK-файлам, загружаемым вне Google Play.Интеграция с экосистемой
iOS тесно интегрирован с другими продуктами Apple: iCloud, AirDrop, Handoff, Continuity, Apple Watch, HomeKit. Это позволяет создавать кросс-устройственные приложения с единым пользовательским опытом.
Android интегрируется с сервисами Google: Gmail, Google Maps, Drive, Firebase, Google Assistant, Wear OS. Эти сервисы предоставляют мощные инструменты для разработчиков — особенно для аналитики (Firebase), push-уведомлений, облачного хранения и машинного обучения. Однако интеграция с другими устройствами (TV, часы, авто) менее унифицирована, чем в Apple.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№1/основные-платформы-мобильных-приложений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №1/Основные платформы мобильных приложений.md</guid><pubDate>Tue, 14 Oct 2025 09:39:40 GMT</pubDate></item><item><title><![CDATA[Основные понятия веб страницы]]></title><description><![CDATA[Основные понятия веб-страницыВеб-страница — это документ, отображаемый в браузере, который состоит из трёх взаимосвязанных технологий: HTML, CSS и JavaScript. Каждая из них выполняет свою уникальную роль, и только их совместное использование позволяет создавать полноценные, интерактивные и визуально привлекательные приложения.HTML (HyperText Markup Language) — это язык гипертекстовой разметки, созданный для описания структуры веб-документов. Он не выполняет вычислений, не обрабатывает логику и не управляет поведением — его задача: обозначить смысл содержимого. Каждый элемент HTML — это маркер, который говорит браузеру: «Это заголовок», «Это абзац», «Это ссылка», «Это изображение».HTML работает на основе тегов — специальных ключевых слов, заключённых в угловые скобки: &lt;tag&gt;. Теги могут быть:
Парными — имеют открывающий и закрывающий тег: &lt;p&gt;Это параграф&lt;/p&gt; Самозакрывающимися — не содержат содержимого и закрываются сразу: &lt;img src="image.jpg" alt="Описание изображения" /&gt;
&lt;br /&gt; Каждый тег может иметь атрибуты — дополнительные параметры, уточняющие поведение или свойства элемента. Например:&lt;a href="https://example.com" target="_blank"&gt;Перейти&lt;/a&gt;
Здесь href указывает адрес ссылки, а target="_blank" — открывать её в новой вкладке.HTML5 — современная версия стандарта — ввела семантические теги, которые не только описывают внешний вид, но и передают значение контента:
&lt;header&gt; — шапка страницы или раздела
&lt;nav&gt; — навигационное меню
&lt;main&gt; — основное содержимое страницы
&lt;section&gt; — логический блок тематически связанного контента
&lt;article&gt; — самостоятельная сущность (например, статья, пост)
&lt;footer&gt; — подвал
Использование семантики улучшает:
Доступность — для пользователей с ограниченными возможностями (экранная речь корректно интерпретирует структуру),
SEO — поисковые системы лучше понимают и ранжируют содержимое,
Поддержку кода — разработчики быстрее ориентируются в структуре.
CSS (Cascading Style Sheets) — это язык, предназначенный для оформления HTML-документов. Он отвечает за то, как выглядит страница: цвета, размеры, расположение элементов, анимации, адаптивность под разные устройства.CSS работает через селекторы — правила, определяющие, к каким элементам применяются стили. Пример:h1 { color: #2c3e50; font-size: 2rem; text-align: center;
}
Здесь h1 — селектор, { ... } — набор свойств и их значений.CSS обладает ключевыми особенностями:
Каскадность (Cascading) — стили могут переопределяться. Если два правила влияют на один элемент, приоритет определяется по специфичности селектора, порядку объявления и использованию !important.
Наследование — некоторые свойства (например, font-family, color) автоматически передаются дочерним элементам.
Медиа-запросы — позволяют применять стили в зависимости от характеристик устройства: ширины экрана, ориентации, разрешения. Это основа адаптивного дизайна:
@media (max-width: 768px) { body { font-size: 14px; }
} CSS можно подключать тремя способами:
Внутренний стиль — внутри &lt;style&gt; в &lt;head&gt; (не рекомендуется для больших проектов).
Внешний файл — через &lt;link rel="stylesheet" href="styles.css"&gt; — лучшая практика.
Встроенный стиль — атрибут style внутри тега (&lt;p style="color:red;"&gt;) — используется крайне редко, только для экстренных случаев.
Важно: HTML отвечает за что — CSS — за как выглядит. Их разделение — фундаментальный принцип веб-разработки. Это позволяет:
Менять дизайн без трогания структуры,
Одинаковый HTML отображать по-разному на разных устройствах,
Ускорять загрузку за счёт кэширования CSS-файлов,
Облегчать командную разработку (дизайнеры работают с CSS, разработчики — с HTML и JS). В рамках дисциплины мы не будем изучать свойства CSS, поэтому они остаются на самообучение
Каждый валидный HTML-документ должен начинаться с DOCTYPE, чтобы браузер знал, какой стандарт использовать. Без него он может перейти в режим "quirks mode", где поведение становится непредсказуемым.&lt;!DOCTYPE html&gt;
— единственное объявление, необходимое для HTML5. Не требует закрывающего тега.Корневой элемент. Атрибут lang обязателен для доступности и SEO:&lt;html lang="ru"&gt;
Указывает язык содержимого — помогает экранной речи, переводчикам и поисковикам.Не отображается на странице, но содержит метаданные, необходимые для работы браузера и поисковых систем:
&lt;meta charset="UTF-8"&gt; — задаёт кодировку символов. UTF-8 поддерживает все языки мира — обязательный элемент.
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; — критически важен для мобильных устройств. Без него страница будет масштабироваться как на десктопе, что делает её нечитаемой на телефоне.
&lt;title&gt; — название вкладки браузера и заголовок в результатах поиска. Должен быть уникальным и описательным.
&lt;link&gt; — подключение внешних ресурсов: CSS, favicon, шрифтов.
&lt;script&gt; — подключение JavaScript (может находиться и в &lt;head&gt;, и в &lt;body&gt;, но это отдельная тема).
Пример полного &lt;head&gt;:&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; &lt;title&gt;Моя первая страница&lt;/title&gt; &lt;link rel="stylesheet" href="styles.css"&gt; &lt;link rel="icon" href="favicon.ico" type="image/x-icon"&gt;
&lt;/head&gt;
Содержит всё, что видит пользователь. Внутри могут быть любые элементы, включая:
Заголовки: &lt;h1&gt; до &lt;h6&gt; — иерархия важности. &lt;h1&gt; — главный заголовок страницы, только один.
Параграфы: &lt;p&gt; — для текстовых блоков.
Списки: &lt;ul&gt; — неупорядоченный (с точками),
&lt;ol&gt; — упорядоченный (с номерами),
&lt;li&gt; — элемент списка. Изображения: &lt;img src="..." alt="..."&gt; — alt обязателен для доступности и SEO.
Ссылки: &lt;a href="..."&gt;текст&lt;/a&gt; — href — адрес перехода.
Кнопки: &lt;button&gt;...&lt;/button&gt; — для взаимодействия.
Формы: &lt;form&gt;, &lt;input&gt;, &lt;label&gt; — для сбора данных.
Пример минимальной, но корректной структуры &lt;body&gt;:&lt;body&gt; &lt;header&gt; &lt;h1&gt;Добро пожаловать!&lt;/h1&gt; &lt;/header&gt; &lt;main&gt; &lt;p&gt;Это основной текст страницы.&lt;/p&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;/main&gt; &lt;footer&gt; &lt;p&gt;&amp;copy; 2025 Моя компания&lt;/p&gt; &lt;/footer&gt;
&lt;/body&gt;
HTML — дерево. Элементы должны быть правильно вложены:
✅ Правильно:&lt;p&gt;&lt;strong&gt;Жирный текст&lt;/strong&gt; внутри параграфа&lt;/p&gt;
❌ Неправильно:&lt;p&gt;&lt;strong&gt;Жирный текст&lt;/p&gt;&lt;/strong&gt; &lt;!-- Нарушена вложенность --&gt;
Браузеры пытаются исправить ошибки, но это приводит к непредсказуемому поведению, особенно в сложных случаях.
Используйте семантические теги вместо &lt;div&gt; там, где это возможно.
Не используйте &lt;h1&gt;–&lt;h6&gt; исключительно для изменения размера шрифта — используйте CSS.
Все изображения должны иметь alt — даже если пустой (alt=""), если они декоративные.
Для кнопок и ссылок используйте правильные теги: &lt;button&gt; — для действий, &lt;a&gt; — для переходов.
Поддерживайте чистую и читаемую структуру: отступы, переносы, комментарии (если нужно).
Всегда проверяйте валидность кода через <a data-tooltip-position="top" aria-label="https://validator.w3.org/" rel="noopener nofollow" class="external-link is-unresolved" href="https://validator.w3.org/" target="_self">validator.w3.org</a>.
DOM (Document Object Model — Модель объектов документа) — это программное представление веб-документа (обычно HTML или XML), созданное браузером в виде иерархического дерева объектов, где каждый элемент документа — это объект, доступный для манипуляций через JavaScript.DOM не является частью самого HTML-файла. Он динамически генерируется браузером при загрузке страницы: парсер читает HTML-код и превращает его в структуру из узлов (nodes), которые можно изменять, добавлять, удалять или запрашивать с помощью JavaScript.Каждый элемент HTML становится узлом (node) в DOM-дереве:
Элементные узлы — теги (&lt;div&gt;, &lt;p&gt;, &lt;button&gt; и т.д.)
Текстовые узлы — текст внутри тегов
Атрибутные узлы — атрибуты элементов (id, class, href)
Корневой узел — &lt;html&gt;
Дочерние и родительские узлы — элементы связаны отношениями «родитель–ребёнок»
Пример HTML:&lt;div id="container"&gt; &lt;h1&gt;Привет, мир!&lt;/h1&gt; &lt;p&gt;Это параграф.&lt;/p&gt;
&lt;/div&gt;
Соответствующее DOM-дерево:html
└── body └── div#container ├── h1 │ └── #text: "Привет, мир!" └── p └── #text: "Это параграф."
Каждый узел имеет свойства и методы, позволяющие взаимодействовать с ним. Например:
element.tagName — имя тега,
element.textContent — содержимое текста,
element.id, element.className — значения атрибутов,
element.appendChild(), element.removeChild() — управление дочерними узлами.
JavaScript не может напрямую работать с HTML-кодом файла. Он работает только с DOM-представлением, которое браузер создал в памяти. Это позволяет:
Динамически изменять содержимое страницы без перезагрузки (например, обновлять список задач, менять текст кнопки),
Реагировать на действия пользователя — клики, ввод текста, скроллинг,
Изменять стили элементов — через element.style,
Добавлять и удалять элементы — например, создавать новые карточки товаров по запросу,
Получать информацию о состоянии страницы — размер окна, положение элементов, состояние форм.
Без DOM JavaScript был бы бесполезен на веб-странице — он просто не имел бы «точки входа» в контент.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№3/основные-понятия-веб-страницы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №3/Основные понятия веб страницы.md</guid><pubDate>Tue, 14 Oct 2025 09:39:37 GMT</pubDate></item><item><title><![CDATA[Основные типы мобильных приложений]]></title><description><![CDATA[Мобильное приложение — это не просто программа, запущенная на смартфоне. Его тип определяется тем, как оно создано, на чём работает и как взаимодействует с операционной системой и аппаратными компонентами устройства. Выбор типа приложения влияет на производительность, сроки разработки, стоимость поддержки и качество пользовательского опыта. Существует четыре основных типа: нативные, веб-приложения, гибридные и кроссплатформенные.Нативные приложения — это программы, разработанные специально для одной конкретной платформы с использованием официальных языков программирования, SDK и инструментов, предоставленных её создателем.Для iOS приложения пишутся на Swift или Objective-C с использованием фреймворков UIKit и SwiftUI, собираются в Xcode и компилируются напрямую в машинный код для архитектуры ARM процессоров Apple.
Для Android — на Kotlin или Java с использованием Android SDK, сборка происходит через Android Studio в APK или AAB-файлы, которые затем интерпретируются Android Runtime (ART).Преимущества: Максимальная производительность — код выполняется напрямую на устройстве без промежуточных слоёв. Полный доступ ко всем API устройства: камера, GPS, Bluetooth, сенсоры, биометрия, уведомления, фоновые задачи. Соответствие стандартам платформы (Human Interface Guidelines для iOS, Material Design для Android) — обеспечивает интуитивный и «родной» пользовательский опыт. Лучшая стабильность и поддержка обновлений ОС — разработчики получают ранний доступ к новым функциям через beta-версии SDK.
Ограничения: Требуется отдельная команда разработчиков для каждой платформы — удвоение затрат на разработку и тестирование. Дублирование логики и дизайна между версиями — увеличивает время выхода на рынок. Высокая зависимость от экосистемы: обновление API может потребовать переписывания значительной части кода.
Области применения:
Нативные приложения — стандарт для проектов, где важны скорость, надёжность и глубокая интеграция с устройством: банковские и финансовые приложения, игры, AR/VR-решения, медицинские системы, приложения с реальным временем (например, такси, доставка), корпоративные инструменты с высокими требованиями к безопасности.Веб-приложения — это сайты, спроектированные так, чтобы вести себя как мобильные приложения. Они работают в браузере, но могут быть добавлены на домашний экран, работать оффлайн и отправлять уведомления благодаря технологиям PWA.Основаны на стандартных веб-технологиях: HTML5, CSS3, JavaScript, а также Service Workers (для кэширования и работы без интернета), Web App Manifest (для определения иконки, имени, цвета темы) и Push API.Преимущества: Одна кодовая база — работает на всех устройствах с браузером (iOS, Android, даже десктоп). Нет необходимости проходить модерацию в магазинах приложений — публикация мгновенная. Низкие затраты на разработку и обслуживание. Не требует установки — пользователь сразу переходит по ссылке. Автоматическое обновление — изменения видны сразу после релиза.
Ограничения: Ограниченный доступ к аппаратным возможностям устройства: нет прямого доступа к контактам, файловой системе, Bluetooth Low Energy, NFC, гироскопу в некоторых случаях. Невозможность использовать многие нативные UI-компоненты — интерфейс выглядит как сайт, а не как приложение. Зависимость от браузера: производительность и совместимость различаются между Safari, Chrome, Firefox. Отсутствие в App Store и Google Play — потеря видимости, возможности рейтингов, рекомендаций и внутренних покупок через официальные каналы.
Области применения:
PWA подходят для контентных сервисов, информационных сайтов, электронной коммерции с простой логикой, корпоративных порталов, приложений с низким уровнем взаимодействия: онлайн-газеты, каталоги товаров, формы обратной связи, калькуляторы, лендинги. Особенно эффективны там, где важна скорость распространения и минимальные затраты — например, маркетинговые кампании или временные акции.Гибридные приложения — это веб-приложения, обёрнутые в «оболочку» нативного контейнера (WebView), который позволяет им запускаться как обычные мобильные приложения из магазинов. Они используют веб-технологии (HTML/CSS/JS), но имеют доступ к нативным API через плагины.Популярные фреймворки: Apache Cordova (ранее PhoneGap) и Ionic (основан на Angular/React/Vue + Cordova).Преимущества: Одна кодовая база для iOS и Android — снижение затрат на разработку. Возможность публикации в App Store и Google Play — как нативные приложения. Быстрая разработка для команд с опытом в вебе. Поддержка большинства базовых функций: камера, геолокация, уведомления, файловая система — через плагины.
Ограничения: Производительность ниже, чем у нативных — все операции проходят через WebView, что создаёт задержки, особенно при анимациях и сложной графике. Плагины часто устаревают или плохо документированы — могут вызывать баги на новых версиях ОС. UX редко достигает уровня «родного» приложения — интерфейс чувствуется как «веб-страница в обёртке». Ограниченный доступ к современным нативным функциям (например, Face ID, ARKit, Android Jetpack Compose).
Области применения:
Гибридные приложения подходят для прототипирования, MVP-проектов, внутренних корпоративных инструментов, приложений с простой логикой и минимальным взаимодействием с оборудованием: учётные системы, формы регистрации, CRM-клиенты, базовые лояльностные программы. Идеальны, когда бюджет ограничен, а сроки — жёсткие, и требуется быстрый выход на два рынка.Кроссплатформенные приложения — это приложения, написанные на одном языке и фреймворке, которые компилируются в нативный код для разных платформ. Это не обёртки, а генерация нативных компонентов на основе единого исходного кода.Популярные фреймворки: Flutter (Dart, от Google), React Native (JavaScript/TypeScript, от Meta), Xamarin (C#, от Microsoft), Kivy (Python, редко используется в коммерческой разработке).Отличие от гибридных: вместо WebView они используют настоящие нативные UI-компоненты (например, Flutter рисует собственные виджеты, React Native вызывает native UI элементы iOS/Android напрямую).Преимущества: Одна кодовая база — до 80–95% общего кода между iOS и Android. Производительность близка к нативной — особенно в Flutter и React Native с правильной оптимизацией. Доступ к большинству нативных API через библиотеки (например, Firebase, Mapbox, camera plugin). Современный UI — возможность создавать уникальный дизайн, не привязанный к стандартам платформы. Активное сообщество, регулярные обновления, хорошая документация.
Ограничения: Некоторые функции требуют написания нативного кода (Java/Kotlin, Swift/Objective-C) — если нужна глубокая интеграция с OS. Размер приложения больше, чем у чисто нативного (особенно в Flutter — включает движок рендеринга). Возможны баги на границах платформ — поведение одного и того же компонента может отличаться на iOS и Android. Обучение новому языку (Dart, TypeScript) требует времени для команд, привыкших к Java/Kotlin или Swift.
Области применения:
Кроссплатформенные решения — выбор большинства стартапов, компаний с ограниченным бюджетом, но амбициозными целями. Подходят для социальных сетей, мессенджеров, e-commerce, финтех-приложений, образовательных платформ, приложений с частыми обновлениями и необходимостью быстро масштабироваться. Примеры: Facebook, Instagram (частично), Uber Eats, Alibaba, Tencent.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№1/основные-типы-мобильных-приложений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №1/Основные типы мобильных приложений.md</guid><pubDate>Tue, 14 Oct 2025 09:39:37 GMT</pubDate></item><item><title><![CDATA[Основные технологии для разработки мобильных приложений]]></title><description><![CDATA[Нативная разработка предполагает использование официальных языков программирования, сред разработки и фреймворков, предоставляемых производителями платформ — Apple и Google. Приложения компилируются напрямую в машинный код, обеспечивающий максимальную производительность и полный доступ к API устройства.Для разработки приложений под iOS используется Swift — язык, созданный Apple в 2014 году как современная замена Objective-C. Swift отличается чистым синтаксисом, безопасностью типов, поддержкой функционального программирования и высокой скоростью выполнения. Он активно развивается и является стандартом для новых проектов.Вместо него до сих пор встречается Objective-C — унаследованный от NeXTSTEP язык, который использовался в iOS до появления Swift. Он остаётся актуальным при поддержке старых проектов, но новые разработчики начинают с Swift.Инструмент разработки — Xcode, единственный официально поддерживаемый IDE от Apple. Он включает в себя редактор кода, симулятор устройств, инструменты отладки, профилирования производительности и систему управления версиями (Git). Xcode работает только на macOS, что делает разработку под iOS невозможной на Windows или Linux без виртуализации.Фреймворки интерфейса:
UIKit — традиционный фреймворк для создания пользовательских интерфейсов. Работает на основе иерархии представлений (UIView), требует детального описания макетов через код или Interface Builder. Подходит для сложных, детально настраиваемых интерфейсов.
SwiftUI — декларативный фреймворк, представленный в 2019 году. Позволяет описывать интерфейс как функцию состояния приложения — «что должно отображаться при данном состоянии», а не «как его построить». Упрощает разработку, обеспечивает автоматическую адаптацию под все размеры экранов и темы (светлая/тёмная), и полностью интегрирован с Swift. Считается будущим iOS-разработки.
Обе технологии работают с экосистемой Apple: Core Animation, Core Location, ARKit, HealthKit, Face ID, Push Notifications — всё доступно через единые API, документированные и стабильно поддерживающиеся Apple.Основным языком для Android сегодня является Kotlin — язык, разработанный JetBrains и официально объявленный Google предпочтительным для Android-разработки с 2019 года. Kotlin сочетает в себе функциональные и объектно-ориентированные парадигмы, обладает более безопасной системой типов (отсутствие null-pointer исключений по умолчанию), сжатым синтаксисом и полной совместимостью с Java.Java остаётся актуальной благодаря огромной базе legacy-приложений и корпоративных систем. Многие библиотеки, туториалы и инструкции всё ещё написаны на Java, но новые проекты рекомендуют начинать с Kotlin.Среда разработки — Android Studio, основанная на IntelliJ IDEA. Она предоставляет полноценный набор инструментов: эмулятор устройств, профайлер памяти и сети, анализатор производительности, инструменты для тестирования и поддержку Firebase. Работает на Windows, macOS и Linux — обеспечивает большую доступность, чем Xcode.Фреймворки интерфейса:
XML-разметка + View-система — классический подход. Интерфейс описывается в XML-файлах, а логика — в Kotlin/Java-классах. Требует явного связывания элементов UI с кодом (findViewById()), что создаёт больше шаблонного кода и потенциальных ошибок.
Jetpack Compose — современный декларативный фреймворк, аналог SwiftUI. Позволяет описывать интерфейс как функцию состояния, используя только Kotlin. Компоненты (Composables) перерисовываются автоматически при изменении данных. Упрощает создание динамических интерфейсов, снижает количество кода и повышает читаемость. С 2023 года считается основным стандартом для новых проектов.
Android также предлагает богатую экосистему Jetpack — набор библиотек (ViewModel, Room, Navigation, DataStore, WorkManager и др.), которые решают типовые задачи: управление жизненным циклом, работа с базами данных, фоновые задачи, маршрутизация между экранами — всё стандартизировано и поддерживается Google.Кроссплатформенные технологии позволяют писать один код, который компилируется в нативные приложения для iOS и Android. Отличие от гибридных — отсутствие WebView: вместо веб-страницы приложение использует настоящие нативные компоненты или собственные рендереры, что обеспечивает близкую к нативной производительность.Разработан Google и представлен в 2017 году. Основан на языке Dart — объектно-ориентированном языке с быстрой компиляцией и поддержкой JIT/AOT (Just-in-Time / Ahead-of-Time). Flutter компилирует код напрямую в нативный ARM-код, минуя виртуальную машину.Ключевая особенность — декларативная widget-архитектура. Весь интерфейс строится из деревьев виджетов — каждый элемент (кнопка, текст, список) — это виджет, который может быть изменён, вложен или переиспользован. Даже отступы и цвета — это виджеты.Flutter не использует нативные UI-компоненты iOS или Android. Вместо этого он рендерит собственные элементы с помощью графического движка Skia — то же, что используется в Chrome и Android. Это даёт:
Единый дизайн на всех платформах — приложение выглядит одинаково на iPhone и Samsung.
Высокую производительность — 60–120 FPS даже на сложных анимациях.
Гибкость дизайна — можно создавать уникальные интерфейсы, не привязанные к Material Design или Human Interface Guidelines.
Ограничения: больший размер приложения (включает рендер-движок), ограниченная интеграция с некоторыми нативными API без написания плагинов на Swift/Kotlin, менее «родной» UX на iOS, если не следовать гайдлайнам вручную.Flutter идеален для проектов с акцентом на дизайн: продукты с уникальной визуальной идентичностью, маркетплейсы, сервисы с частыми анимациями, MVP-стартапы, где важна скорость выхода на два рынка.Разработан Meta (ранее Facebook) в 2015 году. Основан на JavaScript и TypeScript — языках, уже знакомых миллионам веб-разработчиков. React Native использует принцип React — компонентный подход, где интерфейс строится из повторно используемых компонентов, реагирующих на изменения состояния.Архитектура React Native основана на JS-бриджe: JavaScript-код выполняется в отдельном потоке, а вызовы к нативным компонентам (кнопки, списки, камера) передаются через мост. Это позволяет использовать настоящие нативные UI-элементы, но создаёт задержки при частых взаимодействиях между JS и нативным кодом.Преимущества:
Высокая скорость разработки для команд с опытом в вебе.
Большое сообщество и множество готовых библиотек (npm).
Возможность частичного перехода: можно внедрять React Native-экраны в существующее нативное приложение.
Поддержка горячей перезагрузки (Hot Reload) — изменения видны мгновенно.
Ограничения:
Производительность ниже, чем у Flutter или нативных приложений — особенно при сложной анимации или работе с большим количеством данных.
Зависимость от сторонних библиотек для доступа к API — многие требуют установки и настройки нативных модулей (Native Modules).
Разница в поведении между iOS и Android — некоторые компоненты могут работать по-разному, требуя платформо-специфичного кода.
Сложность отладки: ошибки могут возникать как в JS, так и в нативном коде, затрудняя диагностику.
React Native популярен в компаниях, где есть команда веб-разработчиков, нуждающаяся в выходе на мобильный рынок без полного переобучения. Примеры: Facebook, Instagram, Skype, Walmart, Tesla.Разработан Microsoft, ранее известный как Xamarin Forms. Использует язык C# и фреймворк .NET — популярный в корпоративной разработке. В 2022 году Xamarin был объединён с .NET Multi-platform App UI (.NET MAUI) — современной версией, поддерживающей не только iOS и Android, но и Windows, macOS.Отличие от React Native и Flutter: Xamarin/.NET MAUI не использует мост. Код компилируется напрямую в нативный код через Mono или .NET runtime, что обеспечивает лучшую производительность и меньшие накладные расходы.Плюсы:
Полный доступ к нативным API через привязки (bindings) — почти все функции устройства доступны «из коробки».
Единая кодовая база для мобильных и десктопных приложений.
Интеграция с Visual Studio и Azure — удобна для корпоративных проектов.
Сильная типизация и безопасность C#.
Минусы:
Меньшее сообщество по сравнению с Flutter и React Native.
Более сложная настройка, особенно для новичков.
Менее гибкий UI — интерфейс часто выглядит «по-Windows», если не применять платформо-специфичные стили.
Медленнее развитие экосистемы по сравнению с Google и Meta.
.NET MAUI подходит для enterprise-решений: внутренние корпоративные приложения, ERP-системы, CRM, медицинские терминалы, приложения с интеграцией в облачные сервисы Microsoft (Azure, Office 365).]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№1/основные-технологии-для-разработки-мобильных-приложений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №1/Основные технологии для разработки мобильных приложений.md</guid><pubDate>Tue, 14 Oct 2025 09:39:36 GMT</pubDate></item><item><title><![CDATA[Создание своей HTML страницы]]></title><description><![CDATA[Чтобы создать HTML-страницу, достаточно использовать любой текстовый редактор — даже Блокнот. Однако для эффективной разработки рекомендуется использовать современный редактор кода, такой как Visual Studio Code (VS Code).HTML-страница — это текстовый файл с расширением .html. Минимальная структура HTML-документа выглядит так:&lt;!DOCTYPE html&gt;
&lt;html lang="ru"&gt;
&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;title&gt;Моя первая страница&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Привет, мир!&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
Сохраните этот код в файл с именем, например, index.html. Откройте его в браузере — вы увидите заголовок «Привет, мир!». Это и есть ваша первая веб-страница.<a data-href="Как создавать файлы с определённым расширением" href="материалы/как-сделать/как-создавать-файлы-с-определённым-расширением.html" class="internal-link" target="_self" rel="noopener nofollow">Как создавать файлы с определённым расширением</a>JavaScript можно подключать к HTML-странице двумя основными способами: встроенно (внутри HTML-файла) или через внешний файл. Второй способ — единственно правильный для профессиональной разработки.JavaScript можно вставить прямо внутрь HTML-документа с помощью тега &lt;script&gt;:&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;title&gt;Страница с встроенным JS&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Привет!&lt;/h1&gt; &lt;script&gt; alert("Это встроенный JavaScript!"); document.write("&lt;p&gt;Текст добавлен скриптом.&lt;/p&gt;"); &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Почему это не рекомендуется:
Нарушает принцип разделения ответственности: структура (HTML), стиль (CSS) и логика (JS) должны быть разделены.
Сложно поддерживать и масштабировать код — особенно при росте проекта.
Затрудняется повторное использование кода между страницами.
Ухудшается читаемость и тестирование.
Может замедлять загрузку страницы, если скрипт большой.
Используйте этот способ только для быстрых экспериментов, демонстраций или очень простых примеров.Правильный и стандартный способ — создать отдельный файл с расширением .js и подключить его к HTML:
Создайте файл script.js в той же папке, что и index.html.
Напишите в нём JavaScript-код:
// script.js
alert("Это внешний JavaScript-файл!");
document.querySelector('h1').style.color = 'blue'; Подключите его в HTML перед закрывающим тегом &lt;/body&gt;:
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;title&gt;Страница с внешним JS&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Привет!&lt;/h1&gt; &lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Преимущества:
Чистый, организованный код.
Возможность переиспользования одного файла на нескольких страницах.
Упрощённая отладка и версионный контроль (Git).
Лучшая производительность — браузер может кэшировать внешние скрипты.
JavaScript следует подключать в самом конце тела HTML-документа, перед закрывающим тегом &lt;/body&gt;.Когда браузер встречает тег &lt;script&gt; во время парсинга HTML, он приостанавливает загрузку и разбор DOM-дерева, чтобы загрузить и выполнить скрипт. Если скрипт подключен в &lt;head&gt; или в начале &lt;body&gt;, а он пытается взаимодействовать с элементами, которые ещё не загружены — возникнет ошибка:&lt;head&gt; &lt;script src="script.js"&gt;&lt;/script&gt; &lt;!-- ❌ Опасно! --&gt;
&lt;/head&gt;
&lt;body&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt;
&lt;/body&gt;
Если в script.js написано:document.getElementById('myButton').addEventListener('click', () =&gt; { alert('Клик!');
});
— то скрипт выполнится до того, как кнопка появится в DOM, и getElementById вернёт null. Результат — ошибка в консоли.&lt;body&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;script src="script.js"&gt;&lt;/script&gt; &lt;!-- ✅ Безопасно: DOM уже построен --&gt;
&lt;/body&gt;
Теперь браузер сначала полностью загрузит и отрисует все элементы страницы, а только потом выполнит скрипт — и все запросы к DOM будут успешными.
Быстрая отрисовка контента: пользователь видит страницу быстрее, без задержек из-за загрузки скриптов.
Предсказуемое поведение: код работает только тогда, когда всё, к чему он обращается, уже существует.
Совместимость с современными практиками: так делают все крупные фреймворки и библиотеки. Если скрипт не зависит от DOM (например, модуль аналитики, который запускается сразу при загрузке страницы), его можно размещать в &lt;head&gt;.
Использование атрибута defer (в &lt;head&gt;) позволяет отложить выполнение скрипта до завершения парсинга HTML — это альтернатива размещению в конце, но требует понимания нюансов.
&lt;head&gt; &lt;script src="script.js" defer&gt;&lt;/script&gt; &lt;!-- ✅ Альтернатива, если нужно в head --&gt;
&lt;/head&gt; ✅ Рекомендация: Всегда подключайте JavaScript-файлы перед закрывающим тегом &lt;/body&gt;, если только вы точно не знаете, что делаете и почему используете defer или async. Это — базовое правило надёжной и предсказуемой работы JavaScript на веб-странице.
Чтобы реагировать на действия пользователя (например, нажатие кнопки), можно назначить обработчик события двумя способами: через атрибуты HTML или через JavaScript. Второй способ — единственный корректный для профессиональной разработки.Можно напрямую вписать JavaScript-код в атрибут onclick элемента:&lt;button onclick="alert('Кнопка нажата!')"&gt;Нажми меня&lt;/button&gt;
Или вызвать функцию:&lt;script&gt;
function handleClick() { alert('Функция вызвана через атрибут!');
}
&lt;/script&gt; &lt;button onclick="handleClick()"&gt;Нажми меня&lt;/button&gt;
Почему это не рекомендуется:
Смешивание ответственности: логика (JS) и структура (HTML) сливаются — нарушает принцип разделения.
Сложность поддержки: сложно отлаживать, тестировать и рефакторить код, особенно при росте проекта.
Уязвимость к ошибкам: если имя функции опечатано — ошибка не будет заметна до момента клика.
Не масштабируемо: невозможно динамически добавлять/удалять обработчики, работать с несколькими элементами, использовать замыкания.
Проблемы с безопасностью: в некоторых контекстах (CSP) использование onclick может быть заблокировано. ⚠️ Используйте этот способ только для быстрых экспериментов или учебных примеров — никогда в продакшене.
Правильный и стандартный способ — назначать обработчики событий из JavaScript, после того как DOM загружен:&lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;script src="script.js"&gt;&lt;/script&gt;
// script.js
const button = document.getElementById('myButton'); button.addEventListener('click', function() { alert('Кнопка нажата через addEventListener!');
});
Преимущества:
Полное разделение логики и разметки.
Возможность назначать несколько обработчиков на один элемент.
Легко удалять обработчики через removeEventListener.
Поддержка современных возможностей JS: стрелочные функции, async/await, замыкания.
Удобно работать с динамически создаваемыми элементами.
Совместимость с системами сборки, тестирования и фреймворками.
Дополнительно — лучшая практика:document.addEventListener('DOMContentLoaded', () =&gt; { const button = document.getElementById('myButton'); if (button) { button.addEventListener('click', () =&gt; { console.log('Клик обработан надёжно'); }); }
});
Это гарантирует, что скрипт выполнится только после полной загрузки DOM, даже если он подключён в &lt;head&gt;.Представим, что у нас есть кнопка в HTML:&lt;button id="myButton"&gt;Нажми меня&lt;/button&gt;
Мы хотим, чтобы при нажатии на неё в консоль браузера выводилось сообщение: "Кнопка была нажата!"
Убедитесь, что у вас есть файл script.js, и он подключен в конце &lt;body&gt;:&lt;body&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
В script.js напишите:const button = document.getElementById('myButton');
Эта строка говорит браузеру:
👉 «Найди элемент на странице, у которого атрибут id="myButton"» — и сохрани его в переменную button.Теперь добавьте эту строку:button.addEventListener('click', () =&gt; { console.log('Кнопка была нажата!');
});
Что здесь происходит (без функций):
addEventListener — это встроенная команда, которая привязывает действие к элементу.
'click' — это тип события, которое мы хотим отслеживать (нажатие).
() — это просто способ сказать: «здесь будет код, который выполнится при событии».
console.log(...) — это команда, которая выводит текст в окно разработчика (не на экран). ✅ Всё, что внутри { } — это просто набор команд, которые должны сработать, когда пользователь кликнет.
Когда пользователь кликает по кнопке — в консоли браузера появляется сообщение: Кнопка была нажата!
Этот шаблон — основа всего дальнейшего взаимодействия с пользователем. Его нужно запомнить как фиксированную формулу:
элемент.addEventListener('событие', () =&gt; { ... });
И заменять:
элемент — на нужный вам (button, input, div и т.д.)
'событие' — на нужное (click, mouseover, keydown и т.д.)
{ ... } — на то, что вы хотите сделать (вывести сообщение, изменить цвет, отправить данные)
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№3/создание-своей-html-страницы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №3/Создание своей HTML страницы.md</guid><pubDate>Tue, 14 Oct 2025 09:39:36 GMT</pubDate></item><item><title><![CDATA[Переменные в JavaScript]]></title><description><![CDATA[Переменная в JavaScript — это именованный контейнер для хранения данных, который позволяет обращаться к значению по его имени в процессе выполнения программы.Каждая переменная ассоциирована с определённым значением (число, строка, объект, функция и т.д.), которое может меняться во время работы приложения. Переменные позволяют сохранять промежуточные результаты, пользовательские данные, состояния интерфейса — всё, что требуется для динамического поведения приложения.let age = 25;
let userName = "Алексей";
let isActive = true;
Здесь:
age, userName, isActive — имена переменных.
25, "Алексей", true — значения, которые они хранят. Динамическая типизация — тип значения определяется автоматически при присваивании, и переменная может хранить значения разных типов в разное время.
let x = 10; // число
x = "привет"; // теперь строка — допустимо
x = [1, 2, 3]; // теперь массив — тоже допустимо Объявление и использование — переменную нужно объявить перед использованием (кроме случаев с var в нестрогом режиме, но это устаревшая практика).
Область видимости — определяет, где переменная доступна (блок, функция, глобально), зависит от ключевого слова (let, const, var).
Подробнее про эти особенности мы прочтём в следующих лекциях.При создании и использовании переменных необходимо следовать <a data-tooltip-position="top" aria-label="Правила наименования переменных в JavaScript" data-href="Правила наименования переменных в JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№2/правила-наименования-переменных-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">правилам наименования переменных</a>.Работа с переменными включает три ключевых действия: объявление, инициализация и присваивание. Эти понятия тесно связаны, но не тождественны — их различие критически важно для понимания поведения кода.Объявление переменной — это создание её имени в области видимости. Оно сообщает интерпретатору: «Я хочу использовать эту метку для хранения значения».В JavaScript есть три ключевых слова для объявления:Примеры:var x; // объявление через var
let y; // объявление через let
const z; // Ошибка: const требует инициализации при объявлении
Ключевое отличие: const обязывает сразу присвоить значение — без этого возникает синтаксическая ошибка.
💡 Рекомендация: Всегда используйте const по умолчанию. Если знаете, что значение будет меняться — замените на let. Никогда не используйте var в современных проектах — он вносит путаницу из-за hoisting и функциональной области видимости.
Инициализация — это первое присваивание значения переменной в момент её создания. Это когда переменная получает своё начальное значение и становится доступной для использования.
Инициализация может совпадать с объявлением.
Она обязательна для const, опциональна для let и var.
Примеры:let age; // объявление — без инициализации (значение undefined)
age = 25; // присваивание — теперь переменная проинициализирована let score = 100; // объявление + инициализация в одной строке
const name = "Алекс"; // объявление + инициализация (обязательно!)
Инициализация = объявление + первое присваивание в одном действии.Присваивание — это операция изменения значения уже существующей переменной. Оно происходит после объявления (и, если нужно, после инициализации).
Для let — можно присваивать сколько угодно раз.
Для const — присваивание разрешено только один раз (при инициализации); любое последующее присваивание вызовет ошибку.
Присваивание не обязательно должно происходить сразу после объявления.
Примеры:let count;
count = 0; // первое присваивание (и одновременно инициализация)
count = count + 1; // второе присваивание — изменение значения
count = null; // присваивание — можно менять const PI = 3.14;
PI = 3.14159; // Ошибка: присваивание const после инициализации запрещено // Но! Если значение — объект или массив:
const user = { name: "Иван" };
user.name = "Петр"; // Разрешено — меняется содержимое объекта, а не ссылка
user = {}; // Ошибка — попытка изменить ссылку
Важно: const защищает ссылку, а не содержимое. Для объектов и массивов можно менять свойства — это не нарушает константность.В JavaScript, как и в любом языке программирования, читаемость и поддерживаемость кода важнее минимального количества строк. Создание дополнительной переменной для хранения промежуточного результата — это не расточительство, а практика, повышающая ясность кода.
Упрощает чтение: имя переменной может объяснять смысл действия, вместо того чтобы оставлять сложное выражение без контекста.
Облегчает отладку: можно легко поставить точку останова на конкретной переменной и увидеть её значение.
Снижает когнитивную нагрузку: другие разработчики (и вы сами через неделю) быстрее поймут логику.
Повышает переиспользуемость: если значение используется несколько раз — нет нужды повторять вычисление.
Без лишней переменной (менее читаемо):if (user.age &gt;= 18 &amp;&amp; user.status === 'active' &amp;&amp; user.country !== 'restricted') { enableAccess();
}
С лишней переменной (более понятно):const isAdult = user.age &gt;= 18;
const isActive = user.status === 'active';
const isAllowedCountry = user.country !== 'restricted'; if (isAdult &amp;&amp; isActive &amp;&amp; isAllowedCountry) { enableAccess();
}
Здесь имена переменных выполняют роль документации — они сразу говорят, что проверяется, а не как.Не стоит создавать переменные ради создания — только если они действительно улучшают понимание. Не нужно оборачивать простые литералы или очевидные значения, например:const five = 5; // Избыточно
return x + five; // Лучше:
return x + 5;
Но если значение получено в результате вычисления, преобразования или запроса — лучше сохранить его с осмысленным именем.Переменные используются для хранения данных, которые могут изменяться во время выполнения программы. Они позволяют:
Сохранять результаты вычислений;
Передавать данные между частями кода;
Управлять состоянием приложения (например, флаги, счётчики, пользовательские данные). Обращайтесь к переменной только после её объявления и инициализации. Попытка использовать let или const до объявления вызовет ошибку ReferenceError.
Не используйте переменные с неопределённым значением (undefined) без проверки — это источник багов.
Избегайте глобальных переменных. Всегда ограничивайте область видимости блоками ({}), функциями или модулями.
Используйте переменные для повторяющихся значений — это упрощает изменение параметров в будущем (например, таймауты, цвета, константы конфигурации).
const apiUrl = 'https://api.example.com/data';
const timeoutMs = 5000; fetch(apiUrl, { timeout: timeoutMs }) .then(response =&gt; response.json()) .then(data =&gt; { const processedData = data.map(item =&gt; item.toUpperCase()); displayResults(processedData); });
Здесь каждая переменная имеет чёткую роль:
apiUrl — централизованное управление адресом API;
timeoutMs — легко изменяемый параметр;
processedData — промежуточный результат, понятный по имени. Переиспользование одной переменной для разных целей:
let user = getUserById(123);
user = calculateDiscount(user); // Теперь user — не объект пользователя, а число. Путаница! Использование переменных без инициализации:
let result;
console.log(result + 10); // NaN — непредсказуемое поведение ]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№2/переменные-в-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №2/Переменные в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:36 GMT</pubDate></item><item><title><![CDATA[Pasted image 20250912212840]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912212840.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912212840.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912212840.png</guid><pubDate>Tue, 14 Oct 2025 09:39:30 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Что такое JavaScript, история появления]]></title><description><![CDATA[JavaScript — это динамический, интерпретируемый язык программирования, изначально разработанный для добавления интерактивности на веб-страницы. Он является одним из трёх основных технологий веб-разработки (наряду с HTML и CSS) и позволяет управлять поведением веб-приложений: обрабатывать события, изменять содержимое страницы, взаимодействовать с сервером и многое другое. Сегодня JavaScript работает не только в браузерах, но и на стороне сервера, в мобильных приложениях, десктопных программах и даже в устройствах Интернета вещей.Это мультипарадигмальный язык, что означает, он поддерживает несколько стилей (парадигм) программирования, и разработчик может выбирать подход, наиболее подходящий для решения задачи. Основные поддерживаемые парадигмы: Функциональное программирование — функции являются первоклассными объектами, можно передавать их как аргументы, возвращать из других функций, создавать замыкания. Поддерживаются чистые функции, иммутабельность, высшие порядки (map, filter, reduce). Объектно-ориентированное программирование (ООП) — через прототипы и (с ES6) синтаксис классов реализуется инкапсуляция, наследование и полиморфизм. Объекты могут динамически расширяться, свойства и методы добавляются во время выполнения. Процедурное программирование — код может быть написан как последовательность инструкций без явного использования классов или функций высшего порядка, что удобно для простых скриптов. JavaScript обладает следующими ключевыми особенностями: Динамическая типизация — тип переменной определяется во время выполнения. Интерпретируемость — код выполняется без предварительной компиляции. Поддержка функционального и объектно-ориентированного стилей — позволяет писать код разными способами. Асинхронность — через колбэки, промисы и async/await обеспечивает неблокирующее выполнение операций. Кроссплатформенность — работает в браузерах, Node.js, React Native, Flutter (через плагины) и других средах. Пример простого кода на JavaScript: alert("Привет, мир!"); let name = "Анна"; console.log("Здравствуйте, " + name + "!"); Этот код отобразит всплывающее окно с сообщением, сохранит имя в переменную и выведет приветствие в консоль браузера.
Веб-браузеры — интерактивные формы, анимации, динамическая загрузка контента. Фронтенд-фреймворки — React, Vue, Angular. Бэкенд — Node.js для серверной логики. Мобильные приложения — React Native, Ionic, NativeScript. Десктопные приложения — Electron. Игры — с использованием Canvas или WebGL. IoT — управление устройствами через JavaScript-среды (например, Johnny-Five).
В середине 1990-х годов веб был преимущественно статичным: HTML описывал структуру, CSS — оформление, но не было инструментов для взаимодействия с пользователем. Нужен был язык, который позволил бы браузерам выполнять простые действия — проверку форм, анимации, реакцию на клики — без обращения к серверу. Netscape Communications, одна из ведущих компаний того времени, решила создать такой язык.В 1995 году Брендан Эйх, работающий в Netscape, за десять дней разработал язык, первоначально названный Mocha, затем LiveScript, а в конце года — JavaScript. Название было выбрано в маркетинговых целях — чтобы ассоциироваться с популярным Java (несмотря на то, что языки принципиально различны). JavaScript был внедрён в браузер Netscape Navigator 2.0.В 1996 году Netscape передала язык в Ecma International для стандартизации. В 1997 году был принят стандарт ECMAScript 1 (ES1). С тех пор язык развивается под управлением Ecma TC39. Каждые 12 месяцев выпускается новая версия стандарта (ES6/ES2015, ES2020, ES2024 и т.д.), которые добавляют новые возможности: стрелочные функции, модули, классы, промисы, деструктуризацию и другие.Сегодня JavaScript — один из самых популярных языков программирования в мире (по данным Stack Overflow, GitHub и других источников). Его экосистема включает тысячи библиотек и фреймворков. Благодаря Node.js он стал универсальным языком, применяемым как на клиенте, так и на сервере. В мобильной разработке JavaScript используется в таких фреймворках, как React Native, позволяя создавать нативные приложения для iOS и Android на единой кодовой базе. Развитие продолжается: активно внедряются новые API, улучшается производительность движков (V8, SpiderMonkey), растёт поддержка TypeScript как надмножества JavaScript.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№2/что-такое-javascript,-история-появления.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №2/Что такое JavaScript, история появления.md</guid><pubDate>Tue, 14 Oct 2025 09:39:25 GMT</pubDate></item><item><title><![CDATA[Практика №9. CSR с гидратацией. Интерактивный счётчик]]></title><description><![CDATA[В рамках этого задания вам необходимо создать веб-приложение, использующее Client-Side Rendering (CSR) с последующей гидратацией. Сервер отдаёт минимальный HTML-шаблон без содержимого — только контейнер и скрипт. Всё поведение (счётчик, управление значениями, стили) реализуется исключительно на клиенте через JavaScript. Приложение — интерактивный счётчик с возможностью задавать начальное значение, минимальное и максимальное значение через атрибуты HTML. Сервер не участвует в логике — он только отдаёт статический index.html и app.js. Задание обязано быть опубликовано в новом приватном репозитории организации GitHub с названием Группа_Фамилия_task-9.index.html&lt;!DOCTYPE html&gt;
&lt;html lang="ru"&gt;
&lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;Счётчик&lt;/title&gt; &lt;link rel="stylesheet" href="/style.css"&gt;
&lt;/head&gt;
&lt;body&gt; &lt;div id="counter" data-initial="0" data-min="-5" data-max="10"&gt; &lt;/div&gt; &lt;script src="/app.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
style.cssbody { font-family: sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background-color: #f5f5f5;
} #counter { text-align: center; padding: 2rem; border-radius: 12px; background-color: white; box-shadow: 0 4px 12px rgba(0,0,0,0.1); min-width: 200px;
} #counter button { padding: 0.5rem 1rem; margin: 0 0.5rem; font-size: 1rem; border: none; border-radius: 6px; cursor: pointer; transition: background-color 0.2s;
} #counter button.decrease { background-color: #ff6b6b; color: white;
} #counter button.reset { background-color: #f7b731; color: white;
} #counter button.increase { background-color: #4ecdc4; color: white;
} #counter span { font-size: 2rem; font-weight: bold; margin: 1rem 0; display: block;
} #counter button:disabled { opacity: 0.5; cursor: not-allowed;
}
Создайте HTTP-сервер на NodeJS, который:
Отвечает на запрос GET / — отдаёт файл index.html
Отвечает на запрос GET /app.js — отдаёт файл app.js
Для всех остальных путей — отдаёт 404 с сообщением &lt;h1&gt;404 Not Found&lt;/h1&gt;
Использует только встроенные модули: http, path, fs
Не использует readFileSync — только readFile
Устанавливает правильный Content-Type: text/html для /
text/javascript для /app.js Сервер слушает порт 3000
Создайте файл index.html с минимальной структурой:
Используйте &lt;div id="counter"&gt; как контейнер для счётчика
Добавьте три data-атрибута: data-initial — начальное значение (по умолчанию 0)
data-min — минимальное допустимое значение (по умолчанию -5)
data-max — максимальное допустимое значение (по умолчанию 10) Подключите стили из /style.css
Подключите скрипт /app.js в конце &lt;body&gt;
Создайте файл style.css с базовыми стилями:
Стили должны применяться только через классы — не через inline-стили
Кнопки должны иметь цвета и переходы
Счётчик должен быть центрирован на странице
Создайте файл app.js, который:
Находит элемент #counter
Считывает значения из data-initial, data-min, data-max (преобразует в числа)
Если атрибуты не заданы — использует значения по умолчанию: initial=0, min=-5, max=10
Генерирует внутри #counter: &lt;span&gt; с текущим значением (изначально = initial)
Три кнопки: «Уменьшить», «Сбросить», «Увеличить» При нажатии: «Уменьшить» — уменьшает значение на 1, но не ниже min
«Увеличить» — увеличивает значение на 1, но не выше max
«Сбросить» — возвращает значение к initial Кнопки «Уменьшить» и «Увеличить» должны отключаться, если достигнуты границы: min → кнопка «Уменьшить» → disabled
max → кнопка «Увеличить» → disabled Все изменения отображаются мгновенно — без перезагрузки
Никаких внешних библиотек — только чистый JavaScript (ES5+)
Никаких fetch(), innerHTML.
После загрузки страницы:
В HTML: &lt;div id="counter" data-initial="0" data-min="-5" data-max="10"&gt;&lt;/div&gt;
После выполнения app.js:
&lt;div id="counter" data-initial="0" data-min="-5" data-max="10"&gt; &lt;span&gt;0&lt;/span&gt; &lt;button class="decrease"&gt;Уменьшить&lt;/button&gt; &lt;button class="reset"&gt;Сбросить&lt;/button&gt; &lt;button class="increase"&gt;Увеличить&lt;/button&gt;
&lt;/div&gt; При нажатии «Увеличить» 12 раз — значение станет 10, кнопка «Увеличить» станет disabled
При нажатии «Уменьшить» — значение упадёт до -5, кнопка «Уменьшить» станет disabled
При нажатии «Сбросить» — значение вернётся к 0, кнопки снова активны Сервер отдаёт только index.html, app.js и style.css — никаких других файлов
Все логика — на клиенте
Никаких React, Vue, jQuery — только чистый JS
Скрипт должен работать сразу после загрузки — без DOMContentLoaded (можно использовать defer или просто поместить в конец &lt;body&gt;)
Стили — только в style.css, не в JS
Никаких alert(), console.log() в финальной версии
На выполнение выделяется 4 практических пары.
Градация баллов после дедлайна: 1 пара: 50% 2 пара: 25% 3 пара: 0% ]]></description><link>задания/секция-1.-javascript/практика-№9.-csr-с-гидратацией.-интерактивный-счётчик.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №9. CSR с гидратацией. Интерактивный счётчик.md</guid><pubDate>Tue, 14 Oct 2025 09:39:25 GMT</pubDate></item><item><title><![CDATA[Приоритет операторов и ассоциативность]]></title><description><![CDATA[Приоритет операторов определяет порядок, в котором выполняются операции в выражении, когда скобки не указаны. Ассоциативность — направление вычисления (слева направо или справа налево), если операторы имеют одинаковый приоритет.
🔹 Важно: Операторы одной группы имеют одинаковый приоритет и выполняются в соответствии с ассоциативностью.
let result = 5 + 3 * 2;
// Выполняется как: 5 + (3 * 2) → 5 + 6 → 11
Умножение (*) имеет более высокий приоритет, чем сложение (+) — поэтому умножение выполняется первым.let a = true;
let b = false;
let c = true; let result = a || b &amp;&amp; c;
// Выполняется как: a || (b &amp;&amp; c) → true || (false &amp;&amp; true) → true || false → true
Оператор &amp;&amp; выше по приоритету, чем || — поэтому сначала вычисляется b &amp;&amp; c.let x = 10;
let y = x &gt; 5 ? "да" : x &lt; 3 ? "нет" : "не знаю";
// Эквивалентно: x &gt; 5 ? "да" : (x &lt; 3 ? "нет" : "не знаю")
Тернарный оператор ?: ассоциативен справа налево, поэтому вложенные условия обрабатываются корректно.let a = 1, b = 2, c = 3;
a = b += c *= 2;
// Выполняется как: c *= 2 → c = 6; b += c → b = 8; a = b → a = 8
// Порядок: справа налево, потому что `=` и составные операторы присваивания ассоциативны справа
Скобки — это не просто формальность. Они делают код предсказуемым и понятным даже для того, кто читает его впервые.if (user.isAdmin &amp;&amp; user.isActive || user.isGuest) { ... }
Что здесь реально проверяется?
→ (user.isAdmin &amp;&amp; user.isActive) || user.isGuestА если вы хотели:
→ user.isAdmin &amp;&amp; (user.isActive || user.isGuest)?Разница критична.if (user.isAdmin &amp;&amp; (user.isActive || user.isGuest)) { ... }
— Чётко видно намерение.// Без скобок — легко ошибиться
if (age &gt;= 18 &amp;&amp; role === 'admin' || role === 'moderator') { ... } // Скобки спасают
if (age &gt;= 18 &amp;&amp; (role === 'admin' || role === 'moderator')) { ... } Никогда не полагайтесь на память о приоритетах
Даже опытные разработчики ошибаются. Если есть сомнения — используйте скобки. Разбивайте сложные выражения на части
Вместо:
const isValid = !isEmpty &amp;&amp; (value.length &gt;= 5 &amp;&amp; value.includes("@")) || isTemp; Лучше:
const isEmpty = value.trim().length === 0;
const hasAtSymbol = value.includes("@");
const meetsLength = value.length &gt;= 5;
const isValid = !isEmpty &amp;&amp; (meetsLength &amp;&amp; hasAtSymbol) || isTemp; Используйте переносы для многострочных условий
if (user &amp;&amp; user.profile &amp;&amp; user.profile.isActive &amp;&amp; (user.role === 'admin' || user.role === 'editor')) { showDashboard();
} Не пишите «умные» однострочные конструкции ради экономии строк
Например:
// ❌ Непонятно
result = a &amp;&amp; b ? c : d || e; // ✅ Ясно
if (a &amp;&amp; b) { result = c;
} else { result = d || e;
} Для логических выражений — комментируйте намерение // Разрешить доступ, если пользователь админ ИЛИ (зарегистрирован и активен)
const canAccess = user.role === 'admin' || (user.registered &amp;&amp; user.active); ]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/приоритет-операторов-и-ассоциативность.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Приоритет операторов и ассоциативность.md</guid><pubDate>Tue, 14 Oct 2025 09:39:24 GMT</pubDate></item><item><title><![CDATA[Операторы работы с битами]]></title><description><![CDATA[Операторы работы с битами выполняют операции на уровне отдельных битов целочисленных значений. В мобильной разработке они встречаются редко, но могут быть полезны при оптимизации хранения флагов, работе с сетевыми протоколами, обработке изображений или взаимодействии с нативными модулями.Все битовые операции в JavaScript работают с 32-битными целыми числами. Любые числа перед операцией приводятся к этому формату (дробные части отбрасываются).Часто используется для хранения нескольких булевых состояний в одном числе.const READ = 1; // 0001
const WRITE = 2; // 0010
const EXEC = 4; // 0100
const DELETE = 8; // 1000 let permissions = READ | WRITE | EXEC; // 0111 = 7 // Проверяем, есть ли право на чтение:
if (permissions &amp; READ) { console.log("Можно читать"); // выполнится
} // Проверяем, есть ли право на удаление:
if (permissions &amp; DELETE) { console.log("Можно удалять"); // не выполнится
} ✅ Экономит память и ускоряет проверки в низкоуровневых сценариях — например, при передаче прав доступа через API или хранении настроек в локальном хранилище.
Объединяет несколько флагов в одно значение:let flags = 0;
flags |= READ; // 0001
flags |= WRITE; // 0011
flags |= EXEC; // 0111 console.log(flags); // 7
Используется для инвертирования конкретного флага:let theme = 0; // 0 — светлая, 1 — тёмная
theme ^= 1; // теперь theme = 1
theme ^= 1; // теперь theme = 0
Также применяется в алгоритмах шифрования или генерации контрольных сумм.Применяется для преобразования чисел и часто встречается в сочетании с indexOf:const arr = ["apple", "banana", "cherry"];
const index = arr.indexOf("banana"); if (~index) { // эквивалентно: if (index !== -1) console.log("Найдено");
} ❗ Устаревший стиль. Современный код предпочтительно пишет так:
if (index !== -1) — более читаемо и понятно.
console.log(5 &lt;&lt; 1); // 10 → 5 * 2¹
console.log(5 &lt;&lt; 2); // 20 → 5 * 2²
console.log(1 &lt;&lt; 3); // 8 → 2³ ⚠️ Работает только с целыми числами. Не заменяет Math.pow() для дробных степеней.
Полезно при оптимизации вычислений в играх, графических движках или обработке сигналов.console.log(8 &gt;&gt; 1); // 4 → 8 / 2
console.log(-8 &gt;&gt; 1); // -4 — знак сохранён
Сохраняет знак числа — подходит для целочисленного деления на 2, 4, 8 и т.д.Преобразует отрицательные числа в большие положительные:console.log(-8 &gt;&gt;&gt; 1); // 2147483644 — интерпретируется как беззнаковое число Используется редко — в основном при работе с бинарными данными (например, Uint32Array, WebAssembly). Хранение флагов в одной переменной: например, права пользователя, состояние UI-элемента, режимы приложения.
Оптимизация производительности: в низкоуровневых системах (игры, аудио/видео обработка).
Работа с нативными модулями: когда приложение использует JNI (Android) или Objective-C/Swift-код, где данные передаются как битовые маски.
Компрессия данных: при отправке маленьких наборов булевых значений через API.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/операторы-работы-с-битами.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Операторы работы с битами.md</guid><pubDate>Tue, 14 Oct 2025 09:39:22 GMT</pubDate></item><item><title><![CDATA[Массивы]]></title><description><![CDATA[Массив — это упорядоченная коллекция значений. Каждый элемент имеет числовой индекс, начиная с 0. Массивы используются для хранения списков: списка задач, списка пользователей, списка элементов в списке приложения.Самый распространённый способ — через литерал:const tasks = ['Почитать книгу', 'Сделать уборку', 'Написать код'];
Можно создать через <a data-tooltip-position="top" aria-label="Конструктор массива Array" data-href="Конструктор массива Array" href="материалы/подтемы/секция-1.-javascript/тема-№11/конструктор-массива-array.html" class="internal-link" target="_self" rel="noopener nofollow">конструктор</a>, но это редко используется:const numbers = new Array(1, 2, 3);
const empty = new Array(5); // массив из 5 пустых ячеек (не [0,0,0,0,0]!)
Литерал [] предпочтительнее: он быстрее, понятнее и безопаснее.Обращение по индексу:console.log(tasks[0]); // "Почитать книгу"
console.log(tasks[2]); // "Написать код"
Если индекс не существует — вернётся undefined:console.log(tasks[5]); // undefined
Многомерные массивы — это массивы, элементами которых являются другие массивы. Они используются для представления структур с несколькими уровнями вложенности: таблицы, матрицы, сетки интерфейса, списки задач с подзадачами.Простейший пример — двумерный массив (матрица 3x3):const matrix = [ [1, 2, 3], [4, 5, 6], [7, 8, 9]
];
Это массив из трёх элементов, каждый из которых — массив чисел.Доступ к элементу осуществляется через два индекса: сначала — строка, потом — столбец:console.log(matrix[0][0]); // 1
console.log(matrix[1][2]); // 6
console.log(matrix[2][1]); // 8
Если попытаться обратиться к несуществующему индексу — получите undefined:console.log(matrix[3][0]); // undefined
console.log(matrix[0][5]); // undefined
У массивов в JS существует достаточно большое количество методов для управления данными.
В рамках темы мы изучим самые часто используемые. Остальные же - вам необходимо будет изучать самостоятельно! Добавить в конец — push():tasks.push('Сделать 47 практику');
console.log(tasks.length); // 4
Удалить из конца — pop():const lastTask = tasks.pop();
console.log(lastTask); // "Сделать 47 практику"
console.log(tasks.length); // 3
Добавить в начало — unshift():tasks.unshift('Позавтракать');
console.log(tasks[0]); // "Позавтракать"
Удалить из начала — shift():const firstTask = tasks.shift();
console.log(firstTask); // "Позавтракать"
Эти методы (push, pop, unshift, shift) меняют исходный массив — это мутация.Мощный метод для вставки, удаления или замены элементов по индексу.Синтаксис: splice(начальный индекс, количество удаляемых, ...новые элементы)Удалить 1 элемент начиная с индекса 1:const fruits = ['яблоко', 'банан', 'апельсин'];
fruits.splice(1, 1); // удаляем "банан"
console.log(fruits); // ['яблоко', 'апельсин']
Вставить элемент:fruits.splice(1, 0, 'груша'); // вставляем "груша" на позицию 1
console.log(fruits); // ['яблоко', 'груша', 'апельсин']
Заменить элемент:fruits.splice(1, 1, 'киви'); // заменяем "груша" на "киви"
console.log(fruits); // ['яблоко', 'киви', 'апельсин']
Копирует часть массива без изменения исходного.Синтаксис: slice(начало, конец) — конец не включается.const items = ['a', 'b', 'c', 'd', 'e'];
const subset = items.slice(1, 4); // с индекса 1 до 3
console.log(subset); // ['b', 'c', 'd']
console.log(items); // ['a', 'b', 'c', 'd', 'e'] — не изменился
indexOf() — возвращает индекс первого совпадения, или -1, если не найдено:const colors = ['красный', 'зелёный', 'синий'];
console.log(colors.indexOf('зелёный')); // 1
console.log(colors.indexOf('жёлтый')); // -1
includes() — возвращает true или false:console.log(colors.includes('синий')); // true
console.log(colors.includes('жёлтый')); // false
includes() удобнее для проверки наличия, indexOf() — если нужно знать позицию.Цикл for — классический, с индексом:for (let i = 0; i &lt; tasks.length; i++) { console.log(`${i + 1}. ${tasks[i]}`);
}
Цикл for...of — перебирает значения, индекс не нужен:for (const task of tasks) { console.log(task);
}
for...of предпочтителен, когда вам не нужен индекс — читаемо и безопасно.
Не используйте for...in для массивов — он перебирает ключи (индексы как строки), и может вести себя неожиданно с дополнительными свойствами.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/массивы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Массивы.md</guid><pubDate>Tue, 14 Oct 2025 09:39:20 GMT</pubDate></item><item><title><![CDATA[Гидратация]]></title><description><![CDATA[Гидратация — это процесс, при котором JavaScript-приложение на клиенте «подключается» к уже сгенерированному сервером HTML, добавляя интерактивность без пересоздания разметки.Сервер на NodeJS получает запрос, запрашивает данные (например, список задач из базы), генерирует полный HTML и отправляет его браузеру:&lt;!DOCTYPE html&gt;
&lt;html&gt; &lt;body&gt; &lt;div id="root"&gt; &lt;h1&gt;Задачи&lt;/h1&gt; &lt;ul&gt; &lt;li&gt;Почитать&lt;/li&gt; &lt;li&gt;Написать код&lt;/li&gt; &lt;/ul&gt; &lt;/div&gt; &lt;script src="/app.js"&gt;&lt;/script&gt; &lt;/body&gt;
&lt;/html&gt;
Браузер мгновенно отображает этот HTML — пользователь видит контент сразу.
Это хорошо для скорости и SEO.Но пока ничего не работает:
— Кнопки не реагируют
— Нельзя добавить задачу
— Нет обработчиков событийПочему? Потому что HTML — это статичный результат. Он не знает, что должен быть интерактивным.Когда загружается и выполняется JavaScript-файл (app.js), фреймворк (например, React, Vue) анализирует уже существующий HTML, сравнивает его с тем, что он ожидает сгенерировать, и привязывает события, состояния и логику к уже отрисованным элементам.Это не перерисовка. Это присоединение поведения к существующей разметке.Пример (упрощённо):// В React
ReactDOM.hydrate(&lt;App /&gt;, document.getElementById('root'));
— React видит: «В DOM уже есть &lt;ul&gt;&lt;li&gt;Почитать&lt;/li&gt;&lt;/ul&gt;»
— Он проверяет: «А должен ли я сгенерировать именно это?» — да
— Он не удаляет элементы
— Он добавляет обработчики кликов, состояния, эффекты — к тем же DOM-узламРезультат:
— Пользователь видит контент сразу
— Через долю секунды — кнопки становятся кликабельными
— Приложение работает как обычное SPA
В CSR — сервер отдаёт пустой index.html. Разметка создаётся полностью JS — нет HTML для «подключения», поэтому гидратация не применяется.
В статическом вебе (WEB 1.0) — вообще нет JavaScript. Нет интерактивности — нет и гидратации. Гидратация требует, чтобы HTML, сгенерированный на сервере, точно совпадал с тем, что сгенерирует клиент.
Если сервер отдал &lt;li&gt;Почитать&lt;/li&gt;, а React ожидает &lt;li data-id="1"&gt;Почитать&lt;/li&gt; — будет ошибка. Если в разметке есть динамические данные (например, время, токены, пользовательские данные), они должны быть одинаковыми на сервере и клиенте. Гидратация — не бесплатна: JS-файл должен загрузиться и выполниться. Если он тяжёлый — интерактивность появится с задержкой. Вы заходите на сайт новостей:
Сервер (NodeJS + Next.js) получает запрос Запрашивает статьи из БД Генерирует HTML с заголовками, текстами, картинками Отдаёт браузеру: &lt;article&gt;&lt;h1&gt;Новость&lt;/h1&gt;&lt;p&gt;Текст...&lt;/p&gt;&lt;/article&gt;
&lt;script src="/_next/.../page.js"&gt;&lt;/script&gt; Браузер отображает статью мгновенно page.js загружается — React запускает hydrate() Клик по кнопке «Лайк» — работает, потому что React привязал обработчик к этому элементу
→ Пользователь не видит «прыжков», не ждёт загрузки JS, чтобы увидеть контент — и при этом может взаимодействовать с приложением.Это стандарт для современных фреймворков: Next.js, Nuxt.js, SvelteKit.
В NodeJS-приложениях гидратация — не опциональная фича, а ключевой механизм для создания быстрых, SEO-оптимизированных веб-приложений. Тем не менее, в основном в течении курса мы будет создавать только CSR-SPA приложения.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/гидратация.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/Гидратация.md</guid><pubDate>Tue, 14 Oct 2025 09:39:18 GMT</pubDate></item><item><title><![CDATA[Операторы присваивания JavaScript]]></title><description><![CDATA[Операторы присваивания используются для записи значений в переменные. В JavaScript они делятся на базовые и составные, а также включают современные операторы, упрощающие работу с потенциально отсутствующими данными.Присваивает значение справа переменной слева.let count = 0;
let message = "Привет";
let isActive = true; Это единственный оператор, который создаёт переменную при первом использовании в глобальной области видимости (если не используется let/const — не рекомендуется).
Сокращённая форма операций, где значение переменной изменяется и сразу присваивается обратно.let score = 100; score += 25; // 125
score *= 2; // 250
score -= 50; // 200
score %= 60; // 20 (остаток от 200 ÷ 60)
score **= 2; // 400 (20²) console.log(score); // 400 ✅ Преимущество: короче, читаемее, немного эффективнее — особенно полезны в циклах и обработке данных.
Присваивает значение только если левый операнд равен null или undefined.let userLanguage = null;
userLanguage ??= "en"; // теперь userLanguage = "en" let userName = "";
userName ??= "Аноним"; // останется "", потому что "" ≠ null/undefined let settings = { theme: undefined };
settings.theme ??= "dark"; // theme станет "dark" console.log(settings.theme); // "dark" 💡 Отличие от =: ??= не перезаписывает существующие значения, даже если они ложные (0, "", false).
Это делает его идеальным для установки значений по умолчанию в конфигурациях, настройках, API-ответах.
let theme = localStorage.getItem("theme");
theme ??= "light"; // если не задано — использовать светлую тему let fontSize = localStorage.getItem("fontSize");
fontSize ??= 16; // если не задано — 16px console.log({ theme, fontSize });
Присваивает значение только если предшествующая цепочка существует (не null/undefined).let user = { profile: { name: "Иван" } }; // Попытка присвоить значение только если user.profile существует
user.profile?.name ??= "Гость"; // НЕ сработает — это не присваивание через ?.
user.profile?.age ??= 25; // НЕ сработает — age не существует, но ?. не создаёт свойства // А вот так:
user.profile?.age = 25; // ❌ Ошибка: нельзя присвоить, если user.profile не существует
На самом деле, ?.= — это оператор присваивания, а не объединения. Он работает следующим образом:let obj = {}; obj?.prop = 10; // ❌ ОШИБКА — SyntaxError: Invalid left-hand side expression // Правильно — только если объект существует:
let config = { settings: {} };
config.settings?.debug = true; // ✅ Работает — config.settings существует console.log(config.settings.debug); // true // Если объект отсутствует — ничего не происходит:
let data = null;
data?.value = "test"; // Ничего не произойдёт — ошибки нет
console.log(data); // null ⚠️ Важно: ?.= не создаёт свойства — он лишь пропускает присваивание, если левая часть null/undefined.
Он применяется только к существующим объектам и их вложенным свойствам.
function updateUser(user, newSettings) { user?.profile?.name = newSettings.name; user?.profile?.email = newSettings.email; user?.preferences?.theme = newSettings.theme;
} updateUser(null, { name: "Анна" }); // Ничего не сломается
updateUser({ profile: {} }, { name: "Анна" }); // profile.name = "Анна" — сработает ✅ Идеально подходит для работы с API-ответами, где структура может быть неполной. Не используйте ?.= для создания новых свойств в null/undefined объектах — это невозможно.
Не путайте ??= и ?.=: ??= — присваивает, если значение null/undefined ?.= — присваивает, только если путь существует ]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/операторы-присваивания-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Операторы присваивания JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:18 GMT</pubDate></item><item><title><![CDATA[Практика №8. SSR-сервер с динамической генерацией страниц]]></title><description><![CDATA[В рамках этого задания вам необходимо создать сервер на NodeJS, который реализует Server-Side Rendering (SSR) — динамическую генерацию HTML-страниц на основе данных, хранящихся в памяти. Сервер должен отдавать полностью готовые HTML-страницы при запросах к корневому пути / и к динамическому пути /task/:id, без использования клиентского JavaScript для рендеринга. Все данные формируются на сервере, ответы содержат структурированный HTML с встроенными стилями и ссылками. Никаких внешних библиотек — только встроенные модули NodeJS: http, path.Задание обязано быть опубликовано в новом приватном репозитории организации GitHub с названием Группа_Фамилия_task-8.(пусто)Создайте HTTP-сервер на NodeJS, который:
GET / — отдаёт главную страницу со списком всех задач GET /task/:id — отдаёт страницу одной задачи, где :id — целое число (например, /task/2)
const tasks = [ { id: 1, title: 'Выучить JavaScript', completed: false }, { id: 2, title: 'Создать Todo-приложение', completed: true }, { id: 3, title: 'Настроить сервер', completed: false }
]; Заголовком &lt;h1&gt;Мои задачи&lt;/h1&gt;
Списком задач в &lt;ul&gt; — каждый элемент &lt;li&gt; содержит название задачи
Для задач с completed: true — добавлять класс completed в &lt;li&gt;
Внутренним стилем в &lt;head&gt;: .completed { text-decoration: line-through; color: #999; } Пустым &lt;script&gt;&lt;/script&gt; в конце &lt;body&gt; (для имитации гидратации)
Корректным &lt;!DOCTYPE html&gt; и мета-тегом кодировки
Content-Type: text/html Заголовком &lt;h1&gt;Задача #&lt;id&gt;&lt;/h1&gt;
Данными задачи: &lt;p&gt;&lt;strong&gt;Название:&lt;/strong&gt; &lt;span&gt;...&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Статус:&lt;/strong&gt; &lt;span&gt;Выполнена&lt;/span&gt;&lt;/p&gt; или &lt;p&gt;&lt;strong&gt;Статус:&lt;/strong&gt; &lt;span&gt;Не выполнена&lt;/span&gt;&lt;/p&gt; Кнопкой «Назад» с ссылкой на /
Корректным &lt;!DOCTYPE html&gt; и мета-тегом кодировки
Content-Type: text/html Если :id не существует в массиве — отдаётся страница 404 с содержимым: &lt;h1&gt;404&lt;/h1&gt;
&lt;p&gt;Задача с таким ID не найдена.&lt;/p&gt; Если :id — не число или пустой — отдаётся 404
Для всех остальных путей (например, /about, /api/users) — отдаётся 404
Не используйте fs.readFileSync() — только асинхронные методы (fs.readFile() не требуется, так как данные в памяти) Используйте только встроенные модули: http, path
Никаких внешних библиотек (Express, etc.)
Никакого клиентского рендеринга — все HTML генерируется на сервере
Никаких fetch() или innerHTML — страницы должны быть полностью готовы при приходе запроса
Устанавливайте правильный Content-Type для всех ответов
Обработка путей — через req.url и строковую манипуляцию (split(), startsWith(), parseInt())
Сервер должен слушать порт 3000
Запрос: GET /
Ответ: &lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;Задачи&lt;/title&gt; &lt;style&gt; .completed { text-decoration: line-through; color: #999; } &lt;/style&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Мои задачи&lt;/h1&gt; &lt;ul&gt; &lt;li&gt;Выучить JavaScript&lt;/li&gt; &lt;li class="completed"&gt;Создать Todo-приложение&lt;/li&gt; &lt;li&gt;Настроить сервер&lt;/li&gt; &lt;/ul&gt; &lt;script&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Запрос: GET /task/2
Ответ: &lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;Задача #2&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Задача #2&lt;/h1&gt; &lt;p&gt;&lt;strong&gt;Название:&lt;/strong&gt; &lt;span&gt;Создать Todo-приложение&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;strong&gt;Статус:&lt;/strong&gt; &lt;span&gt;Выполнена&lt;/span&gt;&lt;/p&gt; &lt;p&gt;&lt;a href="/"&gt;← Назад&lt;/a&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
Запрос: GET /task/999
Ответ: &lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;meta charset="utf-8"&gt; &lt;title&gt;404&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;404&lt;/h1&gt; &lt;p&gt;Задача с таким ID не найдена.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
На выполнение выделяется 3 практических пары.
Градация баллов после дедлайна: 1 пара: 50% 2 пара: 25% 3 пара: 0% ]]></description><link>задания/секция-1.-javascript/практика-№8.-ssr-сервер-с-динамической-генерацией-страниц.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №8. SSR-сервер с динамической генерацией страниц.md</guid><pubDate>Tue, 14 Oct 2025 09:39:17 GMT</pubDate></item><item><title><![CDATA[Логические операторы JavaScript]]></title><description><![CDATA[Логические операторы — &amp;&amp; (И), || (ИЛИ) и ! (НЕ) — позволяют комбинировать и инвертировать логические значения. В JavaScript они работают не только с true и false, но и с любыми значениями, благодаря особенностям приведения типов и механизму короткого замыкания.Возвращает true, если оба операнда истинны.
Но в JavaScript он возвращает не булево значение, а один из операндов — первый ложный или последний истинный.console.log(true &amp;&amp; true); // true
console.log(true &amp;&amp; false); // false
console.log(5 &amp;&amp; "hello"); // "hello" — оба истинны, возвращён второй
console.log(0 &amp;&amp; "test"); // 0 — первый ложный, возвращён он же
console.log("" &amp;&amp; null); // "" — первый ложный
Если первый операнд — ложный, второй не вычисляется.function log() { console.log("Эта функция не вызовется"); return true;
} console.log(false &amp;&amp; log()); // false — функция log() НЕ была вызвана ✅ Это полезно для безопасного доступа к свойствам объектов:
const user = { profile: { name: "Alice" } }; // Безопасно: если user или user.profile отсутствуют — не будет ошибки
console.log(user &amp;&amp; user.profile &amp;&amp; user.profile.name); // "Alice" // Если бы user был undefined — выражение остановилось бы на первом шаге
Возвращает первый истинный операнд, или последний, если все ложные.console.log(true || false); // true
console.log(false || "world"); // "world"
console.log(0 || null || 5 || 10); // 5 — первый истинный
console.log("" || 0 || false); // false — все ложные, возвращён последний
Если первый операнд — истинный, второй не вычисляется.function log() { console.log("Эта функция вызовется только если нужно"); return "result";
} console.log(true || log()); // true — функция log() НЕ вызвана
function greet(name) { name = name || "Гость"; // если name пустой/ложный — использовать "Гость" console.log(`Привет, ${name}!`);
} greet(); // "Привет, Гость!"
greet(""); // "Привет, Гость!"
greet(null); // "Привет, Гость!"
greet("Анна"); // "Привет, Анна!"
greet(0); // "Привет, Гость!" — осторожно! ⚠️ Внимание: 0, "", null, undefined, NaN — всё это ложные значения.
Если вы ожидаете 0 как валидный ввод — такой подход сломается.
function greet(name) { name = name ?? "Гость"; // только null или undefined → заменяются console.log(`Привет, ${name}!`);
} greet(0); // "Привет, 0!" — правильно!
greet(undefined); // "Привет, Гость!" ✅ Рекомендация: в современных приложениях используйте ?? вместо || для установки значений по умолчанию, если вам важно отличать 0, false, "" от null/undefined.
Инвертирует значение операнда. Возвращает булево значение (true или false).console.log(!true); // false
console.log(!false); // true
console.log(!"hello"); // false — строка истинна
console.log(!0); // true — 0 ложен
console.log(!{}); // false — объект истинен
console.log(!!"text"); // true — двойное отрицание приводит к булеву значению
const isEmpty = !array.length; // true, если массив пуст
const hasUser = !!user; // true, если user существует и не null/undefined ✅ Двойное отрицание !!value — популярный способ явно преобразовать любое значение в булево.
Приоритет (с высшего к низшему):
! — НЕ (наиболее высокий)
&amp;&amp; — И
|| — ИЛИ (наименьший)
console.log(true || false &amp;&amp; false); // true
// Эквивалентно: true || (false &amp;&amp; false) → true || false → true
Чтобы избежать путаницы — всегда используйте скобки:console.log((true || false) &amp;&amp; false); // false
(Больше про приоритет операторов будет в этой же теме)]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/логические-операторы-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Логические операторы JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:17 GMT</pubDate></item><item><title><![CDATA[Основные понятия Git]]></title><description><![CDATA[Репозиторий — это папка, в которой Git отслеживает все изменения файлов.
Он хранит всю историю проекта: все коммиты, ветки, настройки.Создать репозиторий можно в любой папке:git init
После этой команды в папке появляется скрытая папка .git — именно там Git хранит всю информацию.
Не удаляйте её — без неё репозиторий перестанет работать.Пример:
Вы создаёте мобильное приложение на React Native. Папка MyMobileApp/ становится репозиторием — Git будет следить за всеми изменениями в файлах App.js, src/components/Button.js, package.json, ios/ и android/.Коммит — это сохранённое состояние проекта на определённый момент.
Это как снимок экрана вашего кода, который вы можете вернуть в любое время.Каждый коммит имеет уникальный хеш (например, a1b2c3d4) и сообщение, описывающее, что было изменено.Пример создания коммита:git add src/components/LoginButton.js
git commit -m "Добавил кнопку входа с анимацией" git add — выбирает изменения для сохранения.
git commit — фиксирует их как единое целое.
Важно: коммит — это не просто сохранение файла. Это логическая единица изменений.
Хороший коммит делает одну вещь и говорит, что именно он сделал.Пример плохого коммита:
"fixed stuff" — непонятно, что исправлено.Пример хорошего коммита:
"Исправил баг: кнопка входа не реагировала на тач в Android" — ясно, понятно, воспроизводимо.Ветка — это изолированная линия разработки.
По умолчанию при создании репозитория создаётся ветка main.Вы можете создавать новые ветки для работы над новой функцией, исправлением бага или экспериментом — и не мешать основной версии приложения.Пример:git branch feature/login-animation
git switch feature/login-animation
Теперь вы работаете в ветке feature/login-animation.
Все изменения — только здесь.
Когда функция готова — вы объедините её с main.Это позволяет:
Не ломать рабочую версию приложения.
Параллельно работать над несколькими задачами.
Легко откатиться, если что-то пошло не так.
Пример сценария:
Вы добавляете анимацию при входе в приложении.
Другой разработчик работает над авторизацией через Google.
Оба работают в своих ветках — никаких конфликтов до момента слияния.Git отслеживает файлы по четырём состояниям. Понимание этих состояний — ключ к работе с Git.Чтобы посмотреть текущее состояние всех файлов:git status
Пример последовательности:
Вы создали src/screens/AuthScreen.js → untracked
Вы выполнили git add src/screens/AuthScreen.js → staged
Вы выполнили git commit -m "Добавил экран авторизации" → теперь файл tracked, изменения зафиксированы
Вы снова отредактировали src/screens/AuthScreen.js → теперь он modified Запомните: чтобы сохранить изменения — нужно сначала add, потом commit.
Нельзя сделать коммит, не добавив изменения в staging-зону.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/основные-понятия-git.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Основные понятия Git.md</guid><pubDate>Tue, 14 Oct 2025 09:39:15 GMT</pubDate></item><item><title><![CDATA[Разница между WEB 1.0 и WEB 2.0 в контексте NodeJS]]></title><description><![CDATA[В контексте NodeJS разница между WEB 1.0 и WEB 2.0 проявляется в том, как сервер формирует ответ и кто отвечает за отображение контента.Сервер просто читает файл с диска и отправляет его как есть.const fs = require('fs');
const http = require('http'); http.createServer((req, res) =&gt; { if (req.url === '/') { fs.readFile('./index.html', (err, data) =&gt; { if (err) { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('&lt;h1&gt;404 Not Found&lt;/h1&gt;'); } else { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(data); } }); }
}).listen(3000);
— index.html — это готовый HTML-документ, написанный заранее.
— Нет данных из базы. Нет персонализации.
— При изменении контента — нужно менять файл на диске.
— Это статика. NodeJS здесь выступает как простой файловый сервер.Сервер не отдаёт HTML — он отдаёт данные.http.createServer((req, res) =&gt; { if (req.url === '/api/tasks') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify([ { id: 1, title: 'Почитать', completed: false }, { id: 2, title: 'Написать код', completed: true } ])); }
}).listen(3000);
— Клиент (браузер или мобильное приложение) делает запрос: fetch('/api/tasks')
— Получает JSON
— С помощью JavaScript (React, Vue, Vanilla JS) строит список задач в DOM
— При обновлении — новый запрос, новый JSON, обновление интерфейсаЭто — чистый CSR (Client-Side Rendering).Сервер динамически создаёт HTML на основе данных, и отправляет его уже готовым.http.createServer((req, res) =&gt; { if (req.url === '/') { const tasks = [ { id: 1, title: 'Почитать', completed: false }, { id: 2, title: 'Написать код', completed: true } ]; let html = ` &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;body&gt; &lt;h1&gt;Задачи&lt;/h1&gt; &lt;ul&gt; ${tasks.map(t =&gt; `&lt;li ${t.completed ? 'style="text-decoration:line-through"' : ''}&gt;${t.title}&lt;/li&gt;`).join('')} &lt;/ul&gt; &lt;script src="/app.js"&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt; `; res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(html); }
}).listen(3000);
— Браузер получает полный HTML — сразу видит контент.
— После загрузки скрипта app.js — React (или другой фреймворк) «подключается» к этому HTML и добавляет интерактивность — это называется <a data-tooltip-position="top" aria-label="Гидратация" data-href="Гидратация" href="материалы/подтемы/секция-1.-javascript/тема-№12/гидратация.html" class="internal-link" target="_self" rel="noopener nofollow">гидратация</a>.
— SEO работает: поисковики видят полный контент.
— Пример: Next.js, Nuxt.js — NodeJS-сервер генерирует HTML на лету.Сервер отдаёт минимальный HTML — без контента.http.createServer((req, res) =&gt; { if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end(` &lt;!DOCTYPE html&gt; &lt;html&gt; &lt;body&gt; &lt;div id="root"&gt;&lt;/div&gt; &lt;script src="/bundle.js"&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt; `); }
}).listen(3000);
— Браузер получает пустой div#root
— Загружается bundle.js (мега-файл с React, логикой, компонентами)
— Только после загрузки и выполнения JS — рендерится список задач
— Пока JS не загрузился — пользователь видит пустую страницу
— SEO сложный: поисковики могут не дождаться выполнения JS
WEB 1.0 — HTML как файл. CSR — HTML как результат работы JS на клиенте. SSR — HTML как результат работы JS на сервере (с последующей гидратацией). NodeJS позволяет реализовывать все три подхода.
WEB 1.0 — для статики.
CSR — для SPA и мобильных веб-приложений.
SSR — для SEO-чувствительных сайтов (магазины, новости, лендинги). Выбор зависит от цели: скорость отображения, SEO, сложность, масштабируемость.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/разница-между-web-1.0-и-web-2.0-в-контексте-nodejs.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/Разница между WEB 1.0 и WEB 2.0 в контексте NodeJS.md</guid><pubDate>Tue, 14 Oct 2025 09:39:13 GMT</pubDate></item><item><title><![CDATA[Оператор `switch`]]></title><description><![CDATA[Оператор switch используется для выбора одного из нескольких блоков кода на основе значения выражения. Он особенно удобен, когда нужно проверить переменную на равенство нескольким дискретным значениям.switch (выражение) { case значение1: // код, если выражение === значение1 break; case значение2: // код, если выражение === значение2 break; default: // код, если ни одно значение не совпало (необязательно)
}
switch сравнивает значение выражения с каждым case с помощью строгого сравнения (===) — то есть и тип, и значение должны совпадать.Пример: выбор языка интерфейсаconst language = "ru"; switch (language) { case "en": setLanguage("English"); break; case "ru": setLanguage("Русский"); break; case "es": setLanguage("Español"); break; default: setLanguage("English"); // запасной вариант
}
Здесь language сравнивается со строками "en", "ru", "es". Если совпадает — выполняется соответствующий блок, и break останавливает выполнение.Без break выполнение продолжается на следующие case — это называется просачиванием (fall-through).Пример с ошибкой:const role = "admin"; switch (role) { case "admin": console.log("Администратор"); case "moderator": console.log("Модератор"); case "user": console.log("Пользователь"); default: console.log("Гость");
}
Вывод:Администратор
Модератор
Пользователь
Гость
Потому что после case "admin": нет break — выполнение «просочилось» дальше.Это может быть полезно в редких случаях — например, когда несколько значений должны делать одно и то же:const permission = "read"; switch (permission) { case "read": case "write": case "delete": enableButton("action"); break; default: disableButton("action");
}
Здесь если permission — "read", "write" или "delete" — кнопка включается. Это читаемо и логично.default не обязателен, но рекомендуется всегда добавлять. Он обрабатывает случаи, когда значение не совпало ни с одним case.Пример: обработка типов уведомленийconst notificationType = "error"; // пришло из API switch (notificationType) { case "success": showBanner("Успешно!", "green"); break; case "warning": showBanner("Предупреждение!", "orange"); break; case "error": showBanner("Ошибка!", "red"); break; default: console.warn("Неизвестный тип уведомления:", notificationType); showBanner("Новое сообщение", "blue");
}
Здесь даже если сервер отправит неожиданный тип — приложение не сломается, а просто покажет стандартное сообщение и залогирует проблему.✅ Используйте switch, когда:
Проверяете одну переменную на равенство нескольким конкретным значениям.
Значения — строковые константы, числа, перечисления (enum).
Код должен быть структурирован и легко расширяться.
❌ Не используйте switch, когда:
Нужно проверять диапазоны (if (score &gt;= 90)).
Условия сложные (if (user.age &gt; 18 &amp;&amp; user.role === "admin")).
Вы сравниваете объекты или массивы — switch работает только с примитивами. switch работает только с примитивами: строки, числа, булевы, null, undefined, символы.
case не может быть выражением — только литералы или константы.
Все case должны быть уникальными в рамках одного switch.
Пример запрещённого:switch (x) { case y + 1: // ОШИБКА — выражение не допускается break;
}
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/оператор-`switch`.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Оператор `switch`.md</guid><pubDate>Tue, 14 Oct 2025 09:39:13 GMT</pubDate></item><item><title><![CDATA[Базовые команды Git]]></title><description><![CDATA[Создаёт новый Git-репозиторий в текущей папке.
После этой команды появляется скрытая папка .git — она хранит всю историю проекта.git init
Пример:
Вы начинаете новый проект на React Native:cd MyMobileApp
git init
Теперь Git отслеживает все файлы в папке MyMobileApp/: App.js, package.json, src/, android/, ios/.
⚠️ Не запускайте git init внутри уже существующего репозитория — это сломает структуру.
Добавляет изменения файлов в staging area — область, откуда они будут включены в следующий коммит.Добавить один файл:git add src/components/LoginButton.js
Добавить все изменённые и новые файлы:git add .
Добавить все файлы, кроме игнорируемых (через .gitignore):git add -A
Пример:
Вы изменили App.js и создали src/screens/Home.js.
Чтобы зафиксировать оба:git add App.js src/screens/Home.js Важно: git add не сохраняет изменения — он только готовит их к сохранению.
Без git commit изменения не зафиксируются.
Сохраняет все подготовленные изменения как один коммит.
Обязательно нужно указывать сообщение с флагом -m.git commit -m "Добавил экран Home с приветствием"
Пример хорошего сообщения:
"Исправил баг: HomeScreen не отображался на Android 12" — понятно, конкретно, воспроизводимо.Пример плохого сообщения:
"fixed" — ничего не объясняет.
Коммит — это логическая единица. Делайте один коммит на одну задачу.
Показывает, какие файлы изменены, какие добавлены, а какие ещё не отслеживаются.git status
Вывод может выглядеть так:On branch main
Changes not staged for commit: modified: src/components/Button.js Untracked files: src/screens/Home.js Changes to be committed: new file: src/utils/api.js
Это помогает понять:
— Что вы сделали?
— Что ещё нужно добавить?
— Что уже готово к коммиту?Показывает список всех коммитов в текущей ветке — от самого нового к самому старому.git log
Вывод:commit a1b2c3d4e5f67890...
Author: Ivan Petrov &lt;ivan@example.com&gt;
Date: Mon Apr 1 10:30:00 2025 +0300 Добавил экран Home с приветствием commit f9e8d7c6b5a4a3b2...
Author: Ivan Petrov &lt;ivan@example.com&gt;
Date: Sun Mar 31 15:20:00 2025 +0300 Настроил стили кнопок
Короткая версия (только хеш и сообщение):git log --oneline
Вывод:a1b2c3d Добавил экран Home с приветствием
f9e8d7c Настроил стили кнопок Используйте git log --oneline чаще — он удобнее для быстрого просмотра.
Показывает, что именно изменилось в файлах между рабочей директорией и последним коммитом.git diff
Пример вывода:diff --git a/src/components/Button.js b/src/components/Button.js
index 1234567..89abcde 100644
--- a/src/components/Button.js
+++ b/src/components/Button.js
@@ -5,7 +5,7 @@ const Button = () =&gt; ( &lt;View style={styles.container}&gt;
- &lt;Text&gt;Войти&lt;/Text&gt;
+ &lt;Text style={styles.bold}&gt;Войти&lt;/Text&gt; &lt;/View&gt; );
Здесь:
- — удалённая строка
+ — добавленная строка
Если вы хотите увидеть изменения, которые уже добавлены в staging (и готовы к коммиту):git diff --cached git diff без флагов — показывает не добавленные изменения.
git diff --cached — показывает добавленные, но ещё не закоммиченные.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/базовые-команды-git.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Базовые команды Git.md</guid><pubDate>Tue, 14 Oct 2025 09:39:13 GMT</pubDate></item><item><title><![CDATA[Что такое Node.js]]></title><description><![CDATA[Node.js — это среда выполнения JavaScript, которая позволяет запускать код на сервере, а не только в браузере. Она построена на движке V8 от Google и даёт JavaScript доступ к системным ресурсам: файловой системе, сети, процессам. Это делает JavaScript полноценным языком для создания серверных приложений, инструментов разработки и автоматизации — всё на том же языке, что и фронтенд.Node.js появился в 2009 году благодаря Райану Далю — разработчику, который задался вопросом: почему JavaScript, который так хорошо справляется с асинхронными событиями в браузере (клики, загрузки, запросы), не может делать то же самое на сервере? Он объединил движок V8, который быстро выполняет JavaScript, с библиотекой libuv — специальной системой для асинхронного ввода-вывода. В результате получилась первая среда, где сервер мог обрабатывать тысячи одновременных соединений без создания отдельного потока на каждое — это стало прорывом в производительности.JavaScript на сервере упрощает разработку. Если вы пишете мобильное приложение на React Native или используете JSON-API, то логика, данные и даже части валидации могут быть общими между клиентом и сервером. Нет необходимости учить два разных языка — JavaScript на фронтенде и, например, Java или Python на бэкенде. Это снижает сложность команды, ускоряет разработку и делает поддержку проще. Также огромная экосистема npm дарит готовые решения для любой задачи — от баз данных до авторизации.В браузере JavaScript работает в ограниченной среде: он может работать с DOM, отправлять запросы через fetch, хранить данные в localStorage, но не может читать файлы с диска или слушать порты. В Node.js этих ограничений нет. Вместо window и document вы получаете global, process, require, module. Вы можете использовать модули fs для работы с файлами, http для создания сервера, path для обработки путей, child_process для запуска команд. То есть — Node.js превращает JavaScript из языка «для страниц» в язык «для всего».Node.js — невидимый двигатель современной мобильной разработки.
— Backend для API: большинство мобильных приложений получают данные через REST или GraphQL. Эти API почти всегда пишут на Node.js (Express, NestJS, Fastify).
— Инструменты сборки: Webpack, Metro, Babel, Vite — все они написаны на Node.js и собирают ваш код в приложение для iOS и Android.
— CLI-инструменты: Expo CLI, Ionic CLI, Capacitor — они создают проекты, добавляют плагины, настраивают конфиги — и всё это работает на Node.js.
— CI/CD: когда вы заливаете код в GitHub, а система автоматически собирает APK/IPA и публикует его — за этим стоит скрипт на Node.js.
Даже если вы никогда не напишете строчку на Node.js — вы будете им пользоваться каждый день. Без него мобильная разработка была бы намного медленнее, сложнее и менее гибкой.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№4/что-такое-node.js.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №4/Что такое Node.js.md</guid><pubDate>Tue, 14 Oct 2025 09:39:12 GMT</pubDate></item><item><title><![CDATA[Объекты]]></title><description><![CDATA[Объект — это неупорядоченная коллекция пар ключ-значение. Ключ — это строка (или символ), значение — любой тип данных: число, строка, массив, другой объект, функция.Объекты используются для хранения структурированных данных: профиль пользователя, настройки приложения, ответ от API, данные задачи с метаданными.Самый распространённый способ — через литерал:const user = { name: 'Анна', age: 28, isAdmin: false
};
Можно создать через конструктор, но это редко используется:const settings = new Object();
settings.theme = 'dark';
settings.language = 'ru';
Литерал {} предпочтительнее: короче, понятнее, быстрее.Если ключ — валидный идентификатор (без пробелов, спецсимволов, не начинается с цифры):console.log(user.name); // "Анна"
console.log(user.age); // 28
Используется, если ключ содержит пробелы, спецсимволы, или если имя свойства динамическое:console.log(user['name']); // "Анна"
console.log(user['age']); // 28 const prop = 'isAdmin';
console.log(user[prop]); // false
Также скобки нужны для ключей с пробелами:const person = { 'first name': 'Иван', 'last-name': 'Петров'
}; console.log(person['first name']); // "Иван"
console.log(person['last-name']); // "Петров" Используйте точечную запись, если возможно — она читаемее. Используйте скобочную, когда нужно динамическое имя свойства.
Просто присваиваем значение новому ключу:user.email = 'anna@example.com';
user['phone'] = '+7 (999) 123-45-67';
Теперь объект выглядит так:{ name: 'Анна', age: 28, isAdmin: false, email: 'anna@example.com', phone: '+7 (999) 123-45-67'
}
Оператор delete:delete user.age;
console.log(user.age); // undefined
Удаление не влияет на структуру других свойств — просто убирает пару ключ-значение.Функция может быть значением свойства — тогда она называется методом:const calculator = { a: 5, b: 3, add() { return this.a + this.b; }, multiply() { return this.a * this.b; }
}; console.log(calculator.add()); // 8
console.log(calculator.multiply()); // 15
this внутри метода ссылается на сам объект — это важно для доступа к его свойствам.Это ключевая особенность в сравнении с примитивными типами данных.Когда вы присваиваете объект переменной, вы не копируете его содержимое — вы копируете ссылку на место в памяти.const user1 = { name: 'Игорь' };
const user2 = user1; // Это не копия — это та же самая ссылка user2.name = 'Мария';
console.log(user1.name); // "Мария" — изменилось и в user1!
Это значит:
Изменение одного объекта влияет на все переменные, ссылающиеся на него.
При передаче объекта в функцию — функция может изменить его содержимое.
Чтобы избежать этого, нужно создавать копию объекта — об этом позже в разделе про распаковку.Пример опасности:function updateName(user) { user.name = 'Аноним';
} const profile = { name: 'Сергей' };
updateName(profile);
console.log(profile.name); // "Аноним" — исходный объект изменён! Всегда помните: объекты — ссылочные типы. Если вам нужна независимая копия — используйте клонирование.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/объекты.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Объекты.md</guid><pubDate>Tue, 14 Oct 2025 09:39:12 GMT</pubDate></item><item><title><![CDATA[Операторы сравнения JavaScript]]></title><description><![CDATA[Операторы сравнения позволяют проверять отношения между значениями и возвращают логическое значение — true или false. В JavaScript важно понимать разницу между нестрогим и строгим сравнением, а также то, как язык приводит типы автоматически.Операторы == (равно) и != (не равно) выполняют приведение типов перед сравнением. Это означает, что JavaScript пытается преобразовать операнды к одному типу, чтобы сделать сравнение возможным.console.log(5 == "5"); // true — строка "5" приводится к числу 5
console.log(true == 1); // true — true приводится к 1
console.log(false == 0); // true — false приводится к 0
console.log("" == 0); // true — пустая строка приводится к 0
console.log(null == undefined); // true — особое правило: null и undefined равны друг другу
console.log("0" == false); // true — "0" → 0, false → 0 → 0 == 0
console.log([] == false); // true — пустой массив → "" → 0 → false → 0
Такие поведения могут привести к скрытым багам, особенно при обработке пользовательского ввода или данных из API.
✅ Правило: Избегайте == и != в production-коде.
Операторы === (строго равно) и !== (строго не равно) не выполняют приведение типов. Сравниваются и значение, и тип.console.log(5 === "5"); // false — разные типы: число и строка
console.log(true === 1); // false — boolean и number
console.log(5 === 5); // true — одинаковые тип и значение
console.log(null === undefined); // false — разные типы
console.log("" === 0); // false — строка не равна числу
Всегда используйте === и !==, если вам нужно точное совпадение.// Хорошо
if (userInput === "yes") { ... } // Плохо
if (userInput == "yes") { ... } // Может сработать на 1, true, "1"
Эти операторы сравнивают значения по величине. При сравнении разных типов JavaScript также применяет приведение, но по другим правилам.console.log(10 &gt; 5); // true
console.log(3 &lt;= 3); // true
Строки сравниваются по символам, в лексикографическом порядке (как в словаре):console.log("apple" &lt; "banana"); // true — 'a' &lt; 'b'
console.log("Z" &lt; "a"); // true — в ASCII 'Z' (90) &lt; 'a' (97)
console.log("10" &lt; "2"); // true — потому что "1" &lt; "2", сравнение по первому символу! ❗ Важно: "10" &lt; "2" даёт true, хотя числово 10 &gt; 2.
Это частая ошибка при сравнении строковых чисел.
Приведите их к числу:console.log(Number("10") &lt; Number("2")); // false
// или проще:
console.log(+ "10" &lt; + "2"); // false
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/операторы-сравнения-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Операторы сравнения JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:11 GMT</pubDate></item><item><title><![CDATA[Замыкания]]></title><description><![CDATA[Замыкание — это когда функция запоминает и сохраняет доступ к переменным из внешней области видимости, даже после того как внешняя функция завершила свою работу.Это происходит потому, что в JavaScript каждая функция «запоминает» окружение, в котором она была создана — даже если она выполняется позже, в другом месте.Простой пример:function createUserManager() { let userCount = 0; return function() { userCount++; return `Пользователей: ${userCount}`; };
} const addUser = createUserManager(); console.log(addUser()); // "Пользователей: 1"
console.log(addUser()); // "Пользователей: 2"
console.log(addUser()); // "Пользователей: 3"
Здесь:
createUserManager создаёт переменную userCount и возвращает внутреннюю функцию
После вызова createUserManager() внешняя функция завершается — её стек должен быть очищен
Но внутренняя функция (addUser) продолжает «помнить» и использовать userCount
Это и есть замыкание: внутренняя функция замыкает на переменную из внешней области
function createThemeManager() { let currentTheme = "light"; return { getTheme() { return currentTheme; }, setTheme(theme) { currentTheme = theme; }, toggleTheme() { currentTheme = currentTheme === "light" ? "dark" : "light"; } };
} const theme = createThemeManager();
theme.setTheme("dark");
console.log(theme.getTheme()); // "dark"
theme.toggleTheme();
console.log(theme.getTheme()); // "light"
Тема хранится в замыкании — не загрязняет глобальное пространство, доступна только через контролируемые методы.function setupButtonHandler(buttonId, userId) { document.getElementById(buttonId).addEventListener("click", function() { console.log(`Кнопка ${buttonId} нажата пользователем ${userId}`); });
} setupButtonHandler("profileBtn", 456);
// При клике выведет: "Кнопка profileBtn нажата пользователем 456"
// Даже если функция setupButtonHandler уже завершилась — замыкание сохранило userId
<a data-tooltip-position="top" aria-label="Каррированные функции" data-href="Каррированные функции" href="материалы/подтемы/секция-1.-javascript/тема-№10/каррированные-функции.html" class="internal-link" target="_self" rel="noopener nofollow">Каррирование</a> — это преобразование функции, принимающей несколько аргументов, в последовательность функций, каждая из которых принимает один аргумент. Основано на замыканиях.function multiply(a) { return function(b) { return function(c) { return a * b * c; }; };
} const multiplyBy2 = multiply(2);
const multiplyBy2And5 = multiplyBy2(5);
console.log(multiplyBy2And5(3)); // 30 // Или в одну строку:
console.log(multiply(2)(5)(3)); // 30
Здесь каждая вложенная функция «запоминает» значение a, затем b, используя замыкание. Это позволяет создавать переиспользуемые частичные версии функций — например, для форматирования, валидации или настройки API-запросов.
Замыкание не создаёт копию переменной — оно ссылается на неё
Если переменная меняется — замыкание видит новое значение
Замыкания могут вызывать утечки памяти, если держат ссылки на большие объекты без необходимости Замыкания — мощный инструмент. Используйте их для инкапсуляции данных, создания приватных состояний, управления контекстом в обработчиках и реализации каррированных функций — особенно в React, Vue или чистом JavaScript без фреймворков.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/замыкания.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Замыкания.md</guid><pubDate>Tue, 14 Oct 2025 09:39:11 GMT</pubDate></item><item><title><![CDATA[Сравнение `if` и `switch`]]></title><description><![CDATA[Выбор между if и switch зависит от типа условия, которое вы проверяете. Оба инструмента решают похожие задачи, но используются в разных сценариях.Используйте if и else if, когда: Проверяете диапазоны значений if (score &gt;= 90) { grade = "A";
} else if (score &gt;= 80) { grade = "B";
} else if (score &gt;= 60) { grade = "C";
} Используете логические операции (&amp;&amp;, ||, !) if (isLoggedIn &amp;&amp; user.role === "admin" &amp;&amp; !user.banned) { showAdminPanel();
} Условия не сводятся к одному значению — например, проверка наличия данных, состояния сети, времени суток if (date.getHours() &gt;= 6 &amp;&amp; date.getHours() &lt; 12) { setMessage("Доброе утро!");
} Значения динамические или вычисляемые — switch не может работать с выражениями в case. Используйте switch, когда: Проверяете одну переменную на равенство конкретным, дискретным значениям — например, строковым ключам, числам, enum-значениям switch (notificationType) { case "info": case "success": showBanner("Сообщение", "blue"); break; case "warning": showBanner("Предупреждение", "orange"); break; case "error": showBanner("Ошибка", "red"); break;
} У вас есть перечисление возможных состояний — язык интерфейса, тип уведомления, статус заказа, режим приложения switch (appTheme) { case "light": case "dark": case "system": applyTheme(appTheme); break;
} Код должен быть структурирован и легко расширяться — добавление нового case не нарушает логику остальных веток. В современных движках JavaScript (V8, SpiderMonkey) разница в производительности между if и switch минимальна — особенно при небольшом количестве условий.
Для большого числа вариантов (например, 10+ дискретных значений) switch может быть чуть быстрее, потому что внутренне использует таблицу переходов (jump table), а не последовательные проверки.
Но в реальных веб и мобильных приложениях эта разница не имеет значения — важнее читаемость и поддерживаемость. switch лучше читается, когда вы видите список возможных значений — как меню.
if лучше читается, когда вы видите логические правила — как условия в форме.
Пример читаемого switch:switch (buttonAction) { case "save": saveData(); break; case "cancel": closeModal(); break; case "delete": confirmDelete(); break;
}
Пример читаемого if:if (isOffline &amp;&amp; hasUnsavedChanges) { showSavePrompt();
} else if (!isOffline &amp;&amp; !hasUnsavedChanges) { hideNotification();
} Используйте switch для перечислений — когда у вас есть фиксированный набор значений.
Используйте if для логики — когда нужно проверять диапазоны, комбинации, условия с &amp;&amp; или ||.
Не гонитесь за «красивым» кодом — выбирайте то, что понятнее вашей команде.
Если вы сомневаетесь — выбирайте if. Он универсален. switch — специализированный инструмент.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/сравнение-`if`-и-`switch`.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Сравнение `if` и `switch`.md</guid><pubDate>Tue, 14 Oct 2025 09:39:10 GMT</pubDate></item><item><title><![CDATA[Отправка файлов с сервера]]></title><description><![CDATA[Отправка статических файлов — HTML, CSS, JS, изображений — это основа любого веб-сервера. NodeJS позволяет отдавать их через модуль fs (file system).Это файлы, которые не генерируются динамически — они лежат на диске и просто читаются и отправляются клиенту.Пример структуры проекта:project/
├── server.js
├── index.html
├── styles/
│ └── style.css
├── scripts/
│ └── app.js
└── images/ └── logo.png
Задача сервера: При запросе / → отдать index.html При запросе /styles/style.css → отдать style.css При запросе /images/logo.png → отдать logo.png
Используем асинхронный метод fs.readFile() — он не блокирует поток выполнения.const http = require('http');
const fs = require('fs');
const path = require('path'); const server = http.createServer((req, res) =&gt; { // Преобразуем URL в путь к файлу let filePath = '.' + req.url; if (filePath === './') { filePath = './index.html'; } // Определяем MIME-тип по расширению файла const extname = path.extname(filePath); let contentType = 'text/html'; switch (extname) { case '.js': contentType = 'text/javascript'; break; case '.css': contentType = 'text/css'; break; case '.json': contentType = 'application/json'; break; case '.png': contentType = 'image/png'; break; case '.jpg': contentType = 'image/jpg'; break; case '.gif': contentType = 'image/gif'; break; } // Читаем файл fs.readFile(filePath, (error, content) =&gt; { if (error) { if (error.code === 'ENOENT') { // Файл не найден res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('&lt;h1&gt;404 Not Found&lt;/h1&gt;'); } else { // Другая ошибка (например, доступ запрещён) res.writeHead(500, { 'Content-Type': 'text/html' }); res.end('&lt;h1&gt;500 Internal Server Error&lt;/h1&gt;'); } } else { // Успешно: отправляем содержимое res.writeHead(200, { 'Content-Type': contentType }); res.end(content); } });
}); server.listen(3000);
Браузер использует Content-Type, чтобы понять, как обработать ответ:
text/html — отображает как страницу text/css — применяет как стиль text/javascript — исполняет как скрипт image/png — показывает как изображение application/json — ожидает JSON-структуру
Если Content-Type не указан или указан неверно — браузер может не загрузить CSS, не запустить JS или не показать картинку.
ENOENT — файл не найден → 404 Not Found Другие ошибки (например, нет прав на чтение) → 500 Internal Server Error
Важно: никогда не показывайте пользователю технические детали ошибок — только общие сообщения.readFileSync() — синхронный метод. Он блокирует весь сервер, пока файл не прочитан.Пример:const content = fs.readFileSync('./index.html'); // 💥 Блокирует поток!
res.end(content);
При одновременном запросе 100 пользователей — сервер на 100 мс будет «зависать» на каждом чтении. Это приведёт к полной остановке ответов.
В продакшене всегда используйте асинхронные методы: fs.readFile(), fs.promises.readFile()
Синхронные методы (readFileSync, writeFileSync) — только для инициализации, скриптов, конфигов при запуске.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/отправка-файлов-с-сервера.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/Отправка файлов с сервера.md</guid><pubDate>Tue, 14 Oct 2025 09:39:09 GMT</pubDate></item><item><title><![CDATA[Базовая работа с элементами веб страницы через JavaScript]]></title><description><![CDATA[В JavaScript для взаимодействия с HTML-элементами используются методы работы с DOM (Document Object Model). Основные способы получения элементов: document.getElementById(id) — возвращает элемент по уникальному атрибуту id.
Пример: const button = document.getElementById('submit-btn'); document.querySelector(selector) — возвращает первый элемент, соответствующий CSS-селектору.
Пример: const title = document.querySelector('h1'); или const item = document.querySelector('.item.active'); document.querySelectorAll(selector) — возвращает NodeList (массивоподобный объект) всех элементов, соответствующих селектору.
Пример: const buttons = document.querySelectorAll('button'); document.getElementsByTagName(name) — возвращает HTMLCollection элементов по тегу.
Пример: const paragraphs = document.getElementsByTagName('p'); document.getElementsByClassName(name) — возвращает HTMLCollection элементов по классу.
Пример: const items = document.getElementsByClassName('list-item'); ⚠️ Методы, возвращающие коллекции (HTMLCollection, NodeList), не являются настоящими массивами и не имеют методов массивов (например, .map(), .filter()). Для их использования можно преобразовать в массив через [...collection] или Array.from(collection).
После получения элемента можно изменять его атрибуты и содержимое: element.textContent — устанавливает или возвращает текстовое содержимое элемента (без HTML-разметки).
Пример: paragraph.textContent = 'Новый текст'; element.innerHTML — устанавливает или возвращает HTML-содержимое элемента (включая разметку).
Пример: div.innerHTML = '&lt;strong&gt;Жирный текст&lt;/strong&gt;'; element.setAttribute(name, value) — задаёт значение атрибута.
Пример: button.setAttribute('disabled', 'true'); element.getAttribute(name) — получает значение атрибута.
Пример: const type = input.getAttribute('type'); element.removeAttribute(name) — удаляет атрибут.
Пример: button.removeAttribute('disabled'); 💡 Используйте textContent для изменения текста — он безопаснее innerHTML, так как не выполняет HTML-код и защищает от XSS-атак.
Стили элемента можно менять напрямую через свойство style — оно представляет собой объект, содержащий все CSS-свойства в формате camelCase:
element.style.propertyName = 'value';
Примеры:
element.style.color = 'red';
element.style.fontSize = '20px';
element.style.backgroundColor = '#f0f0f0';
element.style.marginTop = '10px'; 🔍 Важно: CSS-свойства с дефисом (например, background-color) в JavaScript записываются в camelCase (backgroundColor).
Ограничения:
Стили, заданные через style, имеют приоритет над внешними CSS-правилами.
Нельзя установить несколько стилей одновременно — только по одному свойству.
Для сложных стилевых изменений рекомендуется использовать классы (classList):
element.classList.add('highlight');
element.classList.remove('hidden');
element.classList.toggle('active'); ✅ Использование classList предпочтительнее прямого изменения style — это позволяет отделять логику от стилей и поддерживать чистоту кода.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№3/базовая-работа-с-элементами-веб-страницы-через-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №3/Базовая работа с элементами веб страницы через JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:08 GMT</pubDate></item><item><title><![CDATA[Правила наименования переменных в JavaScript]]></title><description><![CDATA[В JavaScript как и в любом другом языке программирования существуют строгие синтаксические правила для именования переменных: Имя должно начинаться с буквы (a–z, A–Z), символа подчёркивания (_) или знака доллара ($).
✅ Разрешено: name, _count, $element
❌ Запрещено: 2name, -value, 3dModel После первого символа можно использовать буквы, цифры (0–9), _ и $.
✅ Разрешено: userName1, total_price, API_KEY
❌ Запрещено: user-name, email@domain, my variable Имена чувствительны к регистру — name, Name и NAME — это три разные переменные. Нельзя использовать зарезервированные слова языка как имена переменных:
let, const, var, function, if, else, return, class, import, export, null, true, false, this, new, while, for, break, continue, try, catch, finally, throw, switch, case, default, typeof, instanceof, in, of, async, await, yield и другие.
❌ Запрещено: let = 5;, function = "test"; Нельзя использовать ключевые слова будущих версий ECMAScript, даже если они пока не используются (например, package, interface, private, protected, public, static).
❌ Лучше избегать: class, enum, implements, module, namespace, super Хотя JavaScript позволяет многое, следование общепринятым соглашениям делает код понятным, поддерживаемым и профессиональным: Используйте camelCase для имен переменных и функций.
✅ userName, isLoading, getTotalPrice
❌ user_name, User Name, usertotalprice Для констант (которые не меняются) используйте UPPER_SNAKE_CASE.
✅ MAX_USERS, API_URL, DEFAULT_TIMEOUT Выбирайте осмысленные, описательные имена — избегайте аббревиатур и однобуквенных имён, если контекст не очевиден.
✅ numberOfItems, currentUser, isFormValid
❌ n, x, tmp, data1, arr Используйте логические имена для булевых переменных — начинайте с is, has, can, should.
✅ isVisible, hasPermission, canSubmit, isLoading Избегайте двойных отрицаний — лучше isDisabled, чем isNotEnabled. Не используйте $ в начале имени без причины — хотя $ разрешён, он часто используется в библиотеках (например, jQuery) для обозначения объектов DOM. Используйте только если это часть вашей договорённости в проекте (например, const $button = document.querySelector('#btn');). Следуйте единому стилю в команде — согласуйте стиль именования в проекте (через ESLint, Prettier или внутренний гайдлайн). Не пишите имена на кириллице — даже если JavaScript это позволяет, это снижает читаемость для международной команды и может вызвать проблемы с инструментами/редакторами. 💡 Рекомендация: «Не жалейте создавать лишнюю переменную» — лучше сделать код более читаемым через понятные имена, чем экономить на количестве строк. Например: const isEmailValid = validateEmail(userInput); // Читаемо и понятно вместо const v = validateEmail(userInput); // Неясно, что такое v ]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№2/правила-наименования-переменных-в-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №2/Правила наименования переменных в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:08 GMT</pubDate></item><item><title><![CDATA[Практические рекомендации по массивам и объектам]]></title><description><![CDATA[В реальных приложениях важно управлять состоянием предсказуемо. Мутация исходных данных — частая причина багов: один компонент меняет данные, а другой, который их использует, получает неожиданные изменения.Если вам нужно изменить данные, но сохранить оригинал — создавайте копию, а не меняйте исходный объект.❌ Плохо — мутация:const tasks = ['Почитать', 'Написать код']; function addTask(task) { tasks.push(task); // Изменяем исходный массив!
} addTask('Сделать уборку');
console.log(tasks); // ['Почитать', 'Написать код', 'Сделать уборку'] — оригинал изменён
✅ Хорошо — создание копии:const tasks = ['Почитать', 'Написать код']; function addTask(tasksList, task) { return [...tasksList, task]; // Новый массив, оригинал не тронут
} const updatedTasks = addTask(tasks, 'Сделать уборку');
console.log(tasks); // ['Почитать', 'Написать код'] — не изменился
console.log(updatedTasks); // ['Почитать', 'Написать код', 'Сделать уборку']
То же правило для объектов:❌ Плохо:const user = { name: 'Анна', theme: 'light' }; function updateTheme(user, theme) { user.theme = theme; // Мутируем исходный объект return user;
}
✅ Хорошо:function updateTheme(user, theme) { return { ...user, theme }; // Новый объект с обновлённым свойством
} const newUser = updateTheme(user, 'dark');
console.log(user.theme); // "light" — не изменился
console.log(newUser.theme); // "dark"
Копирование с помощью ..., Array.from(), Object.assign() — это поверхностное клонирование. Оно копирует только первый уровень вложенности.Пример:const original = { name: 'Анна', tasks: ['Задача 1', 'Задача 2']
}; const copy = { ...original }; copy.tasks.push('Задача 3'); console.log(original.tasks); // ['Задача 1', 'Задача 2', 'Задача 3'] — изменился!
Почему? Потому что tasks — это массив, и он передаётся по ссылке. Ссылка скопировалась, но сам массив — один и тот же.Эти методы безопасны для простых данных. Но если в объекте есть вложенные массивы или объекты — они остаются по ссылке.
Данные не имеют глубокой вложенности.
Вы работаете с плоскими структурами: профиль пользователя, настройки, простые задачи.
Вы используете библиотеки вроде Redux, Zustand, где ожидается неизменяемость.
Если нужно скопировать вложенные структуры полностью — используйте библиотеки (например, lodash.cloneDeep) или специальные методы. В базовом JavaScript это сложно и неэффективно.
Не используйте JSON.parse(JSON.stringify(obj)) для глубокого клонирования — он ломает функции, undefined, Date, Map, Set, и циклические ссылки.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/практические-рекомендации-по-массивам-и-объектам.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Практические рекомендации по массивам и объектам.md</guid><pubDate>Tue, 14 Oct 2025 09:39:08 GMT</pubDate></item><item><title><![CDATA[Рекомендации по использованию Git]]></title><description><![CDATA[Делайте коммиты часто — не ждите, пока «всё будет готово».
Маленький коммит — это безопасный снимок состояния.
Если что-то сломалось — вы легко найдёте, где именно.Пример плохой практики:
Вы работаете над экраном входа 3 дня — меняете App.js, LoginScreen.js, api.js, styles.tsx — и только тогда делаете один коммит:
"finished login" — непонятно, что изменилось.Пример хорошей практики: Добавил кнопку входа → feat: добавил кнопку входа с анимацией Подключил API для авторизации → feat: подключил POST /login к серверу Исправил баг с фокусом поля ввода → fix: исправил фокус на поле email в iOS
Каждый коммит — отдельная логическая единица.
Легче откатиться, легче ревью, легче находить баги.Сообщение коммита — это история вашего кода.
Оно должно отвечать на вопрос: «Что изменилось и зачем?»Хорошее сообщение:
fix: убрал дублирование стилей в Button и PrimaryButtonПлохое сообщение:
fixed stuffИспользуйте формат:&lt;тип&gt;: &lt;краткое описание&gt;
Типы (по соглашению Conventional Commits):
feat: — новая функция
fix: — исправление бага
docs: — изменения в документации
chore: — технические задачи (обновление зависимостей, настройка сборки)
refactor: — рефакторинг без изменения поведения
Пример:git commit -m "feat: добавил экран восстановления пароля"
git commit -m "fix: кнопка 'Войти' не реагировала на тач в Android"
git commit -m "chore: обновил expo SDK до версии 50" Не пишите «исправил ошибку», «сделал лучше» — это неинформативно.
Пишите что было сделано, где, и если важно — почему.
Никогда не работайте напрямую в main.
Всегда создавайте ветку для каждой задачи.Пример:git switch main
git pull
git switch -c feature/login-screen
# ... работаю над экраном входа ...
git add .
git commit -m "feat: добавил экран входа с валидацией"
git push origin feature/login-screen
Затем на GitHub создаёте Pull Request (или Merge Request).
После ревью — объединяете с main.Это даёт:
Безопасность: основной код не ломается.
Чёткость: каждая ветка — одна задача.
Коллаборацию: другие могут видеть вашу работу, комментировать, предлагать правки.
Возможность отложить: если задача не готова — вы можете закрыть ветку без влияния на проект. Если вы работаете над двумя задачами одновременно — две ветки.
Если вы исправляете баг — ветка bugfix/....
Если вы экспериментируете — ветка experiment/....
Если вы добавляете новые фичи — ветка feature/.... Ветки — это ваша страховка.
Они бесплатны. Они не занимают места.
Используйте их всегда.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/рекомендации-по-использованию-git.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Рекомендации по использованию Git.md</guid><pubDate>Tue, 14 Oct 2025 09:39:07 GMT</pubDate></item><item><title><![CDATA[Арифметические операторы JavaScript]]></title><description><![CDATA[Арифметические операторы — это основные инструменты для выполнения математических вычислений в JavaScript. Они работают с числами и возвращают числовые результаты.Пример использования остатка: const isEven = number =&gt; number % 2 === 0;
console.log(isEven(4)); // true
console.log(isEven(7)); // false
Оператор ** возводит первое число в степень, указанную вторым:console.log(2 ** 4); // 16 (2 × 2 × 2 × 2)
console.log(9 ** 0.5); // 3 (квадратный корень из 9)
Это удобно для расчётов: например, при вычислении площади квадрата или сложных процентов.Унарный плюс + преобразует значение в число:console.log(+"42"); // 42 (строка → число)
console.log(+"hello"); // NaN (непреводимая строка)
console.log(+true); // 1
console.log(+false); // 0
Унарный минус - меняет знак числа:console.log(-5); // -5
console.log(-(3 + 2)); // -5
console.log(-"10"); // -10 (сначала приведение к числу, потом отрицание)
Инкремент ++ увеличивает значение на 1, декремент -- уменьшает на 1.Различают две формы:Сначала изменяет значение, потом возвращает его:let a = 5;
console.log(++a); // 6 — сначала прибавили, потом вернули
console.log(a); // 6
Сначала возвращает текущее значение, потом изменяет:let b = 5;
console.log(b++); // 5 — вернули старое значение
console.log(b); // 6 — теперь уже увеличено 💡 Важно: в циклах и выражениях разница между i++ и ++i может привести к ошибкам, если не учитывать порядок.
JavaScript имеет специальные числовые значения, которые появляются при некорректных операциях.Появляется, когда операция не может быть выполнена:console.log(0 / 0); // NaN
console.log("abc" * 2); // NaN
console.log(NaN + 5); // NaN
console.log(NaN === NaN); // false — важно! NaN не равен самому себе
Для проверки на NaN используйте Number.isNaN():console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("hello")); // false
Получается при делении на ноль или при переполнении:console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Number.MAX_VALUE * 2); // Infinity console.log(Infinity + 1); // Infinity
console.log(Infinity - Infinity); // NaN ⚠️ Не используйте == Infinity для проверки — лучше применять isFinite(): console.log(isFinite(1000)); // true
console.log(isFinite(Infinity)); // false ]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/арифметические-операторы-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Арифметические операторы JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:07 GMT</pubDate></item><item><title><![CDATA[Pasted image 20250912212810]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912212810.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912212810.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912212810.png</guid><pubDate>Tue, 14 Oct 2025 09:39:06 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20250912214649]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912214649.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912214649.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912214649.png</guid><pubDate>Tue, 14 Oct 2025 09:39:06 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Работа с ветками Git]]></title><description><![CDATA[Показывает все ветки в репозитории. Текущая ветка отмечена звёздочкой *.git branch
Пример вывода: main
* feature/login-screen bugfix/button-color
Здесь вы находитесь в ветке feature/login-screen.Чтобы увидеть только удалённые ветки (на сервере):git branch -r
Чтобы увидеть все ветки — локальные и удалённые:git branch -a
Переключает рабочую директорию на указанную ветку.
Изменения в файлах сохраняются, если они не конфликтуют.git checkout feature/login-screen
Если ветка ещё не существует локально, но есть на сервере — можно создать и переключиться сразу:git checkout feature/login-screen
# если ветка не найдена локально — выдаст ошибку
Чтобы создать новую ветку и сразу переключиться:git checkout -b feature/auth-google checkout — многофункциональная команда: она может переключать ветки, восстанавливать файлы, и даже переходить к коммитам. Это может запутать новичков.
Появилась в Git 2.23 как более понятная альтернатива для переключения веток.
Работает только с ветками — меньше шансов ошибиться.git switch feature/login-screen
Создать новую ветку и переключиться:git switch -c feature/auth-google ✅ Рекомендуется использовать git switch для переключения между ветками.
Оставьте git checkout только для восстановления файлов или перехода к старым коммитам.
Объединяет изменения из одной ветки в текущую.
Работает только после переключения на целевую ветку.Пример: вы закончили работу в feature/login-screen и хотите добавить изменения в main.git switch main
git merge feature/login-screen
Если изменений нет в конфликте — Git сделает быстрое слияние (fast-forward).
Если в main были новые коммиты — Git создаст отдельный коммит слияния.Пример вывода после успешного слияния:Updating a1b2c3d..f9e8d7c
Fast-forward src/screens/Login.js | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/screens/Login.js
Если возникает конфликт — Git остановится и попросит вас разрешить его вручную.
Файлы с конфликтами будут помечены специальными маркерами:&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD
&lt;Text&gt;Войти&lt;/Text&gt;
=======
&lt;Text style={styles.bold}&gt;Войти&lt;/Text&gt;
&gt;&gt;&gt;&gt;&gt;&gt;&gt; feature/login-screen
Разрешите конфликт — удалите маркеры, оставьте нужный код — затем:git add src/components/Button.js
git commit ⚠️ Не делайте слияние в main с незавершёнными или неотлаженными фичами.
Всегда тестируйте ветку перед слиянием.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/работа-с-ветками-git.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Работа с ветками Git.md</guid><pubDate>Tue, 14 Oct 2025 09:39:05 GMT</pubDate></item><item><title><![CDATA[Установка и базовое использование Node.js]]></title><description><![CDATA[Node.js можно установить двумя основными способами. Первый — через официальный установщик с сайта nodejs.org: он подходит для новичков и автоматически настраивает Node.js и npm (советую вам использовать этот способ). Второй — через nvm (Node Version Manager): это инструмент для управления несколькими версиями Node.js на одном компьютере, что особенно полезно при работе с разными проектами. На macOS и Linux nvm устанавливается через терминал командой curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash, на Windows — через nvm-windows. После установки nvm можно легко переключаться между версиями: nvm install 20, nvm use 20.После установки важно проверить, что Node.js и npm (менеджер пакетов) работают корректно. В терминале введите node -v — вы увидите текущую версию Node.js (например, v20.12.0). Затем введите npm -v — вы увидите версию npm (например, 10.5.0). Если обе команды возвращают номера версий — среда готова к работе. Если нет — перезагрузите терминал или проверьте путь установки.Чтобы запустить JavaScript-файл в Node.js, создайте файл с расширением .js (например, app.js), напишите в нём любой код — например, console.log('Привет, Node.js!'); — и сохраните. В терминале перейдите в папку с файлом и выполните команду node app.js. Node.js прочитает файл, выполнит его содержимое и выведет результат в консоль. Это простейший способ тестировать серверный код, не используя браузер.Так-же, для вас будет проще запускать его сразу из редактора кода.Нажимаем на f5 находясь в нужном файле.
В первый запуск у вас спросят выбрать способ дебагера, выбираем Node.js.
<img alt="Pasted image 20240928221620.png" src="материалы/файлы/pasted-image-20240928221620.png" target="_self">ПКМ по файлу.<br><img alt="Pasted image 20240928222139.png" src="материалы/файлы/pasted-image-20240928222139.png" target="_self">нажимаем кнопку Run "название скрипта"Дальше можем просто нажимать на кнопку "запуск"<br>
<img alt="Pasted image 20240928222237.png" src="материалы/файлы/pasted-image-20240928222237.png" target="_self">REPL (Read-Eval-Print Loop) — это интерактивная оболочка Node.js, которая позволяет сразу писать и выполнять JavaScript-код в терминале. Чтобы запустить её, введите node без аргументов. Вы увидите приглашение &gt; — теперь можете вводить выражения: 2 + 2, const name = 'Миша'; console.log(name);. Результат выводится мгновенно. Для выхода из REPL нажмите Ctrl + C дважды или введите .exit. REPL идеален для быстрой проверки синтаксиса, экспериментов с API или отладки небольших фрагментов кода.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№4/установка-и-базовое-использование-node.js.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №4/Установка и базовое использование Node.js.md</guid><pubDate>Tue, 14 Oct 2025 09:39:05 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Цепочки `else if`]]></title><description><![CDATA[Цепочка else if` позволяет проверить несколько условий последовательно — и выполнить только первый подходящий блок.Синтаксис:if (условие1) { // выполнится, если условие1 истинно
} else if (условие2) { // выполнится, если условие1 ложно, а условие2 истинно
} else if (условие3) { // выполнится, если условие1 и условие2 ложны, а условие3 истинно
} else { // выполнится, если все условия ложны (необязательно)
}
Важно: как только одно из условий становится истинным — выполняется соответствующий блок, и все остальные условия не проверяются.const userRole = "moderator"; if (userRole === "admin") { showAdminPanel();
} else if (userRole === "moderator") { showModeratorPanel();
} else if (userRole === "user") { showUserPanel();
} else { showGuestPanel();
}
Здесь:
Если роль — "admin" — показывается панель администратора, и проверка останавливается.
Если роль — "moderator" — показывается панель модератора, даже если бы были другие условия, они не проверяются.
Если ни одно из известных значений не подошло — показывается панель гостя.
Представьте, что вы перепутали порядок:if (userRole === "user") { showUserPanel();
} else if (userRole === "moderator") { showModeratorPanel();
} else if (userRole === "admin") { showAdminPanel();
}
Если пользователь имеет роль "admin", он попадёт в блок "user", потому что "admin" содержит "user" как подстроку? Нет — в данном случае сравнение строгое (===), так что не сработает. Но если бы вы использовали indexOf или includes, ошибки были бы критичны.Более реальный пример с ошибкой:const score = 95; if (score &gt;= 60) { grade = "C"; // Всегда сработает первым!
} else if (score &gt;= 80) { grade = "B";
} else if (score &gt;= 90) { grade = "A";
}
Здесь оценка 95 получит "C", потому что первое условие score &gt;= 60 уже истинно. Правильно:if (score &gt;= 90) { grade = "A";
} else if (score &gt;= 80) { grade = "B";
} else if (score &gt;= 60) { grade = "C";
} else { grade = "F";
}
const themeSetting = "dark"; if (themeSetting === "light") { document.body.classList.remove("dark-theme"); document.body.classList.add("light-theme");
} else if (themeSetting === "dark") { document.body.classList.remove("light-theme"); document.body.classList.add("dark-theme");
} else if (themeSetting === "system") { if (window.matchMedia("(prefers-color-scheme: dark)").matches) { document.body.classList.add("dark-theme"); } else { document.body.classList.add("light-theme"); }
} else { // значение неизвестно — используем по умолчанию document.body.classList.add("light-theme");
}
Здесь три явных варианта и один запасной — логика понятна, читаема, и порядок условий критичен.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/цепочки-`else-if`.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Цепочки `else if`.md</guid><pubDate>Tue, 14 Oct 2025 09:39:04 GMT</pubDate></item><item><title><![CDATA[Маршрутизация в NodeJS]]></title><description><![CDATA[Маршрутизация — это сопоставление URL-путей с соответствующими обработчиками. Каждый запрос приходит с определённым путём (например, /, /about, /api/users) — сервер должен понять, какой код запустить для каждого из них.Встроенного роутера в NodeJS нет — его нужно писать вручную. Для этого используется свойство req.url, содержащее путь запроса.Пример:const http = require('http'); const server = http.createServer((req, res) =&gt; { const path = req.url; if (path === '/') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('&lt;h1&gt;Главная страница&lt;/h1&gt;'); } else if (path === '/about') { res.writeHead(200, { 'Content-Type': 'text/html' }); res.end('&lt;h1&gt;О нас&lt;/h1&gt;'); } else if (path === '/api/users') { res.writeHead(200, { 'Content-Type': 'application/json' }); res.end(JSON.stringify([{ id: 1, name: 'Анна' }])); } else { res.writeHead(404, { 'Content-Type': 'text/html' }); res.end('&lt;h1&gt;404 Not Found&lt;/h1&gt;'); }
}); server.listen(3000);
Запросы:
GET / → главная страница GET /about → страница "О нас" GET /api/users → список пользователей в JSON GET /anything-else → 404 Нет зависимостей — работает на чистом NodeJS Прозрачно: видно, что происходит под капотом Подходит для обучения и простых серверов Полный контроль над логикой С ростом количества маршрутов код становится громоздким Нет поддержки параметров: /user/123, /post/:id — нужно писать регулярки или split('/') Нет методов (GET/POST): нужно проверять req.method отдельно Нет валидации, обработки ошибок, middleware Сложно масштабировать — не подходит для реальных проектов
В реальных проектах маршрутизацию не пишут вручную. Используют фреймворки, например Express.js, где всё выглядит так:app.get('/', (req, res) =&gt; res.send('Главная'));
app.get('/about', (req, res) =&gt; res.send('О нас'));
app.get('/api/users', (req, res) =&gt; res.json(users));
app.post('/api/users', (req, res) =&gt; { /* создать пользователя */ });
Но важно понимать: Express просто упрощает то, что вы уже умеете делать через http.
Понимание базовой логики (req.url, req.method, res.end) — фундамент. Без него фреймворки — чёрный ящик.
Маршрутизация — это не про библиотеки. Это про то, как сервер решает: «Что делать, когда пришёл запрос по этому пути?» — и это вы должны уметь делать вручную. Когда мы начнем изучать React - мы так-же затронем тему маршрутизации, и не смотря на то что это будет выполняться на стороне клиента - логика останется той же.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/маршрутизация-в-nodejs.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/Маршрутизация в NodeJS.md</guid><pubDate>Tue, 14 Oct 2025 09:39:04 GMT</pubDate></item><item><title><![CDATA[Работа с удалёнными репозиториями]]></title><description><![CDATA[Чтобы отправить локальный репозиторий на GitHub, нужно связать его с удалённым.git remote add origin https://github.com/username/MyMobileApp.git origin — это имя, которое вы даёте удалённому репозиторию (по умолчанию так называют главный удалённый репозиторий).
URL берётся из вашего репозитория на GitHub — кнопка «Code» → «HTTPS».
Проверить, что привязка прошла:git remote -v
Вывод:origin https://github.com/username/MyMobileApp.git (fetch)
origin https://github.com/username/MyMobileApp.git (push) Не используйте git remote add origin если репозиторий уже имеет удалённую связь — это вызовет ошибку.
Отправляет ваши локальные коммиты в удалённый репозиторий.git push origin main
Первый раз, когда вы отправляете ветку — Git может попросить аутентификацию (логин/пароль или токен).
На GitHub с 2021 года пароли не работают — используйте Personal Access Token (PAT) вместо пароля.
Если вы работаете с веткой feature/login-screen:git push origin feature/login-screen
После первого push можно использовать короткую команду:git push
Git запомнит, куда отправлять изменения для текущей ветки.Загружает изменения с удалённого репозитория и объединяет их с вашей текущей веткой.git pull origin main
Это эквивалент двух команд:git fetch origin main
git merge origin/main
Пример:
Коллега добавил новый экран в main. Вы выполняете:git switch main
git pull
Теперь у вас есть последние изменения — даже если вы работали офлайн.
⚠️ Если у вас есть незакоммиченные изменения — pull может сломаться.
В этом случае сначала сделайте git stash, потом pull, потом git stash pop.
Создаёт локальную копию удалённого репозитория — со всей историей, ветками и файлами.git clone https://github.com/username/MyMobileApp.git
После этой команды:
Создаётся папка MyMobileApp/
Внутри — все файлы, ветки, история коммитов
Автоматически создаётся связь origin с исходным репозиторием
Пример:
Вы присоединяетесь к команде. Вам дают ссылку на репозиторий — вы клонируете его и сразу можете работать:cd MyMobileApp
npm install
npx expo start Используйте git clone только при начале работы над проектом.
Для обновления существующего репозитория — используйте git pull.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/работа-с-удалёнными-репозиториями.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Работа с удалёнными репозиториями.md</guid><pubDate>Tue, 14 Oct 2025 09:39:03 GMT</pubDate></item><item><title><![CDATA[Вложенные структуры]]></title><description><![CDATA[Вложенные структуры — это когда один тип данных содержит другой: массив внутри объекта, объект внутри массива, или даже объект внутри массива внутри другого объекта. Это основа для представления реальных данных в приложениях: список задач, профили пользователей с контактами, ответы API.Часто используется для хранения списков, связанных с сущностью.Пример: профиль пользователя с его задачами:const user = { name: 'Иван', email: 'ivan@example.com', tasks: [ 'Починить свет', 'Записаться к врачу', 'Написать отчёт' ]
};
Доступ к элементам:console.log(user.tasks[0]); // "Починить свет" // Добавить новую задачу
user.tasks.push('Позвонить маме');
Когда каждый элемент массива — это сложная сущность с несколькими полями.Пример: список задач с метаданными:const tasks = [ { id: 1, title: 'Починить свет', completed: false, priority: 'high' }, { id: 2, title: 'Записаться к врачу', completed: true, priority: 'medium' }, { id: 3, title: 'Написать отчёт', completed: false, priority: 'low' }
];
Такой формат — стандарт для API, баз данных, локального хранилища.Доступ к данным:console.log(tasks[0].title); // "Починить свет"
console.log(tasks[1].completed); // true
Перебор:for (const task of tasks) { if (!task.completed) { console.log(`Невыполнено: ${task.title}`); }
}
Это базовый шаблон, который вы будете встречать повсеместно — в Todo-приложениях, CRM, админках.const todoList = [ { title: 'Сделать уроки', completed: false }, { title: 'Купить хлеб', completed: true }, { title: 'Позвонить коллеге', completed: false }
];
Как обновить статус задачи:const index = 0;
todoList[index].completed = true;
Как отфильтровать невыполненные:const incomplete = todoList.filter(task =&gt; !task.completed);
Как добавить новую:todoList.push({ title: 'Убраться в комнате', completed: false });
Вложенные структуры позволяют:
Описывать реальные сущности (пользователь → задачи → подзадачи)
Структурировать данные для хранения в JSON
Легко передавать их через API (REST, GraphQL)
Удобно отображать в интерфейсе (например, список задач в списке React) Всегда структурируйте данные так, чтобы их было легко читать, изменять и передавать. Вложенные объекты и массивы — основа этого подхода.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/вложенные-структуры.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Вложенные структуры.md</guid><pubDate>Tue, 14 Oct 2025 09:39:02 GMT</pubDate></item><item><title><![CDATA[Pasted image 20250912214653]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20250912214653.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20250912214653.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20250912214653.png</guid><pubDate>Tue, 14 Oct 2025 09:39:02 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Циклы и производительность]]></title><description><![CDATA[Производительность циклов критична в JavaScript — особенно при обработке больших списков, частых обновлений или ресурсоёмких операций. Даже небольшая неоптимизированная операция внутри цикла может замедлить выполнение скрипта.Любая операция, которая не зависит от итерации, не должна выполняться на каждой итерации.const items = getLargeItemList(); // 10 000 элементов for (let i = 0; i &lt; items.length; i++) { // items.length вызывается 10 000 раз — даже если массив не меняется processItem(items[i]);
}
items.length — это свойство. В JavaScript оно вычисляется каждый раз, даже если массив статичен. Это лишняя нагрузка.const items = getLargeItemList();
const length = items.length; // вычисляем один раз for (let i = 0; i &lt; length; i++) { processItem(items[i]);
}
Теперь length — это просто число, и его не нужно пересчитывать.for (let item of items) { if (item.name.toLowerCase().includes(searchTerm.toLowerCase())) { //toLowerCase() вызывается дважды на каждой итерации result.push(item); }
}
Каждый вызов toLowerCase() — это новая строка, которая создаётся и сравнивается. Это лишние выделения памяти и вычисления.const lowerSearchTerm = searchTerm.toLowerCase(); for (let item of items) { if (item.name.toLowerCase().includes(lowerSearchTerm)) { result.push(item); }
} Избегайте сложных вычислений внутри цикла: математика, регулярные выражения, вызовы JSON.parse, querySelector.
Выносите константы за пределы цикла: например, Math.PI, config.threshold, RegExp-шаблоны.
Не модифицируйте массив, который перебираете — это может вызвать неожиданное поведение, особенно при использовании for...of.
Используйте for...of вместо for с индексами, если вам не нужны индексы — меньше кода, меньше рисков. Всё, что не меняется на каждой итерации — выносите за цикл.
Всё, что влияет на производительность (вычисления, вызовы функций) — минимизируйте внутри цикла.
Оптимизация циклов напрямую влияет на скорость выполнения скрипта и отзывчивость приложения.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/циклы-и-производительность.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Циклы и производительность.md</guid><pubDate>Tue, 14 Oct 2025 09:39:02 GMT</pubDate></item><item><title><![CDATA[Практические последствия (var)]]></title><description><![CDATA[var устарел, потому что его поведение непредсказуемо и ведёт к ошибкам, которые сложно отловить. Нет блочной области видимости
Переменные var видны во всей функции, даже если объявлены внутри if или for:
function test() { if (true) { var x = 10; } console.log(x); // 10 — не ошибка, хотя x объявлена внутри if
} Это нарушает ожидания: переменная должна быть локальной для блока, но var делает её функциональной. Поднятие (hoisting) без инициализации
var поднимается в начало функции, но инициализируется значением undefined:
console.log(y); // undefined — не ошибка!
var y = 5; Это может скрыть ошибки: вы используете переменную до её объявления — и ничего не падает. Можно переобъявить
var позволяет объявить одну и ту же переменную несколько раз — без ошибки:
var name = "Анна";
var name = "Иван"; // перезапись — без предупреждения
console.log(name); // "Иван" Это легко приводит к случайной потере данных. let — для переменных, которые меняются.
Блочная область видимости. Нельзя переобъявить в одной области.
let count = 0;
count = 1; // ок
let count = 2; // ошибка: Identifier 'count' has already been declared const — для констант и значений, которые не должны меняться.
Обязательно инициализировать при объявлении.
Не позволяет переприсвоить, но позволяет менять свойства объектов и элементы массивов.
const user = { id: 1 };
user.id = 2; // ок — меняем свойство
user = { id: 3 }; // ошибка — нельзя переприсвоить Всегда используйте let и const — они предсказуемы, безопасны и соответствуют современным стандартам.
Избегайте глобальных переменных — они конфликтуют между файлами, усложняют отладку и ломают модульность.
Объявляйте переменные как можно глубже — в том блоке, где они реально нужны.
Используйте const по умолчанию — если значение не меняется.
Только если нужно переприсвоить — используйте let. Современные инструменты (ESLint, TypeScript, Babel) и стандарты (Airbnb, Google) запрещают var в новом коде.
Использование let и const — не вопрос стиля, а вопрос надёжности.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/практические-последствия-(var).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Практические последствия (var).md</guid><pubDate>Tue, 14 Oct 2025 09:39:02 GMT</pubDate></item><item><title><![CDATA[Оператор rest]]></title><description><![CDATA[Оператор rest (...) — это синтаксис, который собирает несколько элементов в один массив или объект. Он противоположен spread: spread раскрывает, rest собирает.Используется для сбора всех переданных аргументов, которые не были явно описаны в списке параметров.function sum(...numbers) { return numbers.reduce((acc, n) =&gt; acc + n, 0);
} console.log(sum(1, 2, 3)); // 6
console.log(sum(10, 20, 30, 40)); // 100
Здесь numbers — это массив, содержащий все аргументы, переданные в функцию.
...args — общепринятое имя, но можно использовать любое: ...values, ...items.
Полезно, когда количество аргументов неизвестно заранее — например, при обработке пользовательского ввода или API с динамическими параметрами.Позволяет извлечь первые элементы, а остальные собрать в отдельный массив.const colors = ['красный', 'зелёный', 'синий', 'жёлтый']; const [first, second, ...others] = colors; console.log(first); // "красный"
console.log(second); // "зелёный"
console.log(others); // ["синий", "жёлтый"]
Можно пропустить элементы:const [, , third, ...rest] = colors;
console.log(third); // "синий"
console.log(rest); // ["жёлтый"]
Это удобно, когда нужно работать с началом массива, а остальное — передать дальше или игнорировать.Извлекает конкретные свойства, а остальные собирает в новый объект.const user = { name: 'Анна', age: 28, email: 'anna@example.com', role: 'user'
}; const { name, role, ...profile } = user; console.log(name); // "Анна"
console.log(role); // "user"
console.log(profile); // { age: 28, email: 'anna@example.com' }
Часто используется в React для передачи «оставшихся» пропсов:function Button({ variant, ...rest }) { return &lt;button className={variant} {...rest} /&gt;;
}
Здесь variant обрабатывается отдельно, а остальные пропсы (onClick, disabled и т.д.) передаются прямо в &lt;button&gt;.Один и тот же синтаксис ... — но смысл зависит от контекста:
В объявлении (параметры функции, деструктуризация) — это rest.
В выражении (присваивание, вызов функции) — это spread.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/оператор-rest.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Оператор rest.md</guid><pubDate>Tue, 14 Oct 2025 09:39:01 GMT</pubDate></item><item><title><![CDATA[Тернарный оператор]]></title><description><![CDATA[Тернарный оператор ? : — это краткая форма if else, используемая для присваивания значения в зависимости от условия.Синтаксис:условие ? выражение1 : выражение2
Если условие истинно — возвращается выражение1, иначе — выражение2.const isLoggedIn = true;
const buttonText = isLoggedIn ? "Выйти" : "Войти";
button.textContent = buttonText;
Здесь вместо:let buttonText;
if (isLoggedIn) { buttonText = "Выйти";
} else { buttonText = "Войти";
}
Мы пишем одну строку — чище, короче, удобнее для присваивания.const hasAvatar = user.avatarUrl !== null;
const avatarSrc = hasAvatar ? user.avatarUrl : "/images/default-avatar.png";
avatarImage.src = avatarSrc;
const count = 5;
const message = count === 1 ? "1 новое сообщение" : `${count} новых сообщений`;
notification.textContent = message; Краткость: идеален для простых условий, особенно при присваивании.
Читаемость в простых случаях: сразу видно, что значение зависит от условия.
Удобен в шаблонах, функциях, JSX (в React), где нельзя использовать блоки if. Не подходит для сложной логики. Например:
// ПЛОХО — не читаемо и сложно отлаживать
const result = condition1 ? (condition2 ? (condition3 ? "A" : "B") : "C") : (condition4 ? "D" : "E");
Такой код трудно понять и поддерживать. Лучше использовать if else.
Нельзя выполнять несколько действий внутри тернарного оператора:
// НЕ РАБОТАЕТ так, как ожидается
isLoggedIn ? console.log("Вход выполнен"), openDashboard() : redirectToLogin();
Здесь console.log и openDashboard() не будут выполнены как блок. Для нескольких действий используйте if.✅ Используйте тернарный оператор, когда:
Вы присваиваете значение переменной.
Условие простое — одно сравнение, один оператор.
Код должен быть компактным и понятным.
❌ Не используйте, когда:
Нужно выполнить несколько действий.
Условие сложное (с логическими операторами &amp;&amp;, ||, несколькими вложенными).
Вы хотите повысить читаемость для команды — лучше if else.
Тернарный оператор — инструмент для простых решений. Не превращайте его в замену if else.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/тернарный-оператор.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Тернарный оператор.md</guid><pubDate>Tue, 14 Oct 2025 09:39:01 GMT</pubDate></item><item><title><![CDATA[Прерывание и пропуск итераций]]></title><description><![CDATA[Без них цикл всегда выполняет все итерации до завершения условия. Но в реальных приложениях часто нужно:
Остановить цикл, если найден нужный элемент (например, пользователь найден).
Пропустить некорректные данные (например, пустой товар в списке).
Избежать лишних вычислений — это повышает производительность и предсказуемость.
Команда break немедленно завершает цикл, даже если условие ещё истинно.const users = [ { id: 1, name: "Анна" }, { id: 2, name: "Иван" }, { id: 3, name: "Мария" }
]; let foundUser = null; for (let user of users) { if (user.id === 2) { foundUser = user; break; // Нашли — выходим, дальше не ищем }
} console.log(foundUser); // { id: 2, name: "Иван" }
Без break цикл продолжил бы перебирать остальных пользователей — хотя ответ уже найден.Команда continue пропускает остаток текущей итерации и переходит к следующей.const products = [ "Ноутбук", "", "Телефон", null, "Наушники"
]; for (let product of products) { if (!product) { continue; // Пропускаем пустые и null } console.log("Товар: " + product);
}
Вывод:Товар: Ноутбук
Товар: Телефон
Товар: Наушники
Пустые значения ("", null) игнорируются — цикл не выводит их, но не останавливается.При загрузке списка сообщений из API:for (let message of messages) { if (!message.text) { continue; // Пропускаем пустые сообщения } if (message.isDeleted) { break; // Остановить загрузку, если встретили удалённое — дальше не нужно } renderMessage(message);
} break и continue работают только с ближайшим внешним циклом.
Вложенные циклы: break выйдет только из внутреннего.
Используйте их для улучшения читаемости — не для обхода логики, а для оптимизации. Используйте break, когда найдено нужное и дальнейший перебор не нужен.
Используйте continue, когда текущий элемент не подходит и его нужно пропустить.
Это делает код эффективнее и понятнее.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/прерывание-и-пропуск-итераций.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Прерывание и пропуск итераций.md</guid><pubDate>Tue, 14 Oct 2025 09:39:01 GMT</pubDate></item><item><title><![CDATA[Основы сервера на NodeJS]]></title><description><![CDATA[NodeJS позволяет создавать серверы без внешних зависимостей — с помощью встроенного модуля http.Для запуска сервера импортируем модуль http и вызываем createServer(), который принимает функцию обработчика запросов:const http = require('http'); const server = http.createServer((req, res) =&gt; { // req — объект запроса от клиента // res — объект ответа, который мы отправляем обратно
}); server.listen(3000, () =&gt; { console.log('Сервер запущен на http://localhost:3000');
});
Запускаем скрипт — сервер ждёт подключений на порту 3000.Каждый раз, когда браузер или приложение делает запрос (например, открывает http://localhost:3000), вызывается функция-обработчик. В неё передаются два объекта:
req — запрос от клиента. Содержит URL, метод (GET/POST), заголовки.
res — ответ, который сервер отправляет обратно. Используется для отправки данных и установки статуса.
Чтобы ответить клиенту, используем методы res.writeHead() и res.end().
res.writeHead(statusCode, headers) — устанавливает статус и заголовки ответа.
res.end(content) — отправляет тело ответа и завершает соединение.
Пример: отправка текста:const http = require('http'); const server = http.createServer((req, res) =&gt; { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello World');
}); server.listen(3000, () =&gt; { console.log('Сервер запущен на http://localhost:3000');
});
Что происходит:
Клиент заходит на http://localhost:3000
Сервер получает запрос
Отправляет заголовок: статус 200 (OK), тип содержимого — текст
Отправляет тело: "Hello World"
Закрывает соединение
Открываем браузер — видим просто текст: Hello World.
Важно: если не вызвать res.end(), соединение останется висеть — клиент будет ждать ответа "бесконечно". Также важно указывать Content-Type. Без него браузер может неправильно интерпретировать ответ (например, отправить JSON как текст, и он не распарсится).
Пример с JSON:res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ message: 'Привет', status: 'ok' }));
Это — основа любого сервера на NodeJS. Всё, что сложнее (маршрутизация, файлы, API), строится на этих же принципах.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/основы-сервера-на-nodejs.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/Основы сервера на NodeJS.md</guid><pubDate>Tue, 14 Oct 2025 09:39:01 GMT</pubDate></item><item><title><![CDATA[Базовое понимание синтаксиса JavaScript]]></title><description><![CDATA[В рамках данной темы рассматриваются только базовые элементы синтаксиса JavaScript, необходимые для начала практической работы. Полный объём синтаксических конструкций — от операторов и структур управления до модулей, классов, асинхронности и деструктуризации — будет изучаться последовательно в последующих разделах курса. Настоящая часть служит фундаментом для понимания структуры кода, а не исчерпывающим руководством по языку.Комментарии не влияют на выполнение кода и предназначены исключительно для повышения читаемости и документирования.JavaScript поддерживает два типа комментариев: Однострочные — начинаются с //. Все, что следует после // до конца строки, игнорируется движком. // Это однострочный комментарий
let x = 5; // Можно писать и в конце строки Многострочные — заключаются между /* и */. Позволяют комментировать несколько строк или блоки кода. /*
Это многострочный комментарий
Используется для описания функций, модулей или временного отключения кода
*/
let y = 10;
JavaScript — язык, чувствительный к регистру. Это означает, что имена переменных, функций, ключевых слов и свойств различаются по написанию букв в верхнем и нижнем регистре.
Примеры: let name = "Анна";
let Name = "Иван"; // Это другая переменная
let NAME = "Олег"; // И ещё одна console.log(name); // "Анна"
console.log(Name); // "Иван"
console.log(NAME); // "Олег"
То же относится к ключевым словам: let — корректно, Let — ошибка (если не является именем переменной).
Также чувствительны к регистру названия свойств объектов: user.name ≠ user.Name.В JavaScript точки с запятой (;) используются для явного завершения инструкций. Хотя язык позволяет опускать их в большинстве случаев благодаря автоматической вставке точек с запятой (ASI — Automatic Semicolon Insertion), рекомендуется всегда использовать точки с запятой для предотвращения неочевидных ошибок. ]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№2/базовое-понимание-синтаксиса-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №2/Базовое понимание синтаксиса JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:39:00 GMT</pubDate></item><item><title><![CDATA[Преобразование типов (Массивы и Объекты) через JSON]]></title><description><![CDATA[Преобразование типов между объектами/массивами и строками — это основа для хранения и передачи данных в приложении. В JavaScript для этого используются два метода: JSON.stringify() и JSON.parse().Превращает объект или массив в строку в формате JSON — текстовом формате, понятном и серверам, и клиентам.
Про сам формат мы прочтем в следующей теме.
const user = { name: 'Анна', age: 28, isAdmin: false, tasks: ['Почитать', 'Написать код']
}; const jsonString = JSON.stringify(user);
console.log(jsonString);
// '{"name":"Анна","age":28,"isAdmin":false,"tasks":["Почитать","Написать код"]}' Важно: JSON.stringify() не работает с функциями, undefined, Symbol и Map/Set. Они будут проигнорированы или заменены на null.
Пример с игнорированием:const obj = { name: 'Иван', func: function() { return 'test'; }, secret: undefined
}; console.log(JSON.stringify(obj));
// '{"name":"Иван"}' — функция и undefined пропущены
Превращает строку в формате JSON обратно в объект или массив.const json = '{"name":"Анна","age":28,"isAdmin":false}'; const user = JSON.parse(json);
console.log(user.name); // "Анна"
console.log(user.age); // 28
console.log(typeof user); // "object" Если строка не является корректным JSON — будет ошибка SyntaxError.
Пример ошибки:JSON.parse('{name: "Иван"}'); // Ошибка! Ключи должны быть в кавычках
JSON.parse('{"name": "Иван"'); // Ошибка! Нет закрывающей скобки
При запросах к серверу (через fetch, axios и т.д.) данные приходят в виде строки в формате JSON. Чтобы работать с ними как с объектами — нужно их распарсить.fetch('/api/user') .then(response =&gt; response.json()) // автоматически вызывает JSON.parse() .then(user =&gt; { console.log(user.name); // теперь можно работать как с объектом });
Также при сохранении данных в localStorage — они должны быть строками:const tasks = [{ title: 'Убраться', completed: false }]; // Сохраняем
localStorage.setItem('tasks', JSON.stringify(tasks)); // Загружаем
const saved = localStorage.getItem('tasks');
const tasksList = JSON.parse(saved);
console.log(tasksList[0].title); // "Убраться" Всегда используйте JSON.stringify() перед сохранением объектов в localStorage или отправкой на сервер.
Всегда используйте JSON.parse() после получения строки из localStorage или ответа API.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/преобразование-типов-(массивы-и-объекты)-через-json.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Преобразование типов (Массивы и Объекты) через JSON.md</guid><pubDate>Tue, 14 Oct 2025 09:39:00 GMT</pubDate></item><item><title><![CDATA[Что такое Git]]></title><description><![CDATA[Git — это распределённая система контроля версий.
Это означает, что каждый разработчик имеет полную копию истории изменений проекта на своём компьютере — не только последнюю версию файла, но и все прошлые состояния.Без Git вы работаете с файлами как с обычными документами: сохраняете, переписываете, теряете изменения.
Git решает три основные проблемы: История изменений
Вы можете посмотреть, кто, когда и что изменил в любом файле.
Пример: вы заметили, что кнопка перестала работать. С помощью Git вы найдёте, в каком коммите это произошло. Откат к предыдущему состоянию
Если вы внесли ошибку — можно вернуть проект к тому состоянию, когда всё работало.
Пример: git reset --hard a1b2c3d Это вернёт весь проект к коммиту с хешем a1b2c3d. Сотрудничество
Несколько человек могут работать над одним проектом одновременно, не мешая друг другу.
Каждый работает в своей копии, потом объединяет изменения. Пример:
Вы работаете в самолёте. В Git: можете делать коммиты, создавать ветки, просматривать историю — всё работает. В SVN: ничего не сможете сделать, пока не выйдете в сеть.
Git — это инструмент, который работает на вашем компьютере.
Он не требует интернета, чтобы функционировать.
Это делает его надёжным и удобным даже в условиях плохого соединения или при работе офлайн.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/что-такое-git.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Что такое Git.md</guid><pubDate>Tue, 14 Oct 2025 09:39:00 GMT</pubDate></item><item><title><![CDATA[Распаковка (spread)]]></title><description><![CDATA[Распаковка (spread) — это оператор ..., который раскрывает элементы массива или свойства объекта на отдельные значения. Он используется для создания копий, объединения структур и передачи аргументов.Чтобы создать поверхностную копию массива, используйте spread в квадратных скобках:const original = ['яблоко', 'груша'];
const copy = [...original]; copy.push('апельсин');
console.log(original); // ['яблоко', 'груша'] — не изменился
console.log(copy); // ['яблоко', 'груша', 'апельсин']
Это безопасный способ избежать мутации исходного массива.Аналогично — для объектов:const user = { name: 'Анна', age: 28 };
const profile = { ...user, city: 'Москва' }; console.log(user); // { name: 'Анна', age: 28 }
console.log(profile); // { name: 'Анна', age: 28, city: 'Москва' }
Если свойство с таким же ключом уже есть — оно перезаписывается:const settings = { theme: 'light', lang: 'ru' };
const newSettings = { ...settings, theme: 'dark' }; console.log(newSettings.theme); // "dark" — перезаписано
С помощью spread можно объединить несколько массивов в один:const fruits = ['яблоко', 'груша'];
const vegetables = ['морковь', 'огурец'];
const groceries = [...fruits, ...vegetables]; console.log(groceries); // ['яблоко', 'груша', 'морковь', 'огурец']
Это проще и читаемее, чем concat().Объединение двух объектов с разными ключами:const config1 = { host: 'localhost', port: 3000 };
const config2 = { ssl: true, timeout: 5000 };
const finalConfig = { ...config1, ...config2 }; console.log(finalConfig);
// { host: 'localhost', port: 3000, ssl: true, timeout: 5000 }
Если ключи совпадают — значение из второго объекта перезаписывает первое.Spread позволяет передать элементы массива в функцию как отдельные аргументы.Пример: Math.max() принимает несколько чисел, но не массив:const numbers = [10, 5, 23, 8]; // Неверно:
console.log(Math.max(numbers)); // NaN // Верно:
console.log(Math.max(...numbers)); // 23 Распаковка работает только на уровне первого уровня вложенности — это поверхностная копия. Если внутри объекта или массива есть вложенные структуры — они остаются по ссылке.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/распаковка-(spread).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Распаковка (spread).md</guid><pubDate>Tue, 14 Oct 2025 09:39:00 GMT</pubDate></item><item><title><![CDATA[Практика №1. Простая веб-страница с HTML]]></title><description><![CDATA[В рамках этого задания вам необходимо добавить логику при нажатиях на кнопку к существующей веб-странице.Задания обязано быть сделано в собственной директории используя изначальный шаблон html файла из ресурсов index.html (может быть модернизирован) и внешний js файл в той же папке (создается самостоятельно).index.html&lt;!DOCTYPE html&gt;
&lt;html lang="ru"&gt;
&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;title&gt;Изучаем JS в рамках html страницы&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; Эта страница содержит JS код который выполняется на стороне клиента. &lt;br/&gt; &lt;button id="button-1"&gt; Эта кнопка выводит сообщение в консоль &lt;/button&gt; &lt;button id="button-2"&gt; Эта кнопка выводит оповещение в браузере &lt;/button&gt; &lt;br/&gt; &lt;button id="button-3"&gt; Эта кнопка меняет цвет фона на красный &lt;/button&gt; &lt;button id="button-4"&gt; Эта кнопка меняет цвет фона на белый &lt;/button&gt; &lt;br/&gt; &lt;textarea id="text-1"&gt; &lt;/textarea&gt; &lt;br/&gt; &lt;button id="button-5"&gt; Сложить число выше с числом 6 &lt;/button&gt; &lt;div id="answer"&gt; ТУТ БУДЕТ ОТВЕТ &lt;/div&gt; &lt;/body&gt;
&lt;/html&gt;
Необходимо добавить логику для кнопок:
Первые две кнопки должны выводить информацию в консоль и в качестве оповещения в браузере.
Кнопки 3-4 должны менять цвет фона в соответствии с текстом кнопки
Кнопка 5 должна получить текст из текстового поля text-1, получить число из строки при помощи функции parseFloat, и проверить на NaN при помощи функции isNaN. Если это число - сложить с числом 6 и записать ответ в div с id answer.
Вам необходимо добавить дополнительное поле ввода для 5 кнопки.
В итоге пользователь должен вписать два числа в два поля и в итоге получить ответ сложениях этих двух чисел.На выполнение выделяется 1 практическая пара.
Градация баллов после дедлайна:
1 пара: 50%
2 пара: 0%
]]></description><link>задания/секция-1.-javascript/практика-№1.-простая-веб-страница-с-html.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №1. Простая веб-страница с HTML.md</guid><pubDate>Tue, 14 Oct 2025 09:38:59 GMT</pubDate></item><item><title><![CDATA[Рекурсия]]></title><description><![CDATA[Рекурсия — это когда функция вызывает саму себя внутри своего тела. Это способ решить задачу, разбив её на более мелкие подзадачи того же типа.Она удобна, когда задача естественно разбивается на аналогичные подзадачи — например, обход дерева каталогов, вычисление чисел Фибоначчи, работа с вложенными структурами данных.Базовый случай — это условие, при котором рекурсия перестаёт вызывать саму себя и начинает возвращать результат. Рекурсия работает по принципу «разделяй и властвуй»: задача разбивается на меньшие копии самой себя. Но в какой-то момент этот процесс должен остановиться — иначе не будет точки входа в обратный путь.Факториал числа n — это произведение всех натуральных чисел от 1 до n.
Обозначается как n!
Пример: 5! = 5 × 4 × 3 × 2 × 1 = 120Рекурсивное определение:
n! = n × (n-1)!
Базовый случай: 0! = 1Реализация:function factorial(n) { if (n === 0 || n === 1) { return 1; // базовый случай } return n * factorial(n - 1); // рекурсивный вызов
} console.log(factorial(5)); // 120
Здесь factorial(5) вызывает factorial(4), который вызывает factorial(3) и так далее, пока не дойдёт до factorial(1). После этого цепочка возвратов начинает вычислять результат снизу вверх.Каждый рекурсивный вызов занимает память в стеке вызовов. Если рекурсия слишком глубокая — стек переполняется, и браузер или приложение падает с ошибкой Stack Overflow.Пример опасного случая:function infiniteRecursion() { return infiniteRecursion(); // вызов без условия остановки
} infiniteRecursion(); // приведёт к Stack Overflow
Поэтому всегда убедитесь, что рекурсия имеет базовый случай, который остановит вызовы, и что с каждым шагом вы приближаетесь к нему.Используйте рекурсию только тогда, когда она делает код понятнее. В большинстве случаев лучше заменять её циклами — они эффективнее и безопаснее.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/рекурсия.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Рекурсия.md</guid><pubDate>Tue, 14 Oct 2025 09:38:58 GMT</pubDate></item><item><title><![CDATA[WEB 2.0 (интерактивный веб)]]></title><description><![CDATA[WEB 2.0 — это веб как платформа, а не набор статических страниц. Сервер больше не отдаёт HTML-файлы целиком — он отдаёт данные, а браузер (или мобильное приложение) сам строит интерфейс.Основа WEB 2.0 — асинхронные запросы: клиент (через JavaScript) отправляет запросы на сервер, получает ответ в формате JSON, и динамически обновляет часть страницы без перезагрузки. Это называется AJAX (Asynchronous JavaScript and XML).
Но сейчас данные передаются в основном как JSON.
Сервер становится API-бэкендом: он не знает, как выглядит страница — он только обрабатывает запросы и возвращает данные.Пример: Gmail
— Вы открываете mail.google.com — сервер отдаёт минимальный HTML и JS-файл
— Браузер загружает JavaScript
— JS отправляет запрос: GET /api/emails
— Сервер отвечает: [ { "id": 123, "from": "boss@company.com", "subject": "Отчёт", "read": false }, { "id": 124, "from": "friend@gmail.com", "subject": "Вечеринка", "read": true }
]
— JavaScript получает список писем и рендерит их в список на странице
— Когда вы нажимаете «Обновить» — снова запрос, снова JSON, снова обновление спискаПример: мобильное приложение с бэкендом
— Приложение на React Native или Flutter
— При запуске делает запрос: GET /api/user
— Получает: { "name": "Анна", "avatar": "https://example.com/avatar.jpg", "tasks": 5 }
— Отображает данные в интерфейсе
— При нажатии кнопки «Создать задачу» — POST-запрос на /api/tasks с даннымиКлючевое отличие:
Данные и представление разделены.
— Сервер: только логика, база данных, API.
— Клиент: только отображение, взаимодействие, UI. Это позволяет: Одному API обслуживать веб, мобильное приложение, десктоп Обновлять интерфейс без перезагрузки Работать оффлайн (с кэшированием) Масштабировать: серверы могут быть только для данных, клиенты — на любом устройстве
WEB 2.0 — основа всех современных приложений: от VK до мобильных корпоративных систем.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/web-2.0-(интерактивный-веб).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/WEB 2.0 (интерактивный веб).md</guid><pubDate>Tue, 14 Oct 2025 09:38:57 GMT</pubDate></item><item><title><![CDATA[Практика №7. Функции для работы с строками]]></title><description><![CDATA[В рамках этого задания вам необходимо создать модифицировать скрипт task7.js, который должен запускаться при помощи Node.js. Задание обязано быть опубликовано в существующем приватном репозитории организации GitHub с названием Группа_Фамилия_task-3-7.task7.js// Объявления функций
console.log("Тут объявляются функции")
// ...
// Тестирование функций
console.log("Вызов функций") console.log("Функция &lt;название функции&gt;")
// ...
console.log("Функция &lt;название функции&gt;")
// ...
Вам необходимо объявить и реализовать три функции. Каждая функция должна иметь правильный JS нейминг и вызываться минимум три раза с разными параметрами.На вход подается строка, вернутся должна развернутая строка. (то есть в обратную сторону).
Если на вход придет палиндром (необходимо игнорировать пробелы и регистр символов) - вывести сообщение в консоль об этом и вернуть исходную строку.
палиндром - число, буквосочетание, слово или текст, одинаково читающееся в обоих направлениях. Примеры: "101", "Лёша на полке клопа нашёл", "Казак".
На вход подается строка, вернутся должно число. Число - это количество гласных в строке (учитывайте оба регистра), латиница и кириллица.Создайте функции которая принимает пароль в качестве аргумента и возвращает&nbsp;true, если он соответствует следующим требованиям:
Длина не менее 8 символов
Содержит как минимум одну строчную, одну прописную букву и одну цифру
На выполнение выделяется 2 практических пары.
Градация баллов после дедлайна: 1 пара: 50%
2 пара: 25%
3 пара: 0%
]]></description><link>задания/секция-1.-javascript/практика-№7.-функции-для-работы-с-строками.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №7. Функции для работы с строками.md</guid><pubDate>Tue, 14 Oct 2025 09:38:56 GMT</pubDate></item><item><title><![CDATA[Каррированные функции]]></title><description><![CDATA[Каррирование — это преобразование функции, которая принимает несколько аргументов, в последовательность функций, каждая из которых принимает ровно один аргумент.Результат — функция, которую можно вызывать по частям, сохраняя промежуточные состояния через замыкания.Пример:function multiply(a) { return function(b) { return function(c) { return a * b * c; }; };
} const result = multiply(2)(5)(3); // 30
Здесь:
multiply(2) возвращает функцию, запоминающую a = 2
multiply(2)(5) возвращает функцию, запоминающую a = 2 и b = 5
multiply(2)(5)(3) возвращает результат: 2 * 5 * 3 = 30
Каждый уровень — это новая функция, которая замыкает на переменные внешнего уровня.Каррирование позволяет создавать переиспользуемые частичные версии функций:function greet(greeting, name) { return `${greeting}, ${name}!`;
} function curry(fn) { return function(a) { return function(b) { return fn(a, b); }; };
} const greetWith = curry(greet);
const sayHello = greetWith("Привет"); console.log(sayHello("Анна")); // "Привет, Анна!"
console.log(sayHello("Иван")); // "Привет, Иван!"
Теперь sayHello — это готовая функция, которая всегда использует "Привет". Её можно передавать как колбэк, использовать в массивах:const users = ["Анна", "Иван", "Мария"];
const greetings = users.map(sayHello);
// ["Привет, Анна!", "Привет, Иван!", "Привет, Мария!"] Форматирование данных: formatDate(locale, format) → formatDateRu = curry(formatDate)("ru-RU")
Валидация: validateLength(min, max, value) → validateMin5 = curry(validateLength)(5, 100)
Настройка запросов: apiRequest(method, url, headers) → get = curry(apiRequest)("GET") Каррирование — не синтаксическая фича JavaScript, а паттерн, основанный на замыканиях.
Он особенно полезен в функциональном стиле программирования и для создания гибких, переиспользуемых утилит.
Используйте его, когда нужно создавать специализированные версии функций с предустановленными параметрами.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/каррированные-функции.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Каррированные функции.md</guid><pubDate>Tue, 14 Oct 2025 09:38:56 GMT</pubDate></item><item><title><![CDATA[Самое простое использование JavaScript]]></title><description><![CDATA[Для быстрого тестирования и экспериментов с JavaScript можно использовать консоль разработчика — встроенную инструментальную панель в любом современном браузере (Chrome, Firefox, Edge, Safari). Открыть её можно сочетанием клавиш F12 или Ctrl+Shift+I (на macOS — Cmd+Option+I), затем перейти на вкладку Console.Консоль позволяет выполнять JavaScript-код прямо в браузере без создания HTML-файлов. Это идеальное место для проверки синтаксиса, отладки простых выражений и изучения поведения языка в реальном времени.
<img alt="Pasted image 20250912212732.png" src="материалы/файлы/pasted-image-20250912212732.png" target="_self">Для вывода информации в консоль используется функция console.log():console.log("Привет, мир!");
console.log(42);
console.log(true);
<br><img alt="Pasted image 20250912212810.png" src="материалы/файлы/pasted-image-20250912212810.png" target="_self">Эта команда — основной инструмент отладки на начальных этапах. Она выводит переданные значения в консоль, помогая увидеть, что происходит в коде. Можно передавать несколько аргументов:console.log("Значение переменной:", variableName);
Также доступны другие методы:
console.error() — для ошибок (выводится красным),
console.warn() — для предупреждений (жёлтый цвет),
console.table() — для удобного отображения массивов и объектов в виде таблицы.
Для показа пользователю простого сообщения используется функция alert():alert("Это сообщение от JavaScript!");
<br><img alt="Pasted image 20250912212840.png" src="материалы/файлы/pasted-image-20250912212840.png" target="_self">Она выводит модальное окно с текстом, которое блокирует взаимодействие с страницей до нажатия кнопки «ОК». Используется исключительно для учебных целей и быстрой обратной связи — в реальных приложениях alert() не применяется из-за плохого пользовательского опыта.
⚠️ Не используйте alert() в продакшене — он нарушает поток работы пользователя и не поддерживает стилизацию.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№3/самое-простое-использование-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №3/Самое простое использование JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:56 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Цикл while]]></title><description><![CDATA[Цикл while выполняет блок кода пока условие истинно. Он подходит, когда заранее неизвестно, сколько раз нужно повторить действие.while (условие) { // тело цикла
}
Условие проверяется до каждой итерации. Если оно ложно с самого начала — тело цикла не выполнится ни разу.let isLoading = true;
let attempts = 0; while (isLoading &amp;&amp; attempts &lt; 5) { console.log("Попытка загрузки #" + (attempts + 1)); // Имитация асинхронной загрузки if (Math.random() &gt; 0.7) { isLoading = false; console.log("Успешно загружено!"); } attempts++;
}
Здесь мы не знаем, на какой попытке данные загрузятся — поэтому используем while.const messages = ["Привет", "Как дела?", "Пока", "Спасибо"];
let i = 0; while (i &lt; messages.length &amp;&amp; messages[i] !== "Пока") { console.log("Обрабатываю: " + messages[i]); i++;
} console.log("Нашли 'Пока' на позиции " + i);
Вывод:Обрабатываю: Привет
Обрабатываю: Как дела?
Нашли 'Пока' на позиции 2
Если условие никогда не станет false — цикл никогда не завершится. Это приведёт к зависанию приложения.// ОШИБКА — бесконечный цикл
while (true) { console.log("Это никогда не остановится!");
}
Всегда убедитесь, что внутри цикла есть изменение, которое ведёт к завершению условия.
Когда количество итераций зависит от внешних условий: загрузка сети, ожидание ответа API, ввод пользователя.
При работе с потоками данных, где элементы приходят динамически.
В мобильных приложениях — например, повторная попытка отправки запроса при ошибке, пока не будет успеха или превышено лимит попыток. <a data-href="Цикл `do...while`" href="материалы/подтемы/секция-1.-javascript/тема-№8/цикл-`do...while`.html" class="internal-link" target="_self" rel="noopener nofollow">Цикл `do...while`</a>
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/цикл-while.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Цикл while.md</guid><pubDate>Tue, 14 Oct 2025 09:38:54 GMT</pubDate></item><item><title><![CDATA[Конструктор массива Array]]></title><description><![CDATA[Конструктор new Array() может вести себя неожиданно — и это опасно.Вот два случая:const numbers = new Array(1, 2, 3);
console.log(numbers); // [1, 2, 3]
Здесь всё нормально: передали три числа — получили массив из трёх элементов.const empty = new Array(5);
console.log(empty); // [empty × 5] — не [0, 0, 0, 0, 0]!
console.log(empty[0]); // undefined
Здесь вы не создали массив с пятью нулями. Вы создали массив из пяти пустых ячеек. Это не то же самое, что заполненный нулями массив.Попробуйте перебрать его:for (const item of empty) { console.log(item); // ничего не выведется — все элементы undefined
}
Или попробуйте использовать map:const doubled = empty.map(x =&gt; x * 2);
console.log(doubled); // [empty × 5] — всё ещё пусто
Он не сработает, потому что map пропускает пустые ячейки.const numbers = [1, 2, 3]; // ясно, что будет: три числа
const filled = new Array(5).fill(0); // если реально нужны нули — явно заполняем
const simple = [0, 0, 0, 0, 0]; // проще и понятнее Читаемо — сразу видно, что это массив.
Быстро — JavaScript обрабатывает его эффективнее.
Без сюрпризов — не путает длину и значения.
Стандарт — так пишут все профессионалы. ❌ Не пишите new Array(5) — вы рискуете создать не то, что думаете.
✅ Пишите [ ] — и если нужно заполнить — используйте .fill().
Пример безопасного создания массива из 5 нулей:const zeros = Array(5).fill(0); // [0, 0, 0, 0, 0]
Но даже здесь — если вы не уверены, лучше сразу написать:const zeros = [0, 0, 0, 0, 0];
Проще, понятнее, надёжнее.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№11/конструктор-массива-array.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №11/Конструктор массива Array.md</guid><pubDate>Tue, 14 Oct 2025 09:38:54 GMT</pubDate></item><item><title><![CDATA[Возвращаемое значение]]></title><description><![CDATA[Функция может возвращать результат с помощью оператора return. Это значение передаётся обратно в место, откуда функция была вызвана.function calculateDiscount(price, discountPercent) { return price - (price * discountPercent / 100);
} const finalPrice = calculateDiscount(1000, 15);
console.log(finalPrice); // 850
Здесь return отправляет вычисленную сумму обратно в переменную finalPrice.Если в функции нет return, она возвращает undefined:function logMessage(message) { console.log(message);
} const result = logMessage('Привет');
console.log(result); // undefined
Даже если функция что-то делает — например, выводит в консоль — она не возвращает ничего, если не указан return.return можно использовать для преждевременного завершения работы функции — это полезно для проверки условий.Пример: проверка наличия данных перед обработкойfunction updateUserProfile(userData) { if (!userData || !userData.name) { return; // выход, если данные не переданы или нет имени } // Эта часть выполнится только если условия выше не сработали console.log('Обновление профиля для:', userData.name); // ... логика обновления
} updateUserProfile(); // ничего не делает, функция завершается на return
updateUserProfile({ name: 'Анна' }); // обновление профиля
Такой подход упрощает код: вы не пишете вложенные if-else, а сразу отсеиваете невалидные случаи.function loadUserSettings() { if (!userIsAuthenticated) { return; // не продолжаем, если пользователь не авторизован } const settings = api.getSettings(); updateUI(settings);
}
Здесь return предотвращает выполнение дорогостоящих операций — обращение к API, обновление интерфейса — если это бессмысленно. Это улучшает производительность и снижает риск ошибок.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/возвращаемое-значение.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Возвращаемое значение.md</guid><pubDate>Tue, 14 Oct 2025 09:38:54 GMT</pubDate></item><item><title><![CDATA[Практика №5. Использование ветвления.]]></title><description><![CDATA[В рамках этого задания вам необходимо модернизировать скрипт task5.js, который должен запускаться при помощи Node.js. Задание обязано быть опубликовано в существующем приватном репозитории организации GitHub с названием Группа_Фамилия_task-3-7.task5.jsconst lower = -20;
const upper = 100;
const threshold = 30;
let a = Math.floor(Math.random() * (upper-lower+1)) + lower; // Пока не обращаем внимания, тут будет случайное число от -20 до 100
let greek = Math.floor(Math.random() * 11); // от 0 до 10 console.log("Текущее значение переменной a - "+a); // Менять код ниже // Менять код ниже
Необходимо выполнить все три части. Для каждой части необходимо использовать разные методы ветвления.Создайте переменную partOne. partOne должен принять значение в зависимости от условия:
Если a меньше threshold - это полный диапазон чисел от lower к upper (например в этом примере это должно быть число 120)
Если a больше - это произведение a и threshold
Если они равны - то это должна быть строчка "Вам невероятно повезло!"
Во всех случаях необходимо вывести в консоль следующее:
Новое значение partOne
По какому условию оно прошло
Какая вероятность того что оно могло попасть в это условие
Вывести в консоль значение greek в греческой записи (1 - I, 2 - II, 5 - V)Вывести в консоль является ли значение a четным или нечетным.На выполнение выделяется 2 практических пары.
Градация баллов после дедлайна: 1 пара: 50%
2 пара: 25%
3 пара: 0%
]]></description><link>задания/секция-1.-javascript/практика-№5.-использование-ветвления..html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №5. Использование ветвления..md</guid><pubDate>Tue, 14 Oct 2025 09:38:53 GMT</pubDate></item><item><title><![CDATA[Стрелочные функции (Arrow Function)]]></title><description><![CDATA[const multiply = (a, b) =&gt; { return a * b;
};
Она состоит из двух частей: параметры в скобках, затем стрелка =&gt;, и тело функции в фигурных скобках.Если параметр один — скобки можно опустить:const square = x =&gt; x * x;
Если тело функции — одно выражение — фигурные скобки и return можно опустить:const formatName = (first, last) =&gt; first + ' ' + last;
Это называется краткой формой. Она возвращает результат выражения автоматически.Стрелочные функции часто называют анонимными, потому что они не имеют имени в своём определении. Их имя — это переменная, в которую они присваиваются.Стрелочные функции идеальны для простых преобразований и коллбэков — особенно в мобильных приложениях, где код должен быть лаконичным.const tasks = [ { id: 1, title: 'Починить экран', completed: false }, { id: 2, title: 'Обновить приложение', completed: true }
]; const pendingTasks = tasks.filter(task =&gt; !task.completed);
console.log(pendingTasks); // [{ id: 1, title: 'Починить экран', completed: false }]
Здесь стрелочная функция task =&gt; !task.completed передаётся в filter. Она короткая, читаемая и выполняет одну задачу — проверяет, не выполнена ли задача.Пример: обработчик клика в React Native или веб-интерфейсеbutton.addEventListener('click', () =&gt; { showNotification('Данные сохранены');
}); Важно: стрелочные функции не имеют собственного this. Это полезно в классах и коллбэках, но не всегда очевидно для новичков — пока достаточно знать, что для простых операций они удобны, а для сложной логики с this лучше использовать функциональные выражения или объявления.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/стрелочные-функции-(arrow-function).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Стрелочные функции (Arrow Function).md</guid><pubDate>Tue, 14 Oct 2025 09:38:53 GMT</pubDate></item><item><title><![CDATA[Глобальная область видимости]]></title><description><![CDATA[Глобальная область видимости — это область, в которой переменные доступны в любом месте файла, включая все функции и блоки.Переменные объявляются в глобальной области, если они созданы вне всех функций, циклов, условий — то есть на самом верхнем уровне скрипта.Пример:let appVersion = "1.2.0"; // глобальная переменная
const apiUrl = "https://api.example.com"; function loadUserData() { console.log(appVersion); // можно использовать — доступна
} loadUserData();
console.log(appVersion); // тоже доступна
Такие переменные доступны везде — в любой функции, даже в файле, подключённом позже. Это удобно для настроек, которые нужны повсеместно: URL API, токен авторизации, флаги режима приложения.Но есть серьёзный риск — загрязнение глобального пространства.Когда много разработчиков пишут код в одном файле или подключают несколько скриптов, они могут случайно переопределить одну и ту же глобальную переменную.Пример проблемы:// Файл 1 (ваш код)
let user = { id: 1, name: "Петр" }; // Файл 2 (сторонний скрипт)
let user = "guest"; // ой — перезаписал ваш объект! console.log(user); // "guest" — ваша логика сломалась
Такие ошибки сложно отловить: они проявляются не всегда, зависят от порядка загрузки файлов, и могут быть в продакшене.Поэтому:
Избегайте создания глобальных переменных без необходимости
Если нужно хранить данные на уровне приложения — используйте модули или объекты-нэйспейсы
В современном JavaScript используйте import/export — они не создают глобальные переменные Лучшая практика: чем меньше глобальных переменных — тем стабильнее приложение.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/глобальная-область-видимости.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Глобальная область видимости.md</guid><pubDate>Tue, 14 Oct 2025 09:38:52 GMT</pubDate></item><item><title><![CDATA[Цикл `for...of` — перебор значений итерируемых объектов]]></title><description><![CDATA[Цикл for...of — это современный способ перебора значений в итерируемых объектах. Он предназначен для доступа к данным, а не к их ключам.for (значение of итерируемый_объект) { // тело цикла
}
const colors = ["красный", "зелёный", "синий"]; for (let color of colors) { console.log(color);
}
Вывод:красный
зелёный
синий
Здесь color — это значение элемента, а не индекс.const text = "Привет"; for (let char of text) { console.log(char);
}
Вывод:П
р
и
в
е
т
Каждая итерация возвращает один символ.const settings = new Map([ ["theme", "dark"], ["lang", "ru"], ["notifications", true]
]); for (let value of settings) { console.log(value); // ["theme", "dark"], ["lang", "ru"], ["notifications", true]
} // Если нужно отдельно ключ и значение:
for (let [key, value] of settings) { console.log(key + ": " + value);
}
Вывод:theme: dark
lang: ru
notifications: true
const tags = new Set(["javascript", "react", "mobile"]); for (let tag of tags) { console.log(tag);
}
Вывод:javascript
react
mobile Используйте for...of, когда нужно перебрать значения — массивы, строки, Map, Set, NodeList и другие итерируемые структуры.
Это безопасно, понятно и работает предсказуемо.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/цикл-`for...of`-—-перебор-значений-итерируемых-объектов.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Цикл `for...of` — перебор значений итерируемых объектов.md</guid><pubDate>Tue, 14 Oct 2025 09:38:52 GMT</pubDate></item><item><title><![CDATA[Вложенность областей видимости]]></title><description><![CDATA[Вложенность областей видимости означает, что внутренняя область кода (например, функция внутри другой функции) может обращаться к переменным внешней области, но не наоборот.Это работает по принципу «внутри видит наружу, но наружу не видит внутрь».Пример:function outerFunction() { const userName = "Анна"; function innerFunction() { console.log(userName); // доступна — из внутренней функции видна внешняя переменная const userRole = "admin"; } innerFunction(); console.log(userRole); // ошибка: userRole is not defined
}
Здесь:
innerFunction может прочитать userName — потому что он объявлен во внешней функции
outerFunction не может прочитать userRole — он существует только внутри innerFunction
Это естественное поведение, основанное на цепочке областей видимости — так называемой цепочке лексических окружений.Ещё один пример — вложенные блоки:function checkPermissions() { const userId = 123; if (userId &gt; 0) { const hasAccess = true; console.log(userId); // работает — видит внешнюю переменную console.log(hasAccess); // работает — своя переменная } console.log(hasAccess); // ошибка — hasAccess не видна за пределами блока if
}
Почему это важно:
Вы можете создавать локальные контексты: например, обработку авторизации внутри функции, не засоряя внешнюю область
Не нужно бояться, что переменные внутри вспомогательных функций перезапишут глобальные
Легче тестировать: функция работает только с тем, что ей передано или что видно из внешней области Всегда объявляйте переменные как можно глубже — в том блоке, где они реально нужны. Это делает код чище, безопаснее и предсказуемее.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/вложенность-областей-видимости.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Вложенность областей видимости.md</guid><pubDate>Tue, 14 Oct 2025 09:38:51 GMT</pubDate></item><item><title><![CDATA[Функциональная область видимости]]></title><description><![CDATA[Функциональная область видимости означает, что переменная, объявленная с помощью var внутри функции, доступна только внутри этой функции и во всех вложенных блоках — но не за пределами функции.Пример:function checkUser() { var isLoggedIn = true; if (isLoggedIn) { var message = "Пользователь авторизован"; console.log(message); // работает — внутри if } console.log(message); // тоже работает — message доступна в функции
} checkUser();
console.log(isLoggedIn); // ошибка: isLoggedIn is not defined
console.log(message); // ошибка: message is not defined
Здесь isLoggedIn и message видны только внутри функции checkUser. За её пределами — недоступны. Это защищает внешний код от случайных перезаписей.Но есть важная особенность var: он не имеет блочной области видимости.Даже если переменная объявлена внутри if, for или while — она всё равно будет доступна во всей функции.Пример:function processSettings() { if (true) { var theme = "dark"; } console.log(theme); // "dark" — доступна, хотя объявлена внутри if
} processSettings();
То же самое с циклом:function loopExample() { for (var i = 0; i &lt; 3; i++) { console.log(i); } console.log(i); // 3 — i доступна даже после цикла
} loopExample();
Это поведение — особенность var. Он поднимается (hoisting) и привязывается к функции, а не к блоку {}.Почему это проблема:
Сложно отслеживать, где именно переменная была объявлена
Можно случайно использовать переменную до её ожидаемого объявления
Ведёт к ошибкам при рефакторинге
Поэтому в современном JavaScript var не рекомендуется. Вместо него используйте let и const — они дают блочную область видимости и предсказуемое поведение.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/функциональная-область-видимости.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Функциональная область видимости.md</guid><pubDate>Tue, 14 Oct 2025 09:38:51 GMT</pubDate></item><item><title><![CDATA[Цикл `for...in` — перебор ключей объекта]]></title><description><![CDATA[Цикл for...in перебирает ключевые свойства объекта — то есть имена (ключи) его перечисляемых свойств.for (ключ in объект) { // тело цикла
}
const user = { name: "Анна", age: 28, role: "администратор"
}; for (let key in user) { console.log(key + ": " + user[key]);
}
Вывод:name: Анна
age: 28
role: администратор
Каждая итерация возвращает имя свойства — строку. Чтобы получить значение, нужно обратиться через объект[ключ].
Перебирает только перечисляемые свойства (те, что можно увидеть в Object.keys()).
Включает свойства, унаследованные от прототипа, если они не помечены как enumerable: false.
Порядок не гарантирован — особенно для числовых ключей, которые могут быть отсортированы по возрастанию.
const arr = ["a", "b", "c"];
arr.extra = "лишнее"; // добавили нечисловое свойство for (let key in arr) { console.log(key); // выведет: "0", "1", "2", "extra"
}
Проблемы:
Не только индексы — for...in перебирает все перечисляемые свойства, включая те, что добавлены вручную.
Порядок может нарушиться — в некоторых движках числовые ключи сортируются по возрастанию, даже если они были добавлены в другом порядке.
Нет гарантии, что вы получите только элементы массива — если библиотека расширила Array.prototype, это тоже попадёт в цикл. Не используйте for...in для массивов.
Используйте for...of или классический for.
Для массивов for...in — источник багов. Для объектов — нормально, если вы знаете, что делаете.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/цикл-`for...in`-—-перебор-ключей-объекта.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Цикл `for...in` — перебор ключей объекта.md</guid><pubDate>Tue, 14 Oct 2025 09:38:51 GMT</pubDate></item><item><title><![CDATA[Блочная область видимости]]></title><description><![CDATA[Блочная область видимости — это когда переменная доступна только внутри блока кода, заключённого в фигурные скобки {} — например, внутри if, for, while, или любого другого блока.Переменные, объявленные с let и const, привязаны к блоку, а не к функции. Они не видны за пределами этого блока.Пример:if (true) { let isActive = true; const theme = "dark";
} console.log(isActive); // ошибка: isActive is not defined
console.log(theme); // ошибка: theme is not defined
Здесь isActive и theme существуют только внутри if. Как только блок завершён — переменные уничтожаются (в смысле недоступны).То же работает с циклами:for (let i = 0; i &lt; 3; i++) { console.log(i); // 0, 1, 2
} console.log(i); // ошибка: i is not defined
В отличие от var, здесь i не выходит за пределы цикла — это предсказуемо и безопасно.С let в цикле for каждая итерация создаёт новую переменную. Это важно при использовании замыканий.Пример с var — проблема:for (var i = 0; i &lt; 3; i++) { setTimeout(() =&gt; console.log(i), 100);
}
// Выведет: 3, 3, 3 — потому что i — одна переменная, и к моменту запуска setTimeout она = 3
Пример с let — правильно:for (let i = 0; i &lt; 3; i++) { setTimeout(() =&gt; console.log(i), 100);
}
// Выведет: 0, 1, 2 — каждая итерация имеет свою i
Почему так происходит:
let создаёт новую привязку переменной для каждой итерации цикла. var — одну и ту же переменную для всего цикла.
Всегда используйте let и const вместо var.
Они дают точный контроль: переменная существует только там, где вы её объявили — меньше ошибок, проще читать и отлаживать код.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/блочная-область-видимости.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Блочная область видимости.md</guid><pubDate>Tue, 14 Oct 2025 09:38:51 GMT</pubDate></item><item><title><![CDATA[Функциональное выражение (Function Expression)]]></title><description><![CDATA[Функциональное выражение (Function Expression)Синтаксис функционального выражения:const calculateSum = function(a, b) { return a + b;
};
Здесь функция не объявляется как отдельная сущность с именем в области видимости. Вместо этого она создаётся как анонимная функция и присваивается переменной calculateSum.Главное отличие от объявления функции — отсутствие поднятия. Вы не можете вызвать функцию до её присваивания:console.log(calculateSum(2, 3)); // Ошибка: TypeError: calculateSum is not a function const calculateSum = function(a, b) { return a + b;
};
Это важно: функциональное выражение становится доступным только после строки, в которой оно присвоено.Использование: передача функции как аргументаЧасто функциональные выражения используются, когда функция передаётся в другую функцию — например, как коллбэк.Пример: обработка данных списка пользователейconst users = ['Анна', 'Иван', 'Мария']; const capitalizedUsers = users.map(function(name) { return name.charAt(0).toUpperCase() + name.slice(1);
}); console.log(capitalizedUsers); // ['Анна', 'Иван', 'Мария']
Здесь анонимная функция передаётся в метод map. Она будет вызвана для каждого элемента массива. Такой подход часто используется в мобильных приложениях при фильтрации, сортировке или преобразовании данных из API.Функциональные выражения также полезны, когда вы хотите создать функцию динамически или условно:let getGreeting; if (isMorning) { getGreeting = function() { return 'Доброе утро'; };
} else { getGreeting = function() { return 'Добрый день'; };
} console.log(getGreeting()); // зависит от условия
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/функциональное-выражение-(function-expression).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Функциональное выражение (Function Expression).md</guid><pubDate>Tue, 14 Oct 2025 09:38:50 GMT</pubDate></item><item><title><![CDATA[Параметры и аргументы]]></title><description><![CDATA[Параметры — это имена переменных, которые указываются в скобках при объявлении функции. Они определяют, какие данные функция ожидает получить.Аргументы — это реальные значения, которые передаются функции при её вызове.Пример:function greet(name, age) { // name и age — параметры return 'Привет, ' + name + ', тебе ' + age + ' лет';
} console.log(greet('Анна', 25)); // 'Анна' и 25 — аргументы
Здесь name и age — параметры. При вызове greet('Анна', 25) передаются аргументы 'Анна' и 25. Каждый аргумент присваивается соответствующему параметру.Если аргументов меньше, чем параметров — остальные получат значение undefined:console.log(greet('Иван')); // Привет, Иван, тебе undefined лет
Чтобы избежать undefined, можно задать значения по умолчанию:function greet(name, age = 18) { return 'Привет, ' + name + ', тебе ' + age + ' лет';
} console.log(greet('Иван')); // Привет, Иван, тебе 18 лет
console.log(greet('Мария', 22)); // Привет, Мария, тебе 22 лет
Значения по умолчанию работают для любого параметра — не только последнего:function createTask(title = 'Новая задача', priority = 'средний', completed = false) { return { title, priority, completed };
} console.log(createTask()); // { title: 'Новая задача', priority: 'средний', completed: false }
console.log(createTask('Удалить кеш')); // { title: 'Удалить кеш', priority: 'средний', completed: false }
Это особенно полезно в приложениях, где параметры часто не обязательны — например, настройки темы, уведомления, таймауты. Вы можете задать разумные значения по умолчанию и не проверять каждый аргумент вручную.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/параметры-и-аргументы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Параметры и аргументы.md</guid><pubDate>Tue, 14 Oct 2025 09:38:49 GMT</pubDate></item><item><title><![CDATA[Оператор `if`]]></title><description><![CDATA[Оператор if выполняет блок кода, только если условие в скобках истинно.Базовый синтаксис:if (условие) { // код, который выполнится, если условие истинно
}
Условие — это выражение, которое возвращает true или false. В JavaScript к false приводятся значения: false, 0, "" (пустая строка), null, undefined, NaN. Всё остальное — true.Пример: проверка, авторизован ли пользовательconst userToken = localStorage.getItem("token"); if (userToken) { console.log("Пользователь авторизован"); loadUserProfile();
}
Здесь userToken может быть строкой (истина) или null (ложь). Если токен есть — вызываем функцию загрузки профиля. Если нет — ничего не делаем.Нет, они не обязательны, если в блоке if только одна строка:if (userToken) console.log("Пользователь авторизован");
Но рекомендуется всегда использовать фигурные скобки, даже для одной строки.Почему?
Избегает ошибок при доработке кода:
if (userToken) console.log("Пользователь авторизован"); loadUserProfile(); // Эта строка ВСЕГДА выполнится — вне зависимости от условия!
Здесь loadUserProfile() не в блоке if, потому что нет скобок. Это распространённая ошибка. Улучшает читаемость и согласованность кода в команде. Снижает риск багов при рефакторинге. Правило: всегда пишите скобки.if (userToken) { console.log("Пользователь авторизован"); loadUserProfile();
}
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/оператор-`if`.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Оператор `if`.md</guid><pubDate>Tue, 14 Oct 2025 09:38:47 GMT</pubDate></item><item><title><![CDATA[WEB 1.0 (статический веб)]]></title><description><![CDATA[WEB 1.0 — это статический веб: сервер хранит файлы (HTML, CSS, JS, изображения) на диске и отдаёт их клиенту «как есть» при запросе.Когда пользователь вводит URL — например, http://example.com/index.html — веб-сервер (например, Apache или Nginx) находит файл index.html в папке сайта и отправляет его браузеру. Браузер просто отображает содержимое.Нет никакой логики на сервере. Нет баз данных. Нет обработки данных. Нет ответов в формате JSON. Сервер не «думает» — он только достаёт и отдаёт.Пример: сайт-визитка 2005 года
— 5 страниц: index.html, about.html, contact.html, styles.css, script.js
— Все файлы лежат в папке /var/www/html
— При переходе на contact.html сервер находит файл и отправляет его целиком
— Если нужно обновить текст — нужно загрузить новый HTML-файл на серверОграничения:
Нельзя показать разный контент для разных пользователей без создания отдельных файлов
Нельзя обновить часть страницы — только полная перезагрузка
Нет форм, отправки данных, динамических списков
Масштабирование: добавление новой страницы = создание нового файла
Это был стандарт до середины 2000-х.
Сегодня такой подход используется только для статических сайтов (например, GitHub Pages, Vercel для статики), но без серверной логики. Например сайт, на котором вы сейчас читаете лекционный материал - относится именно к статическим сайтам.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/web-1.0-(статический-веб).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/WEB 1.0 (статический веб).md</guid><pubDate>Tue, 14 Oct 2025 09:38:47 GMT</pubDate></item><item><title><![CDATA[Файл .gitignore]]></title><description><![CDATA[Файл .gitignore указывает Git, какие файлы и папки не нужно отслеживать.
Он предотвращает попадание в репозиторий временных, системных или чувствительных файлов, которые не нужны другим разработчикам.Примеры файлов, которые никогда не должны быть в репозитории:
node_modules/ — папка с зависимостями React Native (устанавливается через npm install)
.env — файл с секретными ключами (API-ключи, токены, пароли)
build/, ios/, android/ — скомпилированные бинарники (они разные на каждом компьютере)
.DS_Store, Thumbs.db — системные файлы macOS и Windows
*.log, *.tmp — логи и временные файлы
Создайте файл .gitignore в корне проекта:touch .gitignore
И добавьте туда строки:node_modules/
.env
build/
ios/
android/
*.log
*.tmp
.DS_Store
После этого Git перестанет отслеживать эти файлы — даже если вы выполните git add ..
Если файл уже был добавлен в репозиторий — .gitignore его не игнорирует.
Сначала удалите его из индекса: git rm -r --cached node_modules/
git commit -m "Убрал node_modules из репозитория" Вот стандартный .gitignore для React Native-проекта:# Dependencies
node_modules/ # Environment
.env
.env.local
.env.development
.env.production # Build output
build/
ios/
android/ # Logs
*.log
npm-debug.log* # IDE and editor
.vscode/
.idea/
*.swp
*.swo # OS
.DS_Store
Thumbs.db # Testing
coverage/ # Expo
.expo/
.expo-shared/ Вы можете использовать шаблоны из <a data-tooltip-position="top" aria-label="https://github.com/github/gitignore" rel="noopener nofollow" class="external-link is-unresolved" href="https://github.com/github/gitignore" target="_self">github.com/github/gitignore</a> — там есть готовые .gitignore для React Native, Expo, iOS, Android.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/файл-.gitignore.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Файл .gitignore.md</guid><pubDate>Tue, 14 Oct 2025 09:38:47 GMT</pubDate></item><item><title><![CDATA[Что такое GitHub]]></title><description><![CDATA[GitHub — это хостинг для Git-репозиториев.
Это веб-платформа, где можно хранить код, делиться им с другими и работать совместно.
Хранение — ваш репозиторий сохраняется на сервере GitHub, даже если ваш компьютер сломается.
Обмен — вы можете дать доступ другим разработчикам или сделать репозиторий публичным.
Совместная работа — через pull requests, комментарии, задачи (issues), код-ревью.
Пример:
Вы разрабатываете мобильное приложение на React Native.
Вы закоммитили изменения локально, но хотите, чтобы команда увидела ваш код — вы отправляете его на GitHub.
Другой разработчик клонирует репозиторий, проверяет код, предлагает правки — вы вносите их и снова публикуете.Git — это инструмент, который работает на вашем компьютере.
GitHub — это сервис, который предоставляет место для хранения Git-репозиториев в облаке.
Git — как ручка и тетрадь.
GitHub — как облако, куда вы сканируете тетрадь, чтобы другие могли её видеть.
Вы можете использовать Git без GitHub — локально, на своём компьютере.
Но вы не можете использовать GitHub без Git — он требует репозитория, созданный с помощью Git.
GitHub — это не единственный хостинг. Есть GitLab, Bitbucket, Gitea.
Но GitHub — самый популярный, особенно в открытых проектах и при поиске работы.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№6/что-такое-github.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Что такое GitHub.md</guid><pubDate>Tue, 14 Oct 2025 09:38:46 GMT</pubDate></item><item><title><![CDATA[Цикл `do...while`]]></title><description><![CDATA[Цикл do...while — это разновидность цикла while, в которой тело выполняется хотя бы один раз, даже если условие ложно с самого начала.do { // тело цикла
} while (условие);
Обратите внимание: условие проверяется после выполнения тела. Это главное отличие от while.let userInput = ""; do { userInput = prompt("Введите пароль (минимум 6 символов):");
} while (userInput.length &lt; 6); console.log("Пароль принят: " + userInput);
Здесь пользователь обязательно увидит поле ввода хотя бы один раз — даже если он сразу введёт короткий пароль. Цикл продолжится, пока условие не выполнится.
Используйте do...while, когда нужно хотя бы один раз выполнить действие, а потом проверять, нужно ли повторять.
Особенно полезно для ввода данных, настроек, подтверждений — там, где пользователь должен что-то сделать до продолжения.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/цикл-`do...while`.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Цикл `do...while`.md</guid><pubDate>Tue, 14 Oct 2025 09:38:44 GMT</pubDate></item><item><title><![CDATA[Что такое функция]]></title><description><![CDATA[Функция — это именованный блок кода, который выполняет определённую задачу. Её можно вызывать несколько раз, передавая разные данные, и она всегда будет вести себя одинаково.Без функций код становился бы дублирующимся и неуправляемым. Например, если нужно проверить, заполнено ли поле ввода в трёх разных местах приложения — без функции вы скопировали бы один и тот же код три раза. С функцией — один раз написали, три раза вызвали.Функции помогают структурировать код: разбивают большую задачу на маленькие, понятные части. Это делает его легче тестировать, читать и поддерживать.Пример: обработчик клика по кнопке в HTML&lt;button id="loginBtn"&gt;Войти&lt;/button&gt;
function handleLoginClick() { const email = document.getElementById('email').value; if (email) { console.log('Почта введена, начинаем вход...'); } else { console.log('Введите почту'); }
} document.getElementById('loginBtn').addEventListener('click', handleLoginClick);
Здесь handleLoginClick — функция. Она не выполняется сразу, а ждёт, пока пользователь кликнет. Когда клик происходит — функция вызывается. Это делает интерфейс реактивным. Без функции вы не смогли бы отделить логику от события.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/что-такое-функция.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Что такое функция.md</guid><pubDate>Tue, 14 Oct 2025 09:38:44 GMT</pubDate></item><item><title><![CDATA[Цикл for]]></title><description><![CDATA[Цикл for — это самый гибкий и часто используемый цикл в JavaScript. Он позволяет точно контролировать начало, условие продолжения и изменение счётчика на каждой итерации.for (инициализация; условие; шаг) { // тело цикла
} инициализация — выполняется один раз в начале. Обычно объявляется счётчик (let i = 0).
условие — проверяется перед каждой итерацией. Если false — цикл завершается.
шаг — выполняется после каждого прохода тела цикла. Обычно увеличивает счётчик (i++).
const products = ["Яблоко", "Груша", "Апельсин"]; for (let i = 0; i &lt; products.length; i++) { console.log("Товар: " + products[i]);
}
Вывод:Товар: Яблоко
Товар: Груша
Товар: Апельсин
Здесь i — индекс текущего элемента. Мы используем его для доступа к products[i].Если массив изменяется во время цикла (например, элементы удаляются), length пересчитывается на каждой итерации. Это безопасно.
<a data-href="Цикл `for...in` — перебор ключей объекта" href="материалы/подтемы/секция-1.-javascript/тема-№8/цикл-`for...in`-—-перебор-ключей-объекта.html" class="internal-link" target="_self" rel="noopener nofollow">Цикл `for...in` — перебор ключей объекта</a>
<br><a data-href="Цикл `for...of` — перебор значений итерируемых объектов" href="материалы/подтемы/секция-1.-javascript/тема-№8/цикл-`for...of`-—-перебор-значений-итерируемых-объектов.html" class="internal-link" target="_self" rel="noopener nofollow">Цикл `for...of` — перебор значений итерируемых объектов</a>
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/цикл-for.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Цикл for.md</guid><pubDate>Tue, 14 Oct 2025 09:38:42 GMT</pubDate></item><item><title><![CDATA[Вкратце о REST]]></title><description><![CDATA[REST — это архитектурный подход для построения веб-сервисов, основанный на использовании стандартных HTTP-методов для работы с ресурсами. Подробнее с ним мы познакомимся в соответствующей теме, но некоторые основы стоит показать сейчас:
Ресурсы — сущности, которые можно запросить: /users, /tasks, /products Методы HTTP — действия над ресурсами: GET — получить список или один элемент POST — создать новый ресурс PUT / PATCH — обновить существующий DELETE — удалить ресурс Состояние — сервер не хранит сессию клиента (stateless). Каждый запрос должен содержать всё необходимое для обработки (например, токен авторизации в заголовке).
Пример запросов:GET /api/users → список пользователей
POST /api/users → создать нового пользователя
GET /api/users/123 → получить пользователя с id=123
PUT /api/users/123 → обновить данные пользователя 123
DELETE /api/users/123 → удалить пользователя 123
Ответы приходят в формате JSON — структурированные данные, которые легко читает клиент (веб или мобильное приложение).]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№12/вкратце-о-rest.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №12/Вкратце о REST.md</guid><pubDate>Tue, 14 Oct 2025 09:38:41 GMT</pubDate></item><item><title><![CDATA[Практика №4. Преобразование типов]]></title><description><![CDATA[В рамках этого задания вам необходимо модернизировать скрипт task4.js, который должен запускаться при помощи Node.js. Задание обязано быть опубликовано в существующем приватном репозитории организации GitHub с названием Группа_Фамилия_task-3-7.task4.jsconst booleanValue = false;
const numberValue = 20.20;
const stringValue = "30"; // Менять код ниже
Вам необходимо преобразовать значения переменных следующим образом: booleanValue — преобразовать в строку. numberValue — преобразовать в целое число, округлив в меньшую сторону (вниз). stringValue — преобразовать в число (числовой тип). После преобразования выведите в консоль исходное и преобразованное значение каждой переменной, а также тип данных каждого результата (используйте typeof). На выполнение выделяется 1 практическая пара.
Градация баллов после дедлайна: 1 пара: 0%
]]></description><link>задания/секция-1.-javascript/практика-№4.-преобразование-типов.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №4. Преобразование типов.md</guid><pubDate>Tue, 14 Oct 2025 09:38:41 GMT</pubDate></item><item><title><![CDATA[Объявление функции (Function Declaration)]]></title><description><![CDATA[Объявление функции (Function Declaration)Синтаксис объявления функции:function calculateSum(a, b) { return a + b;
}
Здесь calculateSum — имя функции, a и b — параметры. Функция вычисляет сумму и возвращает результат.Особенность функций, объявленных таким образом — поднятие (hoisting). Это значит, что JavaScript перемещает объявление функции в начало текущей области видимости при компиляции кода. Поэтому вы можете вызвать функцию до её объявления:// Это сработает!
console.log(calculateSum(5, 3)); // 8 function calculateSum(a, b) { return a + b;
}
Это работает только с объявлениями функций. Функциональные выражения и стрелочные функции таким свойством не обладают.Пример: форматирование даты для отображения в интерфейсеfunction formatDateString(dateString) { const date = new Date(dateString); return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });
} console.log(formatDateString('2024-06-15')); // 15 июня 2024 г.
Такая функция может использоваться в любом месте приложения, где нужно отобразить дату в понятном виде — например, в списке уведомлений или истории действий пользователя.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№9/объявление-функции-(function-declaration).html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №9/Объявление функции (Function Declaration).md</guid><pubDate>Tue, 14 Oct 2025 09:38:40 GMT</pubDate></item><item><title><![CDATA[Что такое ветвление]]></title><description><![CDATA[Ветвление — это механизм, при котором программа выбирает, какой участок кода выполнить, в зависимости от того, истинно или ложно условие.В любых программах это используется повсеместно: например, если пользователь авторизован — показываем главный экран, иначе — экран входа. Или если сеть доступна — загружаем данные, иначе — показываем сообщение об ошибке.В JavaScript ветвление реализуется с помощью условных конструкций: if, else, else if, switch и тернарного оператора.Без ветвления программа выполняет команды строго сверху вниз — как линейный список. С ветвлением она становится адаптивной: реагирует на данные, состояние системы, действия пользователя.Пример:const isLoggedIn = true; if (isLoggedIn) { console.log("Добро пожаловать!");
} else { console.log("Пожалуйста, войдите в аккаунт.");
}
Здесь программа ведёт себя по-разному в зависимости от значения isLoggedIn. Это и есть ветвление.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/что-такое-ветвление.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Что такое ветвление.md</guid><pubDate>Tue, 14 Oct 2025 09:38:36 GMT</pubDate></item><item><title><![CDATA[Практика №3. Вывод информации о себе в консоль.]]></title><description><![CDATA[В рамках этого задания вам необходимо создать скрипт task3.js, который должен запускаться при помощи NodeJs.Задание обязано быть опубликовано в новом приватном репозитории организации GitHub с названием Группа_Фамилия_task-3-7.(пусто)Вам необходимо создать следующие переменные:
год рождения
ваш возраст
ваше имя
работаете ли вы?
Вам необходимо вывести в консоль значения переменных и их типов данных.
Вы должны поменять значение возраста и вывести в консоль новый возраст.Используйте нужные ключевые слова и типы данных, при проверке вам необходимо обосновать выбор.На выполнение выделяется 1 практическая пара.
Градация баллов после дедлайна:
1 пара: 50%
]]></description><link>задания/секция-1.-javascript/практика-№3.-вывод-информации-о-себе-в-консоль..html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №3. Вывод информации о себе в консоль..md</guid><pubDate>Tue, 14 Oct 2025 09:38:36 GMT</pubDate></item><item><title><![CDATA[Оператор `else`]]></title><description><![CDATA[Оператор else используется вместе с if, чтобы указать, что нужно выполнить альтернативный блок кода, если условие в if ложно.Синтаксис:if (условие) { // выполнится, если условие истинно
} else { // выполнится, если условие ложно
}
else не имеет собственного условия — он всегда связан с ближайшим предыдущим if.Пример: проверка наличия интернет-соединенияconst isConnected = navigator.onLine; if (isConnected) { syncData();
} else { showOfflineMessage(); saveToLocalCache();
}
Здесь программа либо синхронизирует данные, либо показывает сообщение и сохраняет их локально — в зависимости от состояния сети. Нет третьего варианта — только два пути.
else не может существовать без if.
else выполняется, только если ни один из предыдущих if (или else if) не сработал.
Можно использовать else даже без фигурных скобок — но снова, всегда используйте скобки для ясности и безопасности.
]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№7/оператор-`else`.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №7/Оператор `else`.md</guid><pubDate>Tue, 14 Oct 2025 09:38:35 GMT</pubDate></item><item><title><![CDATA[Что такое цикл]]></title><description><![CDATA[Цикл — это конструкция, которая повторяет выполнение блока кода, пока выполняется заданное условие.Каждое повторение называется итерацией. Например, если вы перебираете 10 элементов массива — это 10 итераций.Циклы нужны, чтобы не писать один и тот же код десятки раз. Без них пришлось бы вручную обрабатывать каждый элемент списка, что невозможно при динамических данных.Пример: у вас есть список задач. Вы хотите вывести каждую в консоль. Без цикла — 10 строк кода. С циклом — одна.const tasks = ["Починить кнопку", "Обновить API", "Проверить стиль"]; for (let i = 0; i &lt; tasks.length; i++) { console.log(tasks[i]);
}
Также циклы используются для генерации данных: например, создание 100 случайных чисел, или заполнение списка пунктов меню.Циклы — это основа работы с коллекциями. Без них невозможно построить интерактивный интерфейс с динамическим содержимым.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№8/что-такое-цикл.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №8/Что такое цикл.md</guid><pubDate>Tue, 14 Oct 2025 09:38:35 GMT</pubDate></item><item><title><![CDATA[Что такое область видимости]]></title><description><![CDATA[Область видимости — это часть кода, в пределах которой переменная или функция доступна для использования.Если переменная объявлена внутри определённой области — она видна только в ней и во всех вложенных областях. Если объявлена вне — она доступна повсюду. Это позволяет изолировать данные, чтобы они не мешали друг другу.Без правильного управления областью видимости:
Переменные случайно перезаписываются
Сложно отлаживать код
Возникают неожиданные ошибки, особенно при росте приложения
Пример:let userName = "Анна"; // глобальная переменная function setUserName() { let userName = "Иван"; // локальная переменная, не перезаписывает глобальную console.log(userName); // "Иван"
} setUserName();
console.log(userName); // "Анна" — не изменилось
Здесь две переменные с одинаковым именем, но в разных областях. Они не мешают друг другу. Это и есть суть области видимости.]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№10/что-такое-область-видимости.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №10/Что такое область видимости.md</guid><pubDate>Tue, 14 Oct 2025 09:38:35 GMT</pubDate></item><item><title><![CDATA[Тема №4. Node.JS, примитивные типы данных JavaScript]]></title><description><![CDATA[В этой теме вы познакомитесь с Node.js — средой выполнения JavaScript вне браузера, и углубитесь в изучение примитивных типов данных JavaScript — фундаментальных строительных блоков любого приложения. Вы узнаете, как Node.js расширяет возможности JavaScript для серверной разработки, и научитесь работать с основными типами: числа, строки, логические значения, null, undefined, symbol и bigint. Это знание необходимо для дальнейшего понимания структур данных, функций и работы с API в мобильных приложениях, использующих JavaScript/TypeScript.
<a data-href="Что такое Node.js" href="материалы/подтемы/секция-1.-javascript/тема-№4/что-такое-node.js.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое Node.js</a>
<br><a data-href="Установка и базовое использование Node.js" href="материалы/подтемы/секция-1.-javascript/тема-№4/установка-и-базовое-использование-node.js.html" class="internal-link" target="_self" rel="noopener nofollow">Установка и базовое использование Node.js</a>
<br><a data-href="Примитивные типы данных JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№4/примитивные-типы-данных-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Примитивные типы данных JavaScript</a> <br><a data-href="Практика №3. Вывод информации о себе в консоль." href="задания/секция-1.-javascript/практика-№3.-вывод-информации-о-себе-в-консоль..html" class="internal-link" target="_self" rel="noopener nofollow">Практика №3. Вывод информации о себе в консоль.</a>
<br><a data-href="Практика №4. Преобразование типов" href="задания/секция-1.-javascript/практика-№4.-преобразование-типов.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №4. Преобразование типов</a>
<br><a data-href="Тема №5. Операторы и операции в JavaScript" href="лекции/секция-1.-javascript/тема-№5.-операторы-и-операции-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №5. Операторы и операции в JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№4.-node.js,-примитивные-типы-данных-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №4. Node.JS, примитивные типы данных JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:33 GMT</pubDate></item><item><title><![CDATA[Тема №3. Использование JavaScript в браузере]]></title><description><![CDATA[В этой теме вы познакомитесь с практическим применением JavaScript в контексте веб-страниц: научитесь использовать консоль разработчика для тестирования кода, поймёте структуру HTML и роль DOM, освоите базовые способы взаимодействия с элементами страницы через JavaScript — получение, изменение содержимого и стилей. Вы создадите первую HTML-страницу с подключённым JavaScript, изучите корректные способы интеграции скриптов и назначения обработчиков событий, избегая устаревших практик.
<a data-href="Самое простое использование JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№3/самое-простое-использование-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Самое простое использование JavaScript</a>
<br><a data-href="Основные понятия веб страницы" href="материалы/подтемы/секция-1.-javascript/тема-№3/основные-понятия-веб-страницы.html" class="internal-link" target="_self" rel="noopener nofollow">Основные понятия веб страницы</a>
<br><a data-href="Базовая работа с элементами веб страницы через JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№3/базовая-работа-с-элементами-веб-страницы-через-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Базовая работа с элементами веб страницы через JavaScript</a>
<br><a data-href="Создание своей HTML страницы" href="материалы/подтемы/секция-1.-javascript/тема-№3/создание-своей-html-страницы.html" class="internal-link" target="_self" rel="noopener nofollow">Создание своей HTML страницы</a> <br><a data-href="Практика №1. Простая веб-страница с HTML" href="задания/секция-1.-javascript/практика-№1.-простая-веб-страница-с-html.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №1. Простая веб-страница с HTML</a>
<br><a data-href="Тема №4. Node.JS, примитивные типы данных JavaScript" href="лекции/секция-1.-javascript/тема-№4.-node.js,-примитивные-типы-данных-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №4. Node.JS, примитивные типы данных JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№3.-использование-javascript-в-браузере.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №3. Использование JavaScript в браузере.md</guid><pubDate>Tue, 14 Oct 2025 09:38:33 GMT</pubDate></item><item><title><![CDATA[Тема №5. Операторы и операции в JavaScript]]></title><description><![CDATA[В этой теме вы изучите основные операторы и операции языка JavaScript, которые позволяют выполнять вычисления, сравнивать значения, управлять логикой программы и изменять данные. Понимание операторов — база для написания условий, циклов и обработки данных в мобильных приложениях. Особое внимание уделено особенностям JavaScript: неявному приведению типов, различиям между строгим и нестрогим сравнением, а также операторам присваивания и распространения.
<a data-href="Определение оператора и операнда" href="материалы/подтемы/секция-1.-javascript/тема-№5/определение-оператора-и-операнда.html" class="internal-link" target="_self" rel="noopener nofollow">Определение оператора и операнда</a>
<br><a data-href="Арифметические операторы JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№5/арифметические-операторы-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Арифметические операторы JavaScript</a>
<br><a data-href="Операторы сравнения JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№5/операторы-сравнения-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Операторы сравнения JavaScript</a>
<br><a data-href="Логические операторы JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№5/логические-операторы-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Логические операторы JavaScript</a>
<br><a data-href="Операторы присваивания JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№5/операторы-присваивания-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Операторы присваивания JavaScript</a>
<br><a data-href="Операторы работы с битами" href="материалы/подтемы/секция-1.-javascript/тема-№5/операторы-работы-с-битами.html" class="internal-link" target="_self" rel="noopener nofollow">Операторы работы с битами</a>
<br><a data-href="Приоритет операторов и ассоциативность" href="материалы/подтемы/секция-1.-javascript/тема-№5/приоритет-операторов-и-ассоциативность.html" class="internal-link" target="_self" rel="noopener nofollow">Приоритет операторов и ассоциативность</a>
(Пусто)<br><a data-href="Тема №6. Git, GitHub" href="лекции/секция-1.-javascript/тема-№6.-git,-github.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №6. Git, GitHub</a>]]></description><link>лекции/секция-1.-javascript/тема-№5.-операторы-и-операции-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №5. Операторы и операции в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:33 GMT</pubDate></item><item><title><![CDATA[Практика №2. Использование git, github]]></title><description><![CDATA[В рамках этого задания вам необходимо загрузить код "Практика №1" в github организацию в виде нового репозитория.(пусто)Регистрируйтесь на <a data-tooltip-position="top" aria-label="https://github.com" rel="noopener nofollow" class="external-link is-unresolved" href="https://github.com" target="_self">GitHub</a>, затем отправьте почту в <a data-tooltip-position="top" aria-label="https://forms.yandex.ru/u/68c460fe90fa7b550e338c06" rel="noopener nofollow" class="external-link is-unresolved" href="https://forms.yandex.ru/u/68c460fe90fa7b550e338c06" target="_self">яндекс формы</a>.
Вам должно будет прийти письмо с приглашением на вступление (Проверяйте указанную почту и/или оповещения в GitHub).Необходимо создать ПРИВАТНЫЙ репозиторий ВНУТРИ ОРГАНИЗАЦИИ.
Название по следующему шаблону:
ГРУППА_ФАМИЛИЯ_НАЗВАНИЕ-ЗАДАНИЯ
Например:
IS231-1_Ivanov_task1.На выполнение выделяется 1 практическая пара.
Градация баллов после дедлайна:
1 пара: 0%
]]></description><link>задания/секция-1.-javascript/практика-№2.-использование-git,-github.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №2. Использование git, github.md</guid><pubDate>Tue, 14 Oct 2025 09:38:33 GMT</pubDate></item><item><title><![CDATA[Практика №6. Вывод таблицы умножения с помощью цикла for]]></title><description><![CDATA[В рамках этого задания вам необходимо создать скрипт task6.js, который должен запускаться при помощи Node.js. Задание обязано быть опубликовано в существующем приватном репозитории организации GitHub с названием Группа_Фамилия_task-3-7.(Пусто)Необходимо вывести в консоль таблицу умножения от 1х0 до 20х20. Формат произвольный, но таблицы должны быть с правильными отступами (т.е. числа должны отцентрованны по правому краю), а сами таблицы должны быть удобными для чтения.На выполнение выделяется 2 практических пары.
Градация баллов после дедлайна: 1 пара: 50%
2 пара: 25%
3 пара: 0%
]]></description><link>задания/секция-1.-javascript/практика-№6.-вывод-таблицы-умножения-с-помощью-цикла-for.html</link><guid isPermaLink="false">Задания/Секция 1. JavaScript/Практика №6. Вывод таблицы умножения с помощью цикла for.md</guid><pubDate>Tue, 14 Oct 2025 09:38:32 GMT</pubDate></item><item><title><![CDATA[Тема №12. Создание сервера NodeJS. WEB 1.0 и WEB 2.0]]></title><description><![CDATA[В этой теме вы изучите основы создания сервера на NodeJS и эволюцию веб-архитектур — от статического веба (WEB 1.0) до интерактивных приложений с динамической генерацией контента (WEB 2.0). Вы поймёте, как сервер обрабатывает запросы, отдаёт файлы и отвечает JSON-данными. Также разберёте ключевые подходы: SSR и CSR, а также основы маршрутизации и работы с файловой системой.
<a data-href="WEB 1.0 (статический веб)" href="материалы/подтемы/секция-1.-javascript/тема-№12/web-1.0-(статический-веб).html" class="internal-link" target="_self" rel="noopener nofollow">WEB 1.0 (статический веб)</a>
<br><a data-href="WEB 2.0 (интерактивный веб)" href="материалы/подтемы/секция-1.-javascript/тема-№12/web-2.0-(интерактивный-веб).html" class="internal-link" target="_self" rel="noopener nofollow">WEB 2.0 (интерактивный веб)</a>
<br><a data-href="Основы сервера на NodeJS" href="материалы/подтемы/секция-1.-javascript/тема-№12/основы-сервера-на-nodejs.html" class="internal-link" target="_self" rel="noopener nofollow">Основы сервера на NodeJS</a>
<br><a data-href="Разница между WEB 1.0 и WEB 2.0 в контексте NodeJS" href="материалы/подтемы/секция-1.-javascript/тема-№12/разница-между-web-1.0-и-web-2.0-в-контексте-nodejs.html" class="internal-link" target="_self" rel="noopener nofollow">Разница между WEB 1.0 и WEB 2.0 в контексте NodeJS</a>
<br><a data-href="Маршрутизация в NodeJS" href="материалы/подтемы/секция-1.-javascript/тема-№12/маршрутизация-в-nodejs.html" class="internal-link" target="_self" rel="noopener nofollow">Маршрутизация в NodeJS</a>
<br><a data-href="Отправка файлов с сервера" href="материалы/подтемы/секция-1.-javascript/тема-№12/отправка-файлов-с-сервера.html" class="internal-link" target="_self" rel="noopener nofollow">Отправка файлов с сервера</a>
<br><a data-href="Вкратце о REST" href="материалы/подтемы/секция-1.-javascript/тема-№12/вкратце-о-rest.html" class="internal-link" target="_self" rel="noopener nofollow">Вкратце о REST</a> <br><a data-href="Практика №8. SSR-сервер с динамической генерацией страниц" href="задания/секция-1.-javascript/практика-№8.-ssr-сервер-с-динамической-генерацией-страниц.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №8. SSR-сервер с динамической генерацией страниц</a>
<br><a data-href="Практика №9. CSR с гидратацией. Интерактивный счётчик" href="задания/секция-1.-javascript/практика-№9.-csr-с-гидратацией.-интерактивный-счётчик.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №9. CSR с гидратацией. Интерактивный счётчик</a>
<br><a data-href="Тема №13. Основы React" href="лекции/секция-2.-react/тема-№13.-основы-react.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №13. Основы React</a>]]></description><link>лекции/секция-1.-javascript/тема-№12.-создание-сервера-nodejs.-web-1.0-и-web-2.0.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №12. Создание сервера NodeJS. WEB 1.0 и WEB 2.0.md</guid><pubDate>Tue, 14 Oct 2025 09:38:32 GMT</pubDate></item><item><title><![CDATA[Тема №9. Функции в JavaScript]]></title><description><![CDATA[В этой теме вы изучите функции — основной механизм инкапсуляции логики в JavaScript. Поймёте, как объявлять, вызывать и передавать данные через функции, а также познакомитесь с разными способами их определения. Это фундамент для организации кода в любом приложении, включая мобильные, где функции используются для обработки событий, работы с данными и управления состоянием интерфейса.
<a data-href="Что такое функция" href="материалы/подтемы/секция-1.-javascript/тема-№9/что-такое-функция.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое функция</a>
<br><a data-href="Объявление функции (Function Declaration)" href="материалы/подтемы/секция-1.-javascript/тема-№9/объявление-функции-(function-declaration).html" class="internal-link" target="_self" rel="noopener nofollow">Объявление функции (Function Declaration)</a>
<br><a data-href="Функциональное выражение (Function Expression)" href="материалы/подтемы/секция-1.-javascript/тема-№9/функциональное-выражение-(function-expression).html" class="internal-link" target="_self" rel="noopener nofollow">Функциональное выражение (Function Expression)</a>
<br><a data-href="Стрелочные функции (Arrow Function)" href="материалы/подтемы/секция-1.-javascript/тема-№9/стрелочные-функции-(arrow-function).html" class="internal-link" target="_self" rel="noopener nofollow">Стрелочные функции (Arrow Function)</a>
<br><a data-href="Параметры и аргументы" href="материалы/подтемы/секция-1.-javascript/тема-№9/параметры-и-аргументы.html" class="internal-link" target="_self" rel="noopener nofollow">Параметры и аргументы</a>
<br><a data-href="Возвращаемое значение" href="материалы/подтемы/секция-1.-javascript/тема-№9/возвращаемое-значение.html" class="internal-link" target="_self" rel="noopener nofollow">Возвращаемое значение</a>
<br><a data-href="Рекурсия" href="материалы/подтемы/секция-1.-javascript/тема-№9/рекурсия.html" class="internal-link" target="_self" rel="noopener nofollow">Рекурсия</a> <br><a data-href="Практика №7. Функции для работы с строками" href="задания/секция-1.-javascript/практика-№7.-функции-для-работы-с-строками.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №7. Функции для работы с строками</a>
<br><a data-href="Тема №10. Область видимости в JavaScript" href="лекции/секция-1.-javascript/тема-№10.-область-видимости-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №10. Область видимости в JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№9.-функции-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №9. Функции в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:31 GMT</pubDate></item><item><title><![CDATA[Тема №10. Область видимости в JavaScript]]></title><description><![CDATA[В этой теме вы изучите область видимости переменных — механизм, определяющий, где в коде доступны объявленные переменные и функции. Поймёте разницу между глобальной, функциональной и блочной областью видимости, а также как это влияет на структуру и надёжность кода. Это ключевое понимание для предотвращения ошибок при работе с переменными в любых приложениях, включая мобильные.
<a data-href="Что такое область видимости" href="материалы/подтемы/секция-1.-javascript/тема-№10/что-такое-область-видимости.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое область видимости</a>
<br><a data-href="Глобальная область видимости" href="материалы/подтемы/секция-1.-javascript/тема-№10/глобальная-область-видимости.html" class="internal-link" target="_self" rel="noopener nofollow">Глобальная область видимости</a>
<br><a data-href="Функциональная область видимости" href="материалы/подтемы/секция-1.-javascript/тема-№10/функциональная-область-видимости.html" class="internal-link" target="_self" rel="noopener nofollow">Функциональная область видимости</a>
<br><a data-href="Блочная область видимости" href="материалы/подтемы/секция-1.-javascript/тема-№10/блочная-область-видимости.html" class="internal-link" target="_self" rel="noopener nofollow">Блочная область видимости</a>
<br><a data-href="Вложенность областей видимости" href="материалы/подтемы/секция-1.-javascript/тема-№10/вложенность-областей-видимости.html" class="internal-link" target="_self" rel="noopener nofollow">Вложенность областей видимости</a>
<br><a data-href="Замыкания" href="материалы/подтемы/секция-1.-javascript/тема-№10/замыкания.html" class="internal-link" target="_self" rel="noopener nofollow">Замыкания</a>
<br><a data-href="Практические последствия (var)" href="материалы/подтемы/секция-1.-javascript/тема-№10/практические-последствия-(var).html" class="internal-link" target="_self" rel="noopener nofollow">Практические последствия (var)</a>
(Пусто)<br><a data-href="Тема №11. Массивы и объекты в JavaScript" href="лекции/секция-1.-javascript/тема-№11.-массивы-и-объекты-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №11. Массивы и объекты в JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№10.-область-видимости-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №10. Область видимости в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:30 GMT</pubDate></item><item><title><![CDATA[Тема №6. Git, GitHub]]></title><description><![CDATA[В этой теме вы познакомитесь с системой контроля версий Git и платформой GitHub — основными инструментами для управления кодом в командной разработке. Изучите базовые команды для отслеживания изменений, создания коммитов и взаимодействия с удалённым репозиторием. Это необходимо для совместной работы над мобильными приложениями, а также для хранения и публикации вашего кода.
<a data-href="Что такое Git" href="материалы/подтемы/секция-1.-javascript/тема-№6/что-такое-git.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое Git</a>
<br><a data-href="Основные понятия Git" href="материалы/подтемы/секция-1.-javascript/тема-№6/основные-понятия-git.html" class="internal-link" target="_self" rel="noopener nofollow">Основные понятия Git</a>
<br><a data-href="Базовые команды Git" href="материалы/подтемы/секция-1.-javascript/тема-№6/базовые-команды-git.html" class="internal-link" target="_self" rel="noopener nofollow">Базовые команды Git</a>
<br><a data-href="Работа с ветками Git" href="материалы/подтемы/секция-1.-javascript/тема-№6/работа-с-ветками-git.html" class="internal-link" target="_self" rel="noopener nofollow">Работа с ветками Git</a>
<br><a data-href="Что такое GitHub" href="материалы/подтемы/секция-1.-javascript/тема-№6/что-такое-github.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое GitHub</a>
<br><a data-href="Работа с удалёнными репозиториями" href="материалы/подтемы/секция-1.-javascript/тема-№6/работа-с-удалёнными-репозиториями.html" class="internal-link" target="_self" rel="noopener nofollow">Работа с удалёнными репозиториями</a>
<br><a data-href="Файл .gitignore" href="материалы/подтемы/секция-1.-javascript/тема-№6/файл-.gitignore.html" class="internal-link" target="_self" rel="noopener nofollow">Файл .gitignore</a>
<br><a data-href="Рекомендации по использованию Git" href="материалы/подтемы/секция-1.-javascript/тема-№6/рекомендации-по-использованию-git.html" class="internal-link" target="_self" rel="noopener nofollow">Рекомендации по использованию Git</a> <br><a data-href="Практика №2. Использование git, github" href="задания/секция-1.-javascript/практика-№2.-использование-git,-github.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №2. Использование git, github</a>
<br><a data-href="Тема №7. Ветвление в JavaScript" href="лекции/секция-1.-javascript/тема-№7.-ветвление-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №7. Ветвление в JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№6.-git,-github.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №6. Git, GitHub.md</guid><pubDate>Tue, 14 Oct 2025 09:38:30 GMT</pubDate></item><item><title><![CDATA[Тема №2. Основы JavaScript]]></title><description><![CDATA[В этой теме вы познакомитесь с основами JavaScript — языком, лежащим в основе интерактивности современных веб- и мобильных приложений. Рассмотрите историю появления языка, его ключевые характеристики и области применения. Вы узнаете, как устроен простейший код на JavaScript, изучите базовые элементы синтаксиса, а также детально разберёте переменные — их объявление и правила именования. Всё это — фундамент для дальнейшего изучения разработки мобильных приложений на JavaScript-основах.
<a data-href="Что такое JavaScript, история появления" href="материалы/подтемы/секция-1.-javascript/тема-№2/что-такое-javascript,-история-появления.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое JavaScript, история появления</a>
<br><a data-href="Базовое понимание синтаксиса JavaScript" href="материалы/подтемы/секция-1.-javascript/тема-№2/базовое-понимание-синтаксиса-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Базовое понимание синтаксиса JavaScript</a>
(Пусто)<br><a data-href="Тема №3. Использование JavaScript в браузере" href="лекции/секция-1.-javascript/тема-№3.-использование-javascript-в-браузере.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №3. Использование JavaScript в браузере</a>]]></description><link>лекции/секция-1.-javascript/тема-№2.-основы-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №2. Основы JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:28 GMT</pubDate></item><item><title><![CDATA[Тема №11. Массивы и объекты в JavaScript]]></title><description><![CDATA[В этой теме вы изучите два фундаментальных типа данных в JavaScript — массивы и объекты — которые используются для структурирования и хранения информации: от списков элементов интерфейса до ответов API. Поймёте, как создавать, изменять и перебирать эти структуры, а также узнаете о различиях между ними и их практическом применении.
<a data-href="Массивы" href="материалы/подтемы/секция-1.-javascript/тема-№11/массивы.html" class="internal-link" target="_self" rel="noopener nofollow">Массивы</a>
<br><a data-href="Объекты" href="материалы/подтемы/секция-1.-javascript/тема-№11/объекты.html" class="internal-link" target="_self" rel="noopener nofollow">Объекты</a>
<br><a data-href="Распаковка (spread)" href="материалы/подтемы/секция-1.-javascript/тема-№11/распаковка-(spread).html" class="internal-link" target="_self" rel="noopener nofollow">Распаковка (spread)</a>
<br><a data-href="Оператор rest" href="материалы/подтемы/секция-1.-javascript/тема-№11/оператор-rest.html" class="internal-link" target="_self" rel="noopener nofollow">Оператор rest</a>
<br><a data-href="Вложенные структуры" href="материалы/подтемы/секция-1.-javascript/тема-№11/вложенные-структуры.html" class="internal-link" target="_self" rel="noopener nofollow">Вложенные структуры</a>
<br><a data-href="Преобразование типов (Массивы и Объекты) через JSON" href="материалы/подтемы/секция-1.-javascript/тема-№11/преобразование-типов-(массивы-и-объекты)-через-json.html" class="internal-link" target="_self" rel="noopener nofollow">Преобразование типов (Массивы и Объекты) через JSON</a>
<br><a data-href="Практические рекомендации по массивам и объектам" href="материалы/подтемы/секция-1.-javascript/тема-№11/практические-рекомендации-по-массивам-и-объектам.html" class="internal-link" target="_self" rel="noopener nofollow">Практические рекомендации по массивам и объектам</a>
(Пусто)<br><a data-href="Тема №12. Создание сервера NodeJS. WEB 1.0 и WEB 2.0" href="лекции/секция-1.-javascript/тема-№12.-создание-сервера-nodejs.-web-1.0-и-web-2.0.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №12. Создание сервера NodeJS. WEB 1.0 и WEB 2.0</a>]]></description><link>лекции/секция-1.-javascript/тема-№11.-массивы-и-объекты-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №11. Массивы и объекты в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:25 GMT</pubDate></item><item><title><![CDATA[Определение оператора и операнда]]></title><description><![CDATA[Оператор — это символ или ключевое слово, которое выполняет определённое действие над данными.Операнд — это значение или переменная, над которой применяется оператор.Операторы классифицируются по количеству операндов, с которыми они работают:
Унарные операторы используют один операнд — например, отрицание !x или инкремент ++i.
Бинарные операторы работают с двумя операндами — например, сложение a + b или сравнение x &gt; y.
Тернарный оператор использует три операнда — единственный в JavaScript: условное выражение condition ? value1 : value2 (про него подробнее будет в следующей теме).]]></description><link>материалы/подтемы/секция-1.-javascript/тема-№5/определение-оператора-и-операнда.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №5/Определение оператора и операнда.md</guid><pubDate>Tue, 14 Oct 2025 09:38:23 GMT</pubDate></item><item><title><![CDATA[Тема №7. Ветвление в JavaScript]]></title><description><![CDATA[В этой теме вы изучите механизмы ветвления в JavaScript — основу логического управления потоком выполнения программы. Вы научитесь использовать условные конструкции для принятия решений на основе данных, что критически важно для реализации интерактивности.
<a data-href="Что такое ветвление" href="материалы/подтемы/секция-1.-javascript/тема-№7/что-такое-ветвление.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое ветвление</a>
<br><a data-href="Оператор `if`" href="материалы/подтемы/секция-1.-javascript/тема-№7/оператор-`if`.html" class="internal-link" target="_self" rel="noopener nofollow">Оператор `if`</a>
<br><a data-href="Оператор `else`" href="материалы/подтемы/секция-1.-javascript/тема-№7/оператор-`else`.html" class="internal-link" target="_self" rel="noopener nofollow">Оператор `else`</a>
<br><a data-href="Цепочки `else if`" href="материалы/подтемы/секция-1.-javascript/тема-№7/цепочки-`else-if`.html" class="internal-link" target="_self" rel="noopener nofollow">Цепочки `else if`</a>
<br><a data-href="Тернарный оператор" href="материалы/подтемы/секция-1.-javascript/тема-№7/тернарный-оператор.html" class="internal-link" target="_self" rel="noopener nofollow">Тернарный оператор</a>
<br><a data-href="Оператор `switch`" href="материалы/подтемы/секция-1.-javascript/тема-№7/оператор-`switch`.html" class="internal-link" target="_self" rel="noopener nofollow">Оператор `switch`</a>
<br><a data-href="Сравнение `if` и `switch`" href="материалы/подтемы/секция-1.-javascript/тема-№7/сравнение-`if`-и-`switch`.html" class="internal-link" target="_self" rel="noopener nofollow">Сравнение `if` и `switch`</a> <br><a data-href="Практика №5. Использование ветвления." href="задания/секция-1.-javascript/практика-№5.-использование-ветвления..html" class="internal-link" target="_self" rel="noopener nofollow">Практика №5. Использование ветвления.</a>
<br><a data-href="Тема №8. Циклы в JavaScript" href="лекции/секция-1.-javascript/тема-№8.-циклы-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №8. Циклы в JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№7.-ветвление-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №7. Ветвление в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:21 GMT</pubDate></item><item><title><![CDATA[Тема №8. Циклы в JavaScript]]></title><description><![CDATA[В этой теме вы изучите циклические конструкции языка JavaScript — фундаментальный механизм для повторения действий. Поймёте, как организовать итерации над данными, что необходимо для обработки списков, массивов и других структур, используемых в приложениях любого типа.
<a data-href="Что такое цикл" href="материалы/подтемы/секция-1.-javascript/тема-№8/что-такое-цикл.html" class="internal-link" target="_self" rel="noopener nofollow">Что такое цикл</a>
<br><a data-href="Цикл for" href="материалы/подтемы/секция-1.-javascript/тема-№8/цикл-for.html" class="internal-link" target="_self" rel="noopener nofollow">Цикл for</a>
<br><a data-href="Цикл while" href="материалы/подтемы/секция-1.-javascript/тема-№8/цикл-while.html" class="internal-link" target="_self" rel="noopener nofollow">Цикл while</a>
<br><a data-href="Прерывание и пропуск итераций" href="материалы/подтемы/секция-1.-javascript/тема-№8/прерывание-и-пропуск-итераций.html" class="internal-link" target="_self" rel="noopener nofollow">Прерывание и пропуск итераций</a>
<br><a data-href="Циклы и производительность" href="материалы/подтемы/секция-1.-javascript/тема-№8/циклы-и-производительность.html" class="internal-link" target="_self" rel="noopener nofollow">Циклы и производительность</a> <br><a data-href="Практика №6. Вывод таблицы умножения с помощью цикла for" href="задания/секция-1.-javascript/практика-№6.-вывод-таблицы-умножения-с-помощью-цикла-for.html" class="internal-link" target="_self" rel="noopener nofollow">Практика №6. Вывод таблицы умножения с помощью цикла for</a>
<br><a data-href="Тема №9. Функции в JavaScript" href="лекции/секция-1.-javascript/тема-№9.-функции-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №9. Функции в JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№8.-циклы-в-javascript.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №8. Циклы в JavaScript.md</guid><pubDate>Tue, 14 Oct 2025 09:38:20 GMT</pubDate></item><item><title><![CDATA[Как создавать файлы с определённым расширением]]></title><description><![CDATA[Самый простой способ - создать файл через "проводник".
<img alt="Pasted image 20250912214611.png" src="материалы/файлы/pasted-image-20250912214611.png" target="_self">
Но для этого нужно сначала включить опцию чтобы мы могли видеть расширение файлов (по умолчанию оно скрыто, особенно на компьютерах колледжа).<br>
<img alt="Pasted image 20250912214624.png" src="материалы/файлы/pasted-image-20250912214624.png" target="_self">
Ну а дальше уже все просто, например нам нужно создать js файл&nbsp;example.js<br>
<img alt="Pasted image 20250912214643.png" src="материалы/файлы/pasted-image-20250912214643.png" target="_self"><br>
<img alt="Pasted image 20250912214649.png" src="материалы/файлы/pasted-image-20250912214649.png" target="_self"><img alt="Pasted image 20250912214653.png" src="материалы/файлы/pasted-image-20250912214653.png" target="_self">]]></description><link>материалы/как-сделать/как-создавать-файлы-с-определённым-расширением.html</link><guid isPermaLink="false">Материалы/Как сделать/Как создавать файлы с определённым расширением.md</guid><pubDate>Tue, 14 Oct 2025 09:38:09 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Pasted image 20240928222237]]></title><description><![CDATA[<img src="материалы/файлы/pasted-image-20240928222237.png" target="_self">]]></description><link>материалы/файлы/pasted-image-20240928222237.html</link><guid isPermaLink="false">Материалы/Файлы/Pasted image 20240928222237.png</guid><pubDate>Tue, 14 Oct 2025 09:38:07 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Тема №1. Как создаются мобильные приложения]]></title><description><![CDATA[Вводная тема, посвящённая базовым понятиям разработки мобильных приложений. <a data-href="Основные платформы мобильных приложений" href="материалы/подтемы/секция-1.-javascript/тема-№1/основные-платформы-мобильных-приложений.html" class="internal-link" target="_self" rel="noopener nofollow">Основные платформы мобильных приложений</a>
<br><a data-href="Основные типы мобильных приложений" href="материалы/подтемы/секция-1.-javascript/тема-№1/основные-типы-мобильных-приложений.html" class="internal-link" target="_self" rel="noopener nofollow">Основные типы мобильных приложений</a>
<br><a data-href="Основные технологии для разработки мобильных приложений" href="материалы/подтемы/секция-1.-javascript/тема-№1/основные-технологии-для-разработки-мобильных-приложений.html" class="internal-link" target="_self" rel="noopener nofollow">Основные технологии для разработки мобильных приложений</a>
(Пусто)<br><a data-href="Тема №2. Основы JavaScript" href="лекции/секция-1.-javascript/тема-№2.-основы-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №2. Основы JavaScript</a>]]></description><link>лекции/секция-1.-javascript/тема-№1.-как-создаются-мобильные-приложения.html</link><guid isPermaLink="false">Лекции/Секция 1. JavaScript/Тема №1. Как создаются мобильные приложения.md</guid><pubDate>Tue, 14 Oct 2025 09:38:07 GMT</pubDate></item><item><title><![CDATA[index]]></title><description><![CDATA[<a rel="noopener nofollow" class="external-link is-unresolved" href="https://t.me/+3RqHSkYzaXUyMTUy" target="_self">https://t.me/+3RqHSkYzaXUyMTUy</a><br><img alt="Pasted image 20250912205946.png" src="материалы/файлы/pasted-image-20250912205946.png" target="_self"><br><img alt="qrcod_72k5.png" src="материалы/файлы/qrcod_72k5.png" target="_self"><br><a data-href="Тема №1. Как создаются мобильные приложения" href="лекции/секция-1.-javascript/тема-№1.-как-создаются-мобильные-приложения.html" class="internal-link" target="_self" rel="noopener nofollow">Тема №1. Как создаются мобильные приложения</a>]]></description><link>index.html</link><guid isPermaLink="false">index.md</guid><pubDate>Tue, 14 Oct 2025 09:37:53 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Базовые понятия Git]]></title><link>материалы/подтемы/секция-1.-javascript/тема-№6/базовые-понятия-git.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Тема №6/Базовые понятия Git.md</guid><pubDate>Fri, 19 Sep 2025 18:01:25 GMT</pubDate></item><item><title><![CDATA[Приоритет операторов и ассоциативность]]></title><description><![CDATA[Приоритет операторов определяет порядок, в котором выполняются операции в выражении, когда скобки не указаны. Ассоциативность — направление вычисления (слева направо или справа налево), если операторы имеют одинаковый приоритет.
🔹 Важно: Операторы одной группы имеют одинаковый приоритет и выполняются в соответствии с ассоциативностью.
let result = 5 + 3 * 2;
// Выполняется как: 5 + (3 * 2) → 5 + 6 → 11
Умножение (*) имеет более высокий приоритет, чем сложение (+) — поэтому умножение выполняется первым.let a = true;
let b = false;
let c = true; let result = a || b &amp;&amp; c;
// Выполняется как: a || (b &amp;&amp; c) → true || (false &amp;&amp; true) → true || false → true
Оператор &amp;&amp; выше по приоритету, чем || — поэтому сначала вычисляется b &amp;&amp; c.let x = 10;
let y = x &gt; 5 ? "да" : x &lt; 3 ? "нет" : "не знаю";
// Эквивалентно: x &gt; 5 ? "да" : (x &lt; 3 ? "нет" : "не знаю")
Тернарный оператор ?: ассоциативен справа налево, поэтому вложенные условия обрабатываются корректно.let a = 1, b = 2, c = 3;
a = b += c *= 2;
// Выполняется как: c *= 2 → c = 6; b += c → b = 8; a = b → a = 8
// Порядок: справа налево, потому что `=` и составные операторы присваивания ассоциативны справа
Скобки — это не просто формальность. Они делают код предсказуемым и понятным даже для того, кто читает его впервые.if (user.isAdmin &amp;&amp; user.isActive || user.isGuest) { ... }
Что здесь реально проверяется?
→ (user.isAdmin &amp;&amp; user.isActive) || user.isGuestА если вы хотели:
→ user.isAdmin &amp;&amp; (user.isActive || user.isGuest)?Разница критична.if (user.isAdmin &amp;&amp; (user.isActive || user.isGuest)) { ... }
— Чётко видно намерение.// Без скобок — легко ошибиться
if (age &gt;= 18 &amp;&amp; role === 'admin' || role === 'moderator') { ... } // Скобки спасают
if (age &gt;= 18 &amp;&amp; (role === 'admin' || role === 'moderator')) { ... } Никогда не полагайтесь на память о приоритетах
Даже опытные разработчики ошибаются. Если есть сомнения — используйте скобки. Разбивайте сложные выражения на части
Вместо:
const isValid = !isEmpty &amp;&amp; (value.length &gt;= 5 &amp;&amp; value.includes("@")) || isTemp; Лучше:
const isEmpty = value.trim().length === 0;
const hasAtSymbol = value.includes("@");
const meetsLength = value.length &gt;= 5;
const isValid = !isEmpty &amp;&amp; (meetsLength &amp;&amp; hasAtSymbol) || isTemp; Используйте переносы для многострочных условий
if (user &amp;&amp; user.profile &amp;&amp; user.profile.isActive &amp;&amp; (user.role === 'admin' || user.role === 'editor')) { showDashboard();
} Не пишите «умные» однострочные конструкции ради экономии строк
Например:
// ❌ Непонятно
result = a &amp;&amp; b ? c : d || e; // ✅ Ясно
if (a &amp;&amp; b) { result = c;
} else { result = d || e;
} Для логических выражений — комментируйте намерение // Разрешить доступ, если пользователь админ ИЛИ (зарегистрирован и активен)
const canAccess = user.role === 'admin' || (user.registered &amp;&amp; user.active); ]]></description><link>материалы/подтемы/секция-1.-javascript/приоритет-операторов-и-ассоциативность.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Приоритет операторов и ассоциативность.md</guid><pubDate>Wed, 17 Sep 2025 18:57:14 GMT</pubDate></item><item><title><![CDATA[Операторы работы с битами]]></title><description><![CDATA[Операторы работы с битами выполняют операции на уровне отдельных битов целочисленных значений. В мобильной разработке они встречаются редко, но могут быть полезны при оптимизации хранения флагов, работе с сетевыми протоколами, обработке изображений или взаимодействии с нативными модулями.Все битовые операции в JavaScript работают с 32-битными целыми числами. Любые числа перед операцией приводятся к этому формату (дробные части отбрасываются).Часто используется для хранения нескольких булевых состояний в одном числе.const READ = 1; // 0001
const WRITE = 2; // 0010
const EXEC = 4; // 0100
const DELETE = 8; // 1000 let permissions = READ | WRITE | EXEC; // 0111 = 7 // Проверяем, есть ли право на чтение:
if (permissions &amp; READ) { console.log("Можно читать"); // выполнится
} // Проверяем, есть ли право на удаление:
if (permissions &amp; DELETE) { console.log("Можно удалять"); // не выполнится
} ✅ Экономит память и ускоряет проверки в низкоуровневых сценариях — например, при передаче прав доступа через API или хранении настроек в локальном хранилище.
Объединяет несколько флагов в одно значение:let flags = 0;
flags |= READ; // 0001
flags |= WRITE; // 0011
flags |= EXEC; // 0111 console.log(flags); // 7
Используется для инвертирования конкретного флага:let theme = 0; // 0 — светлая, 1 — тёмная
theme ^= 1; // теперь theme = 1
theme ^= 1; // теперь theme = 0
Также применяется в алгоритмах шифрования или генерации контрольных сумм.Применяется для преобразования чисел и часто встречается в сочетании с indexOf:const arr = ["apple", "banana", "cherry"];
const index = arr.indexOf("banana"); if (~index) { // эквивалентно: if (index !== -1) console.log("Найдено");
} ❗ Устаревший стиль. Современный код предпочтительно пишет так:
if (index !== -1) — более читаемо и понятно.
console.log(5 &lt;&lt; 1); // 10 → 5 * 2¹
console.log(5 &lt;&lt; 2); // 20 → 5 * 2²
console.log(1 &lt;&lt; 3); // 8 → 2³ ⚠️ Работает только с целыми числами. Не заменяет Math.pow() для дробных степеней.
Полезно при оптимизации вычислений в играх, графических движках или обработке сигналов.console.log(8 &gt;&gt; 1); // 4 → 8 / 2
console.log(-8 &gt;&gt; 1); // -4 — знак сохранён
Сохраняет знак числа — подходит для целочисленного деления на 2, 4, 8 и т.д.Преобразует отрицательные числа в большие положительные:console.log(-8 &gt;&gt;&gt; 1); // 2147483644 — интерпретируется как беззнаковое число Используется редко — в основном при работе с бинарными данными (например, Uint32Array, WebAssembly). Хранение флагов в одной переменной: например, права пользователя, состояние UI-элемента, режимы приложения.
Оптимизация производительности: в низкоуровневых системах (игры, аудио/видео обработка).
Работа с нативными модулями: когда приложение использует JNI (Android) или Objective-C/Swift-код, где данные передаются как битовые маски.
Компрессия данных: при отправке маленьких наборов булевых значений через API.
]]></description><link>материалы/подтемы/секция-1.-javascript/операторы-работы-с-битами.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Операторы работы с битами.md</guid><pubDate>Wed, 17 Sep 2025 18:50:09 GMT</pubDate></item><item><title><![CDATA[Операторы присваивания JavaScript]]></title><description><![CDATA[Операторы присваивания используются для записи значений в переменные. В JavaScript они делятся на базовые и составные, а также включают современные операторы, упрощающие работу с потенциально отсутствующими данными.Присваивает значение справа переменной слева.let count = 0;
let message = "Привет";
let isActive = true; Это единственный оператор, который создаёт переменную при первом использовании в глобальной области видимости (если не используется let/const — не рекомендуется).
Сокращённая форма операций, где значение переменной изменяется и сразу присваивается обратно.let score = 100; score += 25; // 125
score *= 2; // 250
score -= 50; // 200
score %= 60; // 20 (остаток от 200 ÷ 60)
score **= 2; // 400 (20²) console.log(score); // 400 ✅ Преимущество: короче, читаемее, немного эффективнее — особенно полезны в циклах и обработке данных.
Присваивает значение только если левый операнд равен null или undefined.let userLanguage = null;
userLanguage ??= "en"; // теперь userLanguage = "en" let userName = "";
userName ??= "Аноним"; // останется "", потому что "" ≠ null/undefined let settings = { theme: undefined };
settings.theme ??= "dark"; // theme станет "dark" console.log(settings.theme); // "dark" 💡 Отличие от =: ??= не перезаписывает существующие значения, даже если они ложные (0, "", false).
Это делает его идеальным для установки значений по умолчанию в конфигурациях, настройках, API-ответах.
let theme = localStorage.getItem("theme");
theme ??= "light"; // если не задано — использовать светлую тему let fontSize = localStorage.getItem("fontSize");
fontSize ??= 16; // если не задано — 16px console.log({ theme, fontSize });
Присваивает значение только если предшествующая цепочка существует (не null/undefined).let user = { profile: { name: "Иван" } }; // Попытка присвоить значение только если user.profile существует
user.profile?.name ??= "Гость"; // НЕ сработает — это не присваивание через ?.
user.profile?.age ??= 25; // НЕ сработает — age не существует, но ?. не создаёт свойства // А вот так:
user.profile?.age = 25; // ❌ Ошибка: нельзя присвоить, если user.profile не существует
На самом деле, ?.= — это оператор присваивания, а не объединения. Он работает следующим образом:let obj = {}; obj?.prop = 10; // ❌ ОШИБКА — SyntaxError: Invalid left-hand side expression // Правильно — только если объект существует:
let config = { settings: {} };
config.settings?.debug = true; // ✅ Работает — config.settings существует console.log(config.settings.debug); // true // Если объект отсутствует — ничего не происходит:
let data = null;
data?.value = "test"; // Ничего не произойдёт — ошибки нет
console.log(data); // null ⚠️ Важно: ?.= не создаёт свойства — он лишь пропускает присваивание, если левая часть null/undefined.
Он применяется только к существующим объектам и их вложенным свойствам.
function updateUser(user, newSettings) { user?.profile?.name = newSettings.name; user?.profile?.email = newSettings.email; user?.preferences?.theme = newSettings.theme;
} updateUser(null, { name: "Анна" }); // Ничего не сломается
updateUser({ profile: {} }, { name: "Анна" }); // profile.name = "Анна" — сработает ✅ Идеально подходит для работы с API-ответами, где структура может быть неполной. Не используйте ?.= для создания новых свойств в null/undefined объектах — это невозможно.
Не путайте ??= и ?.=: ??= — присваивает, если значение null/undefined ?.= — присваивает, только если путь существует ]]></description><link>материалы/подтемы/секция-1.-javascript/операторы-присваивания-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Операторы присваивания JavaScript.md</guid><pubDate>Wed, 17 Sep 2025 18:41:36 GMT</pubDate></item><item><title><![CDATA[Операторы сравнения JavaScript]]></title><description><![CDATA[Операторы сравнения позволяют проверять отношения между значениями и возвращают логическое значение — true или false. В JavaScript важно понимать разницу между нестрогим и строгим сравнением, а также то, как язык приводит типы автоматически.Операторы == (равно) и != (не равно) выполняют приведение типов перед сравнением. Это означает, что JavaScript пытается преобразовать операнды к одному типу, чтобы сделать сравнение возможным.console.log(5 == "5"); // true — строка "5" приводится к числу 5
console.log(true == 1); // true — true приводится к 1
console.log(false == 0); // true — false приводится к 0
console.log("" == 0); // true — пустая строка приводится к 0
console.log(null == undefined); // true — особое правило: null и undefined равны друг другу
console.log("0" == false); // true — "0" → 0, false → 0 → 0 == 0
console.log([] == false); // true — пустой массив → "" → 0 → false → 0
Такие поведения могут привести к скрытым багам, особенно при обработке пользовательского ввода или данных из API.
✅ Правило: Избегайте == и != в production-коде.
Операторы === (строго равно) и !== (строго не равно) не выполняют приведение типов. Сравниваются и значение, и тип.console.log(5 === "5"); // false — разные типы: число и строка
console.log(true === 1); // false — boolean и number
console.log(5 === 5); // true — одинаковые тип и значение
console.log(null === undefined); // false — разные типы
console.log("" === 0); // false — строка не равна числу
Всегда используйте === и !==, если вам нужно точное совпадение.// Хорошо
if (userInput === "yes") { ... } // Плохо
if (userInput == "yes") { ... } // Может сработать на 1, true, "1"
Эти операторы сравнивают значения по величине. При сравнении разных типов JavaScript также применяет приведение, но по другим правилам.console.log(10 &gt; 5); // true
console.log(3 &lt;= 3); // true
Строки сравниваются по символам, в лексикографическом порядке (как в словаре):console.log("apple" &lt; "banana"); // true — 'a' &lt; 'b'
console.log("Z" &lt; "a"); // true — в ASCII 'Z' (90) &lt; 'a' (97)
console.log("10" &lt; "2"); // true — потому что "1" &lt; "2", сравнение по первому символу! ❗ Важно: "10" &lt; "2" даёт true, хотя числово 10 &gt; 2.
Это частая ошибка при сравнении строковых чисел.
Приведите их к числу:console.log(Number("10") &lt; Number("2")); // false
// или проще:
console.log(+ "10" &lt; + "2"); // false
]]></description><link>материалы/подтемы/секция-1.-javascript/операторы-сравнения-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Операторы сравнения JavaScript.md</guid><pubDate>Wed, 17 Sep 2025 18:36:07 GMT</pubDate></item><item><title><![CDATA[Логические операторы JavaScript]]></title><description><![CDATA[Логические операторы — &amp;&amp; (И), || (ИЛИ) и ! (НЕ) — позволяют комбинировать и инвертировать логические значения. В JavaScript они работают не только с true и false, но и с любыми значениями, благодаря особенностям приведения типов и механизму короткого замыкания.Возвращает true, если оба операнда истинны.
Но в JavaScript он возвращает не булево значение, а один из операндов — первый ложный или последний истинный.console.log(true &amp;&amp; true); // true
console.log(true &amp;&amp; false); // false
console.log(5 &amp;&amp; "hello"); // "hello" — оба истинны, возвращён второй
console.log(0 &amp;&amp; "test"); // 0 — первый ложный, возвращён он же
console.log("" &amp;&amp; null); // "" — первый ложный
Если первый операнд — ложный, второй не вычисляется.function log() { console.log("Эта функция не вызовется"); return true;
} console.log(false &amp;&amp; log()); // false — функция log() НЕ была вызвана ✅ Это полезно для безопасного доступа к свойствам объектов:
const user = { profile: { name: "Alice" } }; // Безопасно: если user или user.profile отсутствуют — не будет ошибки
console.log(user &amp;&amp; user.profile &amp;&amp; user.profile.name); // "Alice" // Если бы user был undefined — выражение остановилось бы на первом шаге
Возвращает первый истинный операнд, или последний, если все ложные.console.log(true || false); // true
console.log(false || "world"); // "world"
console.log(0 || null || 5 || 10); // 5 — первый истинный
console.log("" || 0 || false); // false — все ложные, возвращён последний
Если первый операнд — истинный, второй не вычисляется.function log() { console.log("Эта функция вызовется только если нужно"); return "result";
} console.log(true || log()); // true — функция log() НЕ вызвана
function greet(name) { name = name || "Гость"; // если name пустой/ложный — использовать "Гость" console.log(`Привет, ${name}!`);
} greet(); // "Привет, Гость!"
greet(""); // "Привет, Гость!"
greet(null); // "Привет, Гость!"
greet("Анна"); // "Привет, Анна!"
greet(0); // "Привет, Гость!" — осторожно! ⚠️ Внимание: 0, "", null, undefined, NaN — всё это ложные значения.
Если вы ожидаете 0 как валидный ввод — такой подход сломается.
function greet(name) { name = name ?? "Гость"; // только null или undefined → заменяются console.log(`Привет, ${name}!`);
} greet(0); // "Привет, 0!" — правильно!
greet(undefined); // "Привет, Гость!" ✅ Рекомендация: в современных приложениях используйте ?? вместо || для установки значений по умолчанию, если вам важно отличать 0, false, "" от null/undefined.
Инвертирует значение операнда. Возвращает булево значение (true или false).console.log(!true); // false
console.log(!false); // true
console.log(!"hello"); // false — строка истинна
console.log(!0); // true — 0 ложен
console.log(!{}); // false — объект истинен
console.log(!!"text"); // true — двойное отрицание приводит к булеву значению
const isEmpty = !array.length; // true, если массив пуст
const hasUser = !!user; // true, если user существует и не null/undefined ✅ Двойное отрицание !!value — популярный способ явно преобразовать любое значение в булево.
Приоритет (с высшего к низшему):
! — НЕ (наиболее высокий)
&amp;&amp; — И
|| — ИЛИ (наименьший)
console.log(true || false &amp;&amp; false); // true
// Эквивалентно: true || (false &amp;&amp; false) → true || false → true
Чтобы избежать путаницы — всегда используйте скобки:console.log((true || false) &amp;&amp; false); // false
(Больше про приоритет операторов будет в этой же теме)]]></description><link>материалы/подтемы/секция-1.-javascript/логические-операторы-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Логические операторы JavaScript.md</guid><pubDate>Wed, 17 Sep 2025 18:35:49 GMT</pubDate></item><item><title><![CDATA[Арифметические операторы JavaScript]]></title><description><![CDATA[Арифметические операторы — это основные инструменты для выполнения математических вычислений в JavaScript. Они работают с числами и возвращают числовые результаты.Пример использования остатка: const isEven = number =&gt; number % 2 === 0;
console.log(isEven(4)); // true
console.log(isEven(7)); // false
Оператор ** возводит первое число в степень, указанную вторым:console.log(2 ** 4); // 16 (2 × 2 × 2 × 2)
console.log(9 ** 0.5); // 3 (квадратный корень из 9)
Это удобно для расчётов: например, при вычислении площади квадрата или сложных процентов.Унарный плюс + преобразует значение в число:console.log(+"42"); // 42 (строка → число)
console.log(+"hello"); // NaN (непреводимая строка)
console.log(+true); // 1
console.log(+false); // 0
Унарный минус - меняет знак числа:console.log(-5); // -5
console.log(-(3 + 2)); // -5
console.log(-"10"); // -10 (сначала приведение к числу, потом отрицание)
Инкремент ++ увеличивает значение на 1, декремент -- уменьшает на 1.Различают две формы:Сначала изменяет значение, потом возвращает его:let a = 5;
console.log(++a); // 6 — сначала прибавили, потом вернули
console.log(a); // 6
Сначала возвращает текущее значение, потом изменяет:let b = 5;
console.log(b++); // 5 — вернули старое значение
console.log(b); // 6 — теперь уже увеличено 💡 Важно: в циклах и выражениях разница между i++ и ++i может привести к ошибкам, если не учитывать порядок.
JavaScript имеет специальные числовые значения, которые появляются при некорректных операциях.Появляется, когда операция не может быть выполнена:console.log(0 / 0); // NaN
console.log("abc" * 2); // NaN
console.log(NaN + 5); // NaN
console.log(NaN === NaN); // false — важно! NaN не равен самому себе
Для проверки на NaN используйте Number.isNaN():console.log(Number.isNaN(NaN)); // true
console.log(Number.isNaN("hello")); // false
Получается при делении на ноль или при переполнении:console.log(1 / 0); // Infinity
console.log(-1 / 0); // -Infinity
console.log(Number.MAX_VALUE * 2); // Infinity console.log(Infinity + 1); // Infinity
console.log(Infinity - Infinity); // NaN ⚠️ Не используйте == Infinity для проверки — лучше применять isFinite(): console.log(isFinite(1000)); // true
console.log(isFinite(Infinity)); // false ]]></description><link>материалы/подтемы/секция-1.-javascript/арифметические-операторы-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Арифметические операторы JavaScript.md</guid><pubDate>Wed, 17 Sep 2025 18:25:57 GMT</pubDate></item><item><title><![CDATA[Определение оператора и операнда]]></title><description><![CDATA[Оператор — это символ или ключевое слово, которое выполняет определённое действие над данными.Операнд — это значение или переменная, над которой применяется оператор.Операторы классифицируются по количеству операндов, с которыми они работают:
Унарные операторы используют один операнд — например, отрицание !x или инкремент ++i.
Бинарные операторы работают с двумя операндами — например, сложение a + b или сравнение x &gt; y.
Тернарный оператор использует три операнда — единственный в JavaScript: условное выражение condition ? value1 : value2 (про него подробнее будет в следующей теме).]]></description><link>материалы/подтемы/секция-1.-javascript/определение-оператора-и-операнда.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Определение оператора и операнда.md</guid><pubDate>Wed, 17 Sep 2025 18:22:00 GMT</pubDate></item><item><title><![CDATA[Примитивные типы данных JavaScript]]></title><description><![CDATA[Примитивные типы данных — это базовые, неструктурированные значения в JavaScript, которые не содержат свойств или методов сами по себе и не могут быть изменены после создания. Главная особенность примитивов — они передаются по значению: при присваивании или передаче в функцию копируется само значение, а не ссылка на него. Это означает, что если вы присвоите примитивную переменную другой переменной и измените одну из них — другая останется неизменной. Примитивы также не имеют внутреннего состояния — их нельзя расширить, добавить свойства или переопределить. Они являются фундаментом для всех операций в JavaScript и лежат в основе хранения и обработки любых данных — от чисел в расчётах до текста в интерфейсе мобильного приложения.В JavaScript все числа — это числа с плавающей запятой по стандарту IEEE 754. Это значит, что даже целые числа хранятся как дробные, и из-за особенностей двоичного представления могут возникать небольшие погрешности при вычислениях (например, 0.1 + 0.2 !== 0.3). JavaScript не разделяет целые и вещественные числа — всё объединено в один тип number. Поддерживаются положительные, отрицательные, ноль, а также специальные значения Infinity, -Infinity и NaN (Not a Number).Строка в JavaScript — это последовательность символов, заключённая в одинарные ('), двойные (") или обратные кавычки (`). Обратные кавычки позволяют использовать шаблонные строки — вставлять переменные через ${} и писать многострочный текст без экранирования. Например: `Привет, ${name}!`. Строки неизменяемы — любое изменение создаёт новую строку, а не модифицирует существующую.Логический тип представляет два возможных значения: true и false. Используется для условий, сравнений, флагов состояний (например, загружено ли приложение, авторизован ли пользователь). В JavaScript есть понятие «ложных» и «истинных» значений — например, 0, "", null, undefined воспринимаются как false в булевом контексте, но сами по себе они не являются boolean.null — это специальное значение, которое программист присваивает намеренно, чтобы указать: «здесь ничего нет». Это не ошибка и не неопределённость — это осознанное обозначение отсутствия данных. Например, если пользователь не выбрал аватар, можно установить avatarUrl: null. Несмотря на поведение typeof null === 'object' (историческая ошибка языка), null — это примитив.undefined означает, что переменная была объявлена, но ей ещё не присвоено значение. Это автоматическое состояние, которое присваивается переменной при объявлении через let или const без инициализации. Также возвращается, если функция не возвращает значение, или свойство объекта не существует. Отличие от null: undefined — это результат отсутствия действия, а null — результат преднамеренного действия.<img alt="Pasted image 20240923235323.png" src="материалы/файлы/pasted-image-20240923235323.png" target="_self">Symbol — это новый примитивный тип, появившийся в ES6, предназначенный для создания уникальных ключей свойств объектов. Каждый символ, созданный через Symbol(), гарантированно уникален, даже если у них одинаковое описание. Используется редко в базовой разработке, но важен для внутренней работы библиотек и предотвращения коллизий имён свойств. Не нужно запоминать детали — достаточно знать, что он существует и используется для скрытия и защиты ключей.bigint — это тип для работы с целыми числами, превышающими предел Number.MAX_SAFE_INTEGER (около 9 квадриллионов). Чтобы создать bigint, нужно добавить букву n в конец числа: 123456789012345678901234567890n. Он нужен для точных расчётов — например, при работе с финансовыми данными, хешами, криптографией или большими идентификаторами. С bigint нельзя выполнять операции с обычными числами — требуется явное приведение.Оператор typeof в JavaScript используется для определения типа значения на момент выполнения. Он возвращает строку с названием типа данных. Это важный инструмент для отладки, валидации входных данных и безопасной работы с переменными, особенно когда тип неизвестен заранее — например, при получении данных из API или пользовательского ввода.typeof 42; // "number"
typeof 3.14; // "number"
typeof -0; // "number"
typeof Infinity; // "number"
typeof NaN; // "number" typeof "Привет"; // "string"
typeof ''; // "string"
typeof `Шаблон ${1 + 2}`; // "string" typeof true; // "boolean"
typeof false; // "boolean" typeof null; // "object" — историческая ошибка языка typeof undefined; // "undefined" typeof Symbol('id'); // "symbol" typeof 12345678901234567890n; // "bigint" typeof function() {}; // "function" typeof {}; // "object"
typeof []; // "object" — массивы тоже объекты typeof null возвращает "object" — это известная ошибка в спецификации JavaScript, которая осталась ради совместимости.
typeof всегда возвращает строку, даже если значение не существует (например, typeof undeclaredVariable вернёт "undefined" без ошибки).
Для проверки массивов или объектов typeof недостаточен — лучше использовать Array.isArray() или instanceof.
При работе с JSON-ответами API часто приходят данные неизвестного типа. Например, поле userId может быть числом или строкой. Перед использованием его стоит проверить:if (typeof userId === 'string') { // обработать как строку
} else if (typeof userId === 'number') { // обработать как число
}
Преобразование типов — это процесс изменения значения одного типа данных в другой. В JavaScript, как в языке с динамической типизацией, это происходит постоянно — иногда намеренно, а иногда автоматически, что может приводить к неожиданным результатам. Различают два вида преобразований: явное (когда разработчик сам управляет процессом) и неявное (когда язык делает это автоматически на основе контекста).Явное преобразование — это когда разработчик сознательно и намеренно превращает значение из одного типа в другой с помощью специальных функций или операторов. Это безопасный и предсказуемый способ, который рекомендуется использовать в production-коде.// Число → строка
String(42); // "42"
(42).toString(); // "42"
42 + ""; // "42" — это уже неявное, но можно использовать и явно // Строка → число
Number("123"); // 123
Number("3.14"); // 3.14
Number("abc"); // NaN — некорректная строка
parseInt("42px"); // 42 — преобразует до первого нецифрового символа
parseFloat("3.14abc"); // 3.14 // Строка → булево
Boolean("hello"); // true
Boolean(""); // false — пустая строка — ложь
Boolean("0"); // true — любая непустая строка — истина, даже "false" // Число → булево
Boolean(0); // false
Boolean(-1); // true
Boolean(1); // true
Boolean(NaN); // false
Boolean(Infinity); // true // Любое значение → булево через двойное отрицание
!!"text"; // true
!!0; // false
!!null; // false // Объект → строка
String({}); // "[object Object]"
JSON.stringify({}); // "{}" — для структурированного представления При получении данных из формы (input.value всегда строка).
При работе с API, где типы могут быть неточными.
При необходимости гарантировать поведение — например, чтобы +"5" не вызывало путаницы.
В тестах и валидации входных данных. ✅ Правило: Если вы не уверены в типе — приведите его явно. Это делает код понятнее и надёжнее.
Неявное преобразование — это когда JavaScript автоматически меняет тип значения, чтобы выполнить операцию. Оно происходит при использовании операторов +, -, *, /, ==, if(), while() и других в контекстах, требующих другого типа. Это мощный механизм, но он часто вызывает ошибки у новичков, потому что поведение не всегда очевидно.Если хотя бы один операнд — строка, то оба приводятся к строке:"5" + 3; // "53" — строка + число → конкатенация
5 + "3"; // "53"
"Привет" + 123; // "Привет123"
true + "!" // "true!"
Если оба операнда — числа — выполняется математическое сложение:5 + 3; // 8
0.1 + 0.2; // 0.30000000000000004 — особенность IEEE 754
Математическое сложение так-же происходит если среди операндов нет строк, в таком случае операнды преобразуются в числа:5 + true; // 6 = 5 + 1
false + Infinity; // Infinity - что тоже является числом // 0 + бесконечность
Эти операторы всегда пытаются привести операнды к числам:"5" - "3"; // 2 — строки превратились в числа
"10" * "2"; // 20
"15" / "3"; // 5
"abc" - 1; // NaN — нельзя преобразовать "abc" в число
true - 1; // 0 — true → 1
false * 5; // 0 — false → 0
Оператор == выполняет неявное приведение типов перед сравнением — это главный источник ошибок:"" == 0; // true — пустая строка → 0
"0" == 0; // true — "0" → 0
false == 0; // true — false → 0
null == undefined;// true — особое правило: они равны друг другу
0 == false; // true — false → 0
"1" == true; // true — "1" → 1, true → 1
[] == 0; // true — пустой массив → "" → 0
[1] == 1; // true — [1] → "1" → 1
[1,2] == "1,2"; // true — массив → строка "1,2"
{} == "[object Object]"; // false — объекты сравниваются по ссылке, но при приведении к строке — да, но тут логика сложнее ⚠️ Важно: null == undefined — единственное исключение, где два разных примитива считаются равными.
Любое значение приводится к булевому типу:if ("0") { console.log("Это правда!"); } // сработает — непустая строка → true
if (0) { console.log("Не сработает"); } // не сработает — 0 → false
if ([]) { console.log("Это правда!"); } // сработает — массив → true
if ({}) { console.log("Это правда!"); } // сработает — объект → true
if (null) { console.log("Не сработает"); } // не сработает — null → false
if (undefined) { console.log("Не сработает"); } // не сработает 📌 Эти 6 значений называются falsy — всё остальное — truthy.
// Начинающий разработчик ожидает:
"5" == 5; // true — логично?
"5" === 5; // false — теперь понятно! // А вот так:
[] == ![]; // true — почему?
// Разбор:
// ![] → false (пустой массив → true → отрицание → false)
// [] == false → "" == false → 0 == 0 → true // Или:
" \t\n" == 0; // true — строка с пробелами → пустая после trim → 0
Такие случаи ведут к багам, которые сложно отследить. Особенно в мобильных приложениях, где данные приходят из сети и могут быть неожиданного типа.]]></description><link>материалы/подтемы/секция-1.-javascript/примитивные-типы-данных-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Примитивные типы данных JavaScript.md</guid><pubDate>Wed, 17 Sep 2025 17:42:35 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Установка и базовое использование Node.js]]></title><description><![CDATA[Node.js можно установить двумя основными способами. Первый — через официальный установщик с сайта nodejs.org: он подходит для новичков и автоматически настраивает Node.js и npm (советую вам использовать этот способ). Второй — через nvm (Node Version Manager): это инструмент для управления несколькими версиями Node.js на одном компьютере, что особенно полезно при работе с разными проектами. На macOS и Linux nvm устанавливается через терминал командой curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash, на Windows — через nvm-windows. После установки nvm можно легко переключаться между версиями: nvm install 20, nvm use 20.После установки важно проверить, что Node.js и npm (менеджер пакетов) работают корректно. В терминале введите node -v — вы увидите текущую версию Node.js (например, v20.12.0). Затем введите npm -v — вы увидите версию npm (например, 10.5.0). Если обе команды возвращают номера версий — среда готова к работе. Если нет — перезагрузите терминал или проверьте путь установки.Чтобы запустить JavaScript-файл в Node.js, создайте файл с расширением .js (например, app.js), напишите в нём любой код — например, console.log('Привет, Node.js!'); — и сохраните. В терминале перейдите в папку с файлом и выполните команду node app.js. Node.js прочитает файл, выполнит его содержимое и выведет результат в консоль. Это простейший способ тестировать серверный код, не используя браузер.Так-же, для вас будет проще запускать его сразу из редактора кода.Нажимаем на f5 находясь в нужном файле.
В первый запуск у вас спросят выбрать способ дебагера, выбираем Node.js.
<img alt="Pasted image 20240928221620.png" src="материалы/файлы/pasted-image-20240928221620.png" target="_self">ПКМ по файлу.<br><img alt="Pasted image 20240928222139.png" src="материалы/файлы/pasted-image-20240928222139.png" target="_self">нажимаем кнопку Run "название скрипта"Дальше можем просто нажимать на кнопку "запуск"<br>
<img alt="Pasted image 20240928222237.png" src="материалы/файлы/pasted-image-20240928222237.png" target="_self">REPL (Read-Eval-Print Loop) — это интерактивная оболочка Node.js, которая позволяет сразу писать и выполнять JavaScript-код в терминале. Чтобы запустить её, введите node без аргументов. Вы увидите приглашение &gt; — теперь можете вводить выражения: 2 + 2, const name = 'Миша'; console.log(name);. Результат выводится мгновенно. Для выхода из REPL нажмите Ctrl + C дважды или введите .exit. REPL идеален для быстрой проверки синтаксиса, экспериментов с API или отладки небольших фрагментов кода.]]></description><link>материалы/подтемы/секция-1.-javascript/установка-и-базовое-использование-node.js.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Установка и базовое использование Node.js.md</guid><pubDate>Wed, 17 Sep 2025 17:22:19 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Что такое Node.js]]></title><description><![CDATA[Node.js — это среда выполнения JavaScript, которая позволяет запускать код на сервере, а не только в браузере. Она построена на движке V8 от Google и даёт JavaScript доступ к системным ресурсам: файловой системе, сети, процессам. Это делает JavaScript полноценным языком для создания серверных приложений, инструментов разработки и автоматизации — всё на том же языке, что и фронтенд.Node.js появился в 2009 году благодаря Райану Далю — разработчику, который задался вопросом: почему JavaScript, который так хорошо справляется с асинхронными событиями в браузере (клики, загрузки, запросы), не может делать то же самое на сервере? Он объединил движок V8, который быстро выполняет JavaScript, с библиотекой libuv — специальной системой для асинхронного ввода-вывода. В результате получилась первая среда, где сервер мог обрабатывать тысячи одновременных соединений без создания отдельного потока на каждое — это стало прорывом в производительности.JavaScript на сервере упрощает разработку. Если вы пишете мобильное приложение на React Native или используете JSON-API, то логика, данные и даже части валидации могут быть общими между клиентом и сервером. Нет необходимости учить два разных языка — JavaScript на фронтенде и, например, Java или Python на бэкенде. Это снижает сложность команды, ускоряет разработку и делает поддержку проще. Также огромная экосистема npm дарит готовые решения для любой задачи — от баз данных до авторизации.В браузере JavaScript работает в ограниченной среде: он может работать с DOM, отправлять запросы через fetch, хранить данные в localStorage, но не может читать файлы с диска или слушать порты. В Node.js этих ограничений нет. Вместо window и document вы получаете global, process, require, module. Вы можете использовать модули fs для работы с файлами, http для создания сервера, path для обработки путей, child_process для запуска команд. То есть — Node.js превращает JavaScript из языка «для страниц» в язык «для всего».Node.js — невидимый двигатель современной мобильной разработки.
— Backend для API: большинство мобильных приложений получают данные через REST или GraphQL. Эти API почти всегда пишут на Node.js (Express, NestJS, Fastify).
— Инструменты сборки: Webpack, Metro, Babel, Vite — все они написаны на Node.js и собирают ваш код в приложение для iOS и Android.
— CLI-инструменты: Expo CLI, Ionic CLI, Capacitor — они создают проекты, добавляют плагины, настраивают конфиги — и всё это работает на Node.js.
— CI/CD: когда вы заливаете код в GitHub, а система автоматически собирает APK/IPA и публикует его — за этим стоит скрипт на Node.js.
Даже если вы никогда не напишете строчку на Node.js — вы будете им пользоваться каждый день. Без него мобильная разработка была бы намного медленнее, сложнее и менее гибкой.]]></description><link>материалы/подтемы/секция-1.-javascript/что-такое-node.js.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Что такое Node.js.md</guid><pubDate>Wed, 17 Sep 2025 17:18:03 GMT</pubDate></item><item><title><![CDATA[Создание своей HTML страницы]]></title><description><![CDATA[Чтобы создать HTML-страницу, достаточно использовать любой текстовый редактор — даже Блокнот. Однако для эффективной разработки рекомендуется использовать современный редактор кода, такой как Visual Studio Code (VS Code).HTML-страница — это текстовый файл с расширением .html. Минимальная структура HTML-документа выглядит так:&lt;!DOCTYPE html&gt;
&lt;html lang="ru"&gt;
&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;title&gt;Моя первая страница&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Привет, мир!&lt;/h1&gt;
&lt;/body&gt;
&lt;/html&gt;
Сохраните этот код в файл с именем, например, index.html. Откройте его в браузере — вы увидите заголовок «Привет, мир!». Это и есть ваша первая веб-страница.<a data-href="Как создавать файлы с определённым расширением" href="материалы/как-сделать/как-создавать-файлы-с-определённым-расширением.html" class="internal-link" target="_self" rel="noopener nofollow">Как создавать файлы с определённым расширением</a>JavaScript можно подключать к HTML-странице двумя основными способами: встроенно (внутри HTML-файла) или через внешний файл. Второй способ — единственно правильный для профессиональной разработки.JavaScript можно вставить прямо внутрь HTML-документа с помощью тега &lt;script&gt;:&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;title&gt;Страница с встроенным JS&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Привет!&lt;/h1&gt; &lt;script&gt; alert("Это встроенный JavaScript!"); document.write("&lt;p&gt;Текст добавлен скриптом.&lt;/p&gt;"); &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Почему это не рекомендуется:
Нарушает принцип разделения ответственности: структура (HTML), стиль (CSS) и логика (JS) должны быть разделены.
Сложно поддерживать и масштабировать код — особенно при росте проекта.
Затрудняется повторное использование кода между страницами.
Ухудшается читаемость и тестирование.
Может замедлять загрузку страницы, если скрипт большой.
Используйте этот способ только для быстрых экспериментов, демонстраций или очень простых примеров.Правильный и стандартный способ — создать отдельный файл с расширением .js и подключить его к HTML:
Создайте файл script.js в той же папке, что и index.html.
Напишите в нём JavaScript-код:
// script.js
alert("Это внешний JavaScript-файл!");
document.querySelector('h1').style.color = 'blue'; Подключите его в HTML перед закрывающим тегом &lt;/body&gt;:
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt; &lt;title&gt;Страница с внешним JS&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt; &lt;h1&gt;Привет!&lt;/h1&gt; &lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Преимущества:
Чистый, организованный код.
Возможность переиспользования одного файла на нескольких страницах.
Упрощённая отладка и версионный контроль (Git).
Лучшая производительность — браузер может кэшировать внешние скрипты.
JavaScript следует подключать в самом конце тела HTML-документа, перед закрывающим тегом &lt;/body&gt;.Когда браузер встречает тег &lt;script&gt; во время парсинга HTML, он приостанавливает загрузку и разбор DOM-дерева, чтобы загрузить и выполнить скрипт. Если скрипт подключен в &lt;head&gt; или в начале &lt;body&gt;, а он пытается взаимодействовать с элементами, которые ещё не загружены — возникнет ошибка:&lt;head&gt; &lt;script src="script.js"&gt;&lt;/script&gt; &lt;!-- ❌ Опасно! --&gt;
&lt;/head&gt;
&lt;body&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt;
&lt;/body&gt;
Если в script.js написано:document.getElementById('myButton').addEventListener('click', () =&gt; { alert('Клик!');
});
— то скрипт выполнится до того, как кнопка появится в DOM, и getElementById вернёт null. Результат — ошибка в консоли.&lt;body&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;script src="script.js"&gt;&lt;/script&gt; &lt;!-- ✅ Безопасно: DOM уже построен --&gt;
&lt;/body&gt;
Теперь браузер сначала полностью загрузит и отрисует все элементы страницы, а только потом выполнит скрипт — и все запросы к DOM будут успешными.
Быстрая отрисовка контента: пользователь видит страницу быстрее, без задержек из-за загрузки скриптов.
Предсказуемое поведение: код работает только тогда, когда всё, к чему он обращается, уже существует.
Совместимость с современными практиками: так делают все крупные фреймворки и библиотеки. Если скрипт не зависит от DOM (например, модуль аналитики, который запускается сразу при загрузке страницы), его можно размещать в &lt;head&gt;.
Использование атрибута defer (в &lt;head&gt;) позволяет отложить выполнение скрипта до завершения парсинга HTML — это альтернатива размещению в конце, но требует понимания нюансов.
&lt;head&gt; &lt;script src="script.js" defer&gt;&lt;/script&gt; &lt;!-- ✅ Альтернатива, если нужно в head --&gt;
&lt;/head&gt; ✅ Рекомендация: Всегда подключайте JavaScript-файлы перед закрывающим тегом &lt;/body&gt;, если только вы точно не знаете, что делаете и почему используете defer или async. Это — базовое правило надёжной и предсказуемой работы JavaScript на веб-странице.
Чтобы реагировать на действия пользователя (например, нажатие кнопки), можно назначить обработчик события двумя способами: через атрибуты HTML или через JavaScript. Второй способ — единственный корректный для профессиональной разработки.Можно напрямую вписать JavaScript-код в атрибут onclick элемента:&lt;button onclick="alert('Кнопка нажата!')"&gt;Нажми меня&lt;/button&gt;
Или вызвать функцию:&lt;script&gt;
function handleClick() { alert('Функция вызвана через атрибут!');
}
&lt;/script&gt; &lt;button onclick="handleClick()"&gt;Нажми меня&lt;/button&gt;
Почему это не рекомендуется:
Смешивание ответственности: логика (JS) и структура (HTML) сливаются — нарушает принцип разделения.
Сложность поддержки: сложно отлаживать, тестировать и рефакторить код, особенно при росте проекта.
Уязвимость к ошибкам: если имя функции опечатано — ошибка не будет заметна до момента клика.
Не масштабируемо: невозможно динамически добавлять/удалять обработчики, работать с несколькими элементами, использовать замыкания.
Проблемы с безопасностью: в некоторых контекстах (CSP) использование onclick может быть заблокировано. ⚠️ Используйте этот способ только для быстрых экспериментов или учебных примеров — никогда в продакшене.
Правильный и стандартный способ — назначать обработчики событий из JavaScript, после того как DOM загружен:&lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;script src="script.js"&gt;&lt;/script&gt;
// script.js
const button = document.getElementById('myButton'); button.addEventListener('click', function() { alert('Кнопка нажата через addEventListener!');
});
Преимущества:
Полное разделение логики и разметки.
Возможность назначать несколько обработчиков на один элемент.
Легко удалять обработчики через removeEventListener.
Поддержка современных возможностей JS: стрелочные функции, async/await, замыкания.
Удобно работать с динамически создаваемыми элементами.
Совместимость с системами сборки, тестирования и фреймворками.
Дополнительно — лучшая практика:document.addEventListener('DOMContentLoaded', () =&gt; { const button = document.getElementById('myButton'); if (button) { button.addEventListener('click', () =&gt; { console.log('Клик обработан надёжно'); }); }
});
Это гарантирует, что скрипт выполнится только после полной загрузки DOM, даже если он подключён в &lt;head&gt;.Представим, что у нас есть кнопка в HTML:&lt;button id="myButton"&gt;Нажми меня&lt;/button&gt;
Мы хотим, чтобы при нажатии на неё в консоль браузера выводилось сообщение: "Кнопка была нажата!"
Убедитесь, что у вас есть файл script.js, и он подключен в конце &lt;body&gt;:&lt;body&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;script src="script.js"&gt;&lt;/script&gt;
&lt;/body&gt;
В script.js напишите:const button = document.getElementById('myButton');
Эта строка говорит браузеру:
👉 «Найди элемент на странице, у которого атрибут id="myButton"» — и сохрани его в переменную button.Теперь добавьте эту строку:button.addEventListener('click', () =&gt; { console.log('Кнопка была нажата!');
});
Что здесь происходит (без функций):
addEventListener — это встроенная команда, которая привязывает действие к элементу.
'click' — это тип события, которое мы хотим отслеживать (нажатие).
() — это просто способ сказать: «здесь будет код, который выполнится при событии».
console.log(...) — это команда, которая выводит текст в окно разработчика (не на экран). ✅ Всё, что внутри { } — это просто набор команд, которые должны сработать, когда пользователь кликнет.
Когда пользователь кликает по кнопке — в консоли браузера появляется сообщение: Кнопка была нажата!
Этот шаблон — основа всего дальнейшего взаимодействия с пользователем. Его нужно запомнить как фиксированную формулу:
элемент.addEventListener('событие', () =&gt; { ... });
И заменять:
элемент — на нужный вам (button, input, div и т.д.)
'событие' — на нужное (click, mouseover, keydown и т.д.)
{ ... } — на то, что вы хотите сделать (вывести сообщение, изменить цвет, отправить данные)
]]></description><link>материалы/подтемы/секция-1.-javascript/создание-своей-html-страницы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Создание своей HTML страницы.md</guid><pubDate>Fri, 12 Sep 2025 18:54:37 GMT</pubDate></item><item><title><![CDATA[Базовая работа с элементами веб страницы через JavaScript]]></title><description><![CDATA[В JavaScript для взаимодействия с HTML-элементами используются методы работы с DOM (Document Object Model). Основные способы получения элементов: document.getElementById(id) — возвращает элемент по уникальному атрибуту id.
Пример: const button = document.getElementById('submit-btn'); document.querySelector(selector) — возвращает первый элемент, соответствующий CSS-селектору.
Пример: const title = document.querySelector('h1'); или const item = document.querySelector('.item.active'); document.querySelectorAll(selector) — возвращает NodeList (массивоподобный объект) всех элементов, соответствующих селектору.
Пример: const buttons = document.querySelectorAll('button'); document.getElementsByTagName(name) — возвращает HTMLCollection элементов по тегу.
Пример: const paragraphs = document.getElementsByTagName('p'); document.getElementsByClassName(name) — возвращает HTMLCollection элементов по классу.
Пример: const items = document.getElementsByClassName('list-item'); ⚠️ Методы, возвращающие коллекции (HTMLCollection, NodeList), не являются настоящими массивами и не имеют методов массивов (например, .map(), .filter()). Для их использования можно преобразовать в массив через [...collection] или Array.from(collection).
После получения элемента можно изменять его атрибуты и содержимое: element.textContent — устанавливает или возвращает текстовое содержимое элемента (без HTML-разметки).
Пример: paragraph.textContent = 'Новый текст'; element.innerHTML — устанавливает или возвращает HTML-содержимое элемента (включая разметку).
Пример: div.innerHTML = '&lt;strong&gt;Жирный текст&lt;/strong&gt;'; element.setAttribute(name, value) — задаёт значение атрибута.
Пример: button.setAttribute('disabled', 'true'); element.getAttribute(name) — получает значение атрибута.
Пример: const type = input.getAttribute('type'); element.removeAttribute(name) — удаляет атрибут.
Пример: button.removeAttribute('disabled'); 💡 Используйте textContent для изменения текста — он безопаснее innerHTML, так как не выполняет HTML-код и защищает от XSS-атак.
Стили элемента можно менять напрямую через свойство style — оно представляет собой объект, содержащий все CSS-свойства в формате camelCase:
element.style.propertyName = 'value';
Примеры:
element.style.color = 'red';
element.style.fontSize = '20px';
element.style.backgroundColor = '#f0f0f0';
element.style.marginTop = '10px'; 🔍 Важно: CSS-свойства с дефисом (например, background-color) в JavaScript записываются в camelCase (backgroundColor).
Ограничения:
Стили, заданные через style, имеют приоритет над внешними CSS-правилами.
Нельзя установить несколько стилей одновременно — только по одному свойству.
Для сложных стилевых изменений рекомендуется использовать классы (classList):
element.classList.add('highlight');
element.classList.remove('hidden');
element.classList.toggle('active'); ✅ Использование classList предпочтительнее прямого изменения style — это позволяет отделять логику от стилей и поддерживать чистоту кода.
]]></description><link>материалы/подтемы/секция-1.-javascript/базовая-работа-с-элементами-веб-страницы-через-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Базовая работа с элементами веб страницы через JavaScript.md</guid><pubDate>Fri, 12 Sep 2025 18:40:45 GMT</pubDate></item><item><title><![CDATA[Основные понятия веб страницы]]></title><description><![CDATA[Основные понятия веб-страницыВеб-страница — это документ, отображаемый в браузере, который состоит из трёх взаимосвязанных технологий: HTML, CSS и JavaScript. Каждая из них выполняет свою уникальную роль, и только их совместное использование позволяет создавать полноценные, интерактивные и визуально привлекательные приложения.HTML (HyperText Markup Language) — это язык гипертекстовой разметки, созданный для описания структуры веб-документов. Он не выполняет вычислений, не обрабатывает логику и не управляет поведением — его задача: обозначить смысл содержимого. Каждый элемент HTML — это маркер, который говорит браузеру: «Это заголовок», «Это абзац», «Это ссылка», «Это изображение».HTML работает на основе тегов — специальных ключевых слов, заключённых в угловые скобки: &lt;tag&gt;. Теги могут быть:
Парными — имеют открывающий и закрывающий тег: &lt;p&gt;Это параграф&lt;/p&gt; Самозакрывающимися — не содержат содержимого и закрываются сразу: &lt;img src="image.jpg" alt="Описание изображения" /&gt;
&lt;br /&gt; Каждый тег может иметь атрибуты — дополнительные параметры, уточняющие поведение или свойства элемента. Например:&lt;a href="https://example.com" target="_blank"&gt;Перейти&lt;/a&gt;
Здесь href указывает адрес ссылки, а target="_blank" — открывать её в новой вкладке.HTML5 — современная версия стандарта — ввела семантические теги, которые не только описывают внешний вид, но и передают значение контента:
&lt;header&gt; — шапка страницы или раздела
&lt;nav&gt; — навигационное меню
&lt;main&gt; — основное содержимое страницы
&lt;section&gt; — логический блок тематически связанного контента
&lt;article&gt; — самостоятельная сущность (например, статья, пост)
&lt;footer&gt; — подвал
Использование семантики улучшает:
Доступность — для пользователей с ограниченными возможностями (экранная речь корректно интерпретирует структуру),
SEO — поисковые системы лучше понимают и ранжируют содержимое,
Поддержку кода — разработчики быстрее ориентируются в структуре.
CSS (Cascading Style Sheets) — это язык, предназначенный для оформления HTML-документов. Он отвечает за то, как выглядит страница: цвета, размеры, расположение элементов, анимации, адаптивность под разные устройства.CSS работает через селекторы — правила, определяющие, к каким элементам применяются стили. Пример:h1 { color: #2c3e50; font-size: 2rem; text-align: center;
}
Здесь h1 — селектор, { ... } — набор свойств и их значений.CSS обладает ключевыми особенностями:
Каскадность (Cascading) — стили могут переопределяться. Если два правила влияют на один элемент, приоритет определяется по специфичности селектора, порядку объявления и использованию !important.
Наследование — некоторые свойства (например, font-family, color) автоматически передаются дочерним элементам.
Медиа-запросы — позволяют применять стили в зависимости от характеристик устройства: ширины экрана, ориентации, разрешения. Это основа адаптивного дизайна:
@media (max-width: 768px) { body { font-size: 14px; }
} CSS можно подключать тремя способами:
Внутренний стиль — внутри &lt;style&gt; в &lt;head&gt; (не рекомендуется для больших проектов).
Внешний файл — через &lt;link rel="stylesheet" href="styles.css"&gt; — лучшая практика.
Встроенный стиль — атрибут style внутри тега (&lt;p style="color:red;"&gt;) — используется крайне редко, только для экстренных случаев.
Важно: HTML отвечает за что — CSS — за как выглядит. Их разделение — фундаментальный принцип веб-разработки. Это позволяет:
Менять дизайн без трогания структуры,
Одинаковый HTML отображать по-разному на разных устройствах,
Ускорять загрузку за счёт кэширования CSS-файлов,
Облегчать командную разработку (дизайнеры работают с CSS, разработчики — с HTML и JS). В рамках дисциплины мы не будем изучать свойства CSS, поэтому они остаются на самообучение
Каждый валидный HTML-документ должен начинаться с DOCTYPE, чтобы браузер знал, какой стандарт использовать. Без него он может перейти в режим "quirks mode", где поведение становится непредсказуемым.&lt;!DOCTYPE html&gt;
— единственное объявление, необходимое для HTML5. Не требует закрывающего тега.Корневой элемент. Атрибут lang обязателен для доступности и SEO:&lt;html lang="ru"&gt;
Указывает язык содержимого — помогает экранной речи, переводчикам и поисковикам.Не отображается на странице, но содержит метаданные, необходимые для работы браузера и поисковых систем:
&lt;meta charset="UTF-8"&gt; — задаёт кодировку символов. UTF-8 поддерживает все языки мира — обязательный элемент.
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; — критически важен для мобильных устройств. Без него страница будет масштабироваться как на десктопе, что делает её нечитаемой на телефоне.
&lt;title&gt; — название вкладки браузера и заголовок в результатах поиска. Должен быть уникальным и описательным.
&lt;link&gt; — подключение внешних ресурсов: CSS, favicon, шрифтов.
&lt;script&gt; — подключение JavaScript (может находиться и в &lt;head&gt;, и в &lt;body&gt;, но это отдельная тема).
Пример полного &lt;head&gt;:&lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt; &lt;title&gt;Моя первая страница&lt;/title&gt; &lt;link rel="stylesheet" href="styles.css"&gt; &lt;link rel="icon" href="favicon.ico" type="image/x-icon"&gt;
&lt;/head&gt;
Содержит всё, что видит пользователь. Внутри могут быть любые элементы, включая:
Заголовки: &lt;h1&gt; до &lt;h6&gt; — иерархия важности. &lt;h1&gt; — главный заголовок страницы, только один.
Параграфы: &lt;p&gt; — для текстовых блоков.
Списки: &lt;ul&gt; — неупорядоченный (с точками),
&lt;ol&gt; — упорядоченный (с номерами),
&lt;li&gt; — элемент списка. Изображения: &lt;img src="..." alt="..."&gt; — alt обязателен для доступности и SEO.
Ссылки: &lt;a href="..."&gt;текст&lt;/a&gt; — href — адрес перехода.
Кнопки: &lt;button&gt;...&lt;/button&gt; — для взаимодействия.
Формы: &lt;form&gt;, &lt;input&gt;, &lt;label&gt; — для сбора данных.
Пример минимальной, но корректной структуры &lt;body&gt;:&lt;body&gt; &lt;header&gt; &lt;h1&gt;Добро пожаловать!&lt;/h1&gt; &lt;/header&gt; &lt;main&gt; &lt;p&gt;Это основной текст страницы.&lt;/p&gt; &lt;button id="myButton"&gt;Нажми меня&lt;/button&gt; &lt;/main&gt; &lt;footer&gt; &lt;p&gt;&amp;copy; 2025 Моя компания&lt;/p&gt; &lt;/footer&gt;
&lt;/body&gt;
HTML — дерево. Элементы должны быть правильно вложены:
✅ Правильно:&lt;p&gt;&lt;strong&gt;Жирный текст&lt;/strong&gt; внутри параграфа&lt;/p&gt;
❌ Неправильно:&lt;p&gt;&lt;strong&gt;Жирный текст&lt;/p&gt;&lt;/strong&gt; &lt;!-- Нарушена вложенность --&gt;
Браузеры пытаются исправить ошибки, но это приводит к непредсказуемому поведению, особенно в сложных случаях.
Используйте семантические теги вместо &lt;div&gt; там, где это возможно.
Не используйте &lt;h1&gt;–&lt;h6&gt; исключительно для изменения размера шрифта — используйте CSS.
Все изображения должны иметь alt — даже если пустой (alt=""), если они декоративные.
Для кнопок и ссылок используйте правильные теги: &lt;button&gt; — для действий, &lt;a&gt; — для переходов.
Поддерживайте чистую и читаемую структуру: отступы, переносы, комментарии (если нужно).
Всегда проверяйте валидность кода через <a data-tooltip-position="top" aria-label="https://validator.w3.org/" rel="noopener nofollow" class="external-link is-unresolved" href="https://validator.w3.org/" target="_self">validator.w3.org</a>.
DOM (Document Object Model — Модель объектов документа) — это программное представление веб-документа (обычно HTML или XML), созданное браузером в виде иерархического дерева объектов, где каждый элемент документа — это объект, доступный для манипуляций через JavaScript.DOM не является частью самого HTML-файла. Он динамически генерируется браузером при загрузке страницы: парсер читает HTML-код и превращает его в структуру из узлов (nodes), которые можно изменять, добавлять, удалять или запрашивать с помощью JavaScript.Каждый элемент HTML становится узлом (node) в DOM-дереве:
Элементные узлы — теги (&lt;div&gt;, &lt;p&gt;, &lt;button&gt; и т.д.)
Текстовые узлы — текст внутри тегов
Атрибутные узлы — атрибуты элементов (id, class, href)
Корневой узел — &lt;html&gt;
Дочерние и родительские узлы — элементы связаны отношениями «родитель–ребёнок»
Пример HTML:&lt;div id="container"&gt; &lt;h1&gt;Привет, мир!&lt;/h1&gt; &lt;p&gt;Это параграф.&lt;/p&gt;
&lt;/div&gt;
Соответствующее DOM-дерево:html
└── body └── div#container ├── h1 │ └── #text: "Привет, мир!" └── p └── #text: "Это параграф."
Каждый узел имеет свойства и методы, позволяющие взаимодействовать с ним. Например:
element.tagName — имя тега,
element.textContent — содержимое текста,
element.id, element.className — значения атрибутов,
element.appendChild(), element.removeChild() — управление дочерними узлами.
JavaScript не может напрямую работать с HTML-кодом файла. Он работает только с DOM-представлением, которое браузер создал в памяти. Это позволяет:
Динамически изменять содержимое страницы без перезагрузки (например, обновлять список задач, менять текст кнопки),
Реагировать на действия пользователя — клики, ввод текста, скроллинг,
Изменять стили элементов — через element.style,
Добавлять и удалять элементы — например, создавать новые карточки товаров по запросу,
Получать информацию о состоянии страницы — размер окна, положение элементов, состояние форм.
Без DOM JavaScript был бы бесполезен на веб-странице — он просто не имел бы «точки входа» в контент.]]></description><link>материалы/подтемы/секция-1.-javascript/основные-понятия-веб-страницы.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Основные понятия веб страницы.md</guid><pubDate>Fri, 12 Sep 2025 18:38:42 GMT</pubDate></item><item><title><![CDATA[Самое простое использование JavaScript]]></title><description><![CDATA[Для быстрого тестирования и экспериментов с JavaScript можно использовать консоль разработчика — встроенную инструментальную панель в любом современном браузере (Chrome, Firefox, Edge, Safari). Открыть её можно сочетанием клавиш F12 или Ctrl+Shift+I (на macOS — Cmd+Option+I), затем перейти на вкладку Console.Консоль позволяет выполнять JavaScript-код прямо в браузере без создания HTML-файлов. Это идеальное место для проверки синтаксиса, отладки простых выражений и изучения поведения языка в реальном времени.
<img alt="Pasted image 20250912212732.png" src="материалы/файлы/pasted-image-20250912212732.png" target="_self">Для вывода информации в консоль используется функция console.log():console.log("Привет, мир!");
console.log(42);
console.log(true);
<br><img alt="Pasted image 20250912212810.png" src="материалы/файлы/pasted-image-20250912212810.png" target="_self">Эта команда — основной инструмент отладки на начальных этапах. Она выводит переданные значения в консоль, помогая увидеть, что происходит в коде. Можно передавать несколько аргументов:console.log("Значение переменной:", variableName);
Также доступны другие методы:
console.error() — для ошибок (выводится красным),
console.warn() — для предупреждений (жёлтый цвет),
console.table() — для удобного отображения массивов и объектов в виде таблицы.
Для показа пользователю простого сообщения используется функция alert():alert("Это сообщение от JavaScript!");
<br><img alt="Pasted image 20250912212840.png" src="материалы/файлы/pasted-image-20250912212840.png" target="_self">Она выводит модальное окно с текстом, которое блокирует взаимодействие с страницей до нажатия кнопки «ОК». Используется исключительно для учебных целей и быстрой обратной связи — в реальных приложениях alert() не применяется из-за плохого пользовательского опыта.
⚠️ Не используйте alert() в продакшене — он нарушает поток работы пользователя и не поддерживает стилизацию.
]]></description><link>материалы/подтемы/секция-1.-javascript/самое-простое-использование-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Самое простое использование JavaScript.md</guid><pubDate>Fri, 12 Sep 2025 18:28:41 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item><item><title><![CDATA[Переменные в JavaScript]]></title><description><![CDATA[Переменная в JavaScript — это именованный контейнер для хранения данных, который позволяет обращаться к значению по его имени в процессе выполнения программы.Каждая переменная ассоциирована с определённым значением (число, строка, объект, функция и т.д.), которое может меняться во время работы приложения. Переменные позволяют сохранять промежуточные результаты, пользовательские данные, состояния интерфейса — всё, что требуется для динамического поведения приложения.let age = 25;
let userName = "Алексей";
let isActive = true;
Здесь:
age, userName, isActive — имена переменных.
25, "Алексей", true — значения, которые они хранят. Динамическая типизация — тип значения определяется автоматически при присваивании, и переменная может хранить значения разных типов в разное время.
let x = 10; // число
x = "привет"; // теперь строка — допустимо
x = [1, 2, 3]; // теперь массив — тоже допустимо Объявление и использование — переменную нужно объявить перед использованием (кроме случаев с var в нестрогом режиме, но это устаревшая практика).
Область видимости — определяет, где переменная доступна (блок, функция, глобально), зависит от ключевого слова (let, const, var).
Подробнее про эти особенности мы прочтём в следующих лекциях.При создании и использовании переменных необходимо следовать <a data-tooltip-position="top" aria-label="Правила наименования переменных в JavaScript" data-href="Правила наименования переменных в JavaScript" href="материалы/подтемы/секция-1.-javascript/правила-наименования-переменных-в-javascript.html" class="internal-link" target="_self" rel="noopener nofollow">правилам наименования переменных</a>.Работа с переменными включает три ключевых действия: объявление, инициализация и присваивание. Эти понятия тесно связаны, но не тождественны — их различие критически важно для понимания поведения кода.Объявление переменной — это создание её имени в области видимости. Оно сообщает интерпретатору: «Я хочу использовать эту метку для хранения значения».В JavaScript есть три ключевых слова для объявления:Примеры:var x; // объявление через var
let y; // объявление через let
const z; // Ошибка: const требует инициализации при объявлении
Ключевое отличие: const обязывает сразу присвоить значение — без этого возникает синтаксическая ошибка.
💡 Рекомендация: Всегда используйте const по умолчанию. Если знаете, что значение будет меняться — замените на let. Никогда не используйте var в современных проектах — он вносит путаницу из-за hoisting и функциональной области видимости.
Инициализация — это первое присваивание значения переменной в момент её создания. Это когда переменная получает своё начальное значение и становится доступной для использования.
Инициализация может совпадать с объявлением.
Она обязательна для const, опциональна для let и var.
Примеры:let age; // объявление — без инициализации (значение undefined)
age = 25; // присваивание — теперь переменная проинициализирована let score = 100; // объявление + инициализация в одной строке
const name = "Алекс"; // объявление + инициализация (обязательно!)
Инициализация = объявление + первое присваивание в одном действии.Присваивание — это операция изменения значения уже существующей переменной. Оно происходит после объявления (и, если нужно, после инициализации).
Для let — можно присваивать сколько угодно раз.
Для const — присваивание разрешено только один раз (при инициализации); любое последующее присваивание вызовет ошибку.
Присваивание не обязательно должно происходить сразу после объявления.
Примеры:let count;
count = 0; // первое присваивание (и одновременно инициализация)
count = count + 1; // второе присваивание — изменение значения
count = null; // присваивание — можно менять const PI = 3.14;
PI = 3.14159; // Ошибка: присваивание const после инициализации запрещено // Но! Если значение — объект или массив:
const user = { name: "Иван" };
user.name = "Петр"; // Разрешено — меняется содержимое объекта, а не ссылка
user = {}; // Ошибка — попытка изменить ссылку
Важно: const защищает ссылку, а не содержимое. Для объектов и массивов можно менять свойства — это не нарушает константность.В JavaScript, как и в любом языке программирования, читаемость и поддерживаемость кода важнее минимального количества строк. Создание дополнительной переменной для хранения промежуточного результата — это не расточительство, а практика, повышающая ясность кода.
Упрощает чтение: имя переменной может объяснять смысл действия, вместо того чтобы оставлять сложное выражение без контекста.
Облегчает отладку: можно легко поставить точку останова на конкретной переменной и увидеть её значение.
Снижает когнитивную нагрузку: другие разработчики (и вы сами через неделю) быстрее поймут логику.
Повышает переиспользуемость: если значение используется несколько раз — нет нужды повторять вычисление.
Без лишней переменной (менее читаемо):if (user.age &gt;= 18 &amp;&amp; user.status === 'active' &amp;&amp; user.country !== 'restricted') { enableAccess();
}
С лишней переменной (более понятно):const isAdult = user.age &gt;= 18;
const isActive = user.status === 'active';
const isAllowedCountry = user.country !== 'restricted'; if (isAdult &amp;&amp; isActive &amp;&amp; isAllowedCountry) { enableAccess();
}
Здесь имена переменных выполняют роль документации — они сразу говорят, что проверяется, а не как.Не стоит создавать переменные ради создания — только если они действительно улучшают понимание. Не нужно оборачивать простые литералы или очевидные значения, например:const five = 5; // Избыточно
return x + five; // Лучше:
return x + 5;
Но если значение получено в результате вычисления, преобразования или запроса — лучше сохранить его с осмысленным именем.Переменные используются для хранения данных, которые могут изменяться во время выполнения программы. Они позволяют:
Сохранять результаты вычислений;
Передавать данные между частями кода;
Управлять состоянием приложения (например, флаги, счётчики, пользовательские данные). Обращайтесь к переменной только после её объявления и инициализации. Попытка использовать let или const до объявления вызовет ошибку ReferenceError.
Не используйте переменные с неопределённым значением (undefined) без проверки — это источник багов.
Избегайте глобальных переменных. Всегда ограничивайте область видимости блоками ({}), функциями или модулями.
Используйте переменные для повторяющихся значений — это упрощает изменение параметров в будущем (например, таймауты, цвета, константы конфигурации).
const apiUrl = 'https://api.example.com/data';
const timeoutMs = 5000; fetch(apiUrl, { timeout: timeoutMs }) .then(response =&gt; response.json()) .then(data =&gt; { const processedData = data.map(item =&gt; item.toUpperCase()); displayResults(processedData); });
Здесь каждая переменная имеет чёткую роль:
apiUrl — централизованное управление адресом API;
timeoutMs — легко изменяемый параметр;
processedData — промежуточный результат, понятный по имени. Переиспользование одной переменной для разных целей:
let user = getUserById(123);
user = calculateDiscount(user); // Теперь user — не объект пользователя, а число. Путаница! Использование переменных без инициализации:
let result;
console.log(result + 10); // NaN — непредсказуемое поведение ]]></description><link>материалы/подтемы/секция-1.-javascript/переменные-в-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Переменные в JavaScript.md</guid><pubDate>Fri, 12 Sep 2025 17:31:28 GMT</pubDate></item><item><title><![CDATA[Правила наименования переменных в JavaScript]]></title><description><![CDATA[В JavaScript как и в любом другом языке программирования существуют строгие синтаксические правила для именования переменных: Имя должно начинаться с буквы (a–z, A–Z), символа подчёркивания (_) или знака доллара ($).
✅ Разрешено: name, _count, $element
❌ Запрещено: 2name, -value, 3dModel После первого символа можно использовать буквы, цифры (0–9), _ и $.
✅ Разрешено: userName1, total_price, API_KEY
❌ Запрещено: user-name, email@domain, my variable Имена чувствительны к регистру — name, Name и NAME — это три разные переменные. Нельзя использовать зарезервированные слова языка как имена переменных:
let, const, var, function, if, else, return, class, import, export, null, true, false, this, new, while, for, break, continue, try, catch, finally, throw, switch, case, default, typeof, instanceof, in, of, async, await, yield и другие.
❌ Запрещено: let = 5;, function = "test"; Нельзя использовать ключевые слова будущих версий ECMAScript, даже если они пока не используются (например, package, interface, private, protected, public, static).
❌ Лучше избегать: class, enum, implements, module, namespace, super Хотя JavaScript позволяет многое, следование общепринятым соглашениям делает код понятным, поддерживаемым и профессиональным: Используйте camelCase для имен переменных и функций.
✅ userName, isLoading, getTotalPrice
❌ user_name, User Name, usertotalprice Для констант (которые не меняются) используйте UPPER_SNAKE_CASE.
✅ MAX_USERS, API_URL, DEFAULT_TIMEOUT Выбирайте осмысленные, описательные имена — избегайте аббревиатур и однобуквенных имён, если контекст не очевиден.
✅ numberOfItems, currentUser, isFormValid
❌ n, x, tmp, data1, arr Используйте логические имена для булевых переменных — начинайте с is, has, can, should.
✅ isVisible, hasPermission, canSubmit, isLoading Избегайте двойных отрицаний — лучше isDisabled, чем isNotEnabled. Не используйте $ в начале имени без причины — хотя $ разрешён, он часто используется в библиотеках (например, jQuery) для обозначения объектов DOM. Используйте только если это часть вашей договорённости в проекте (например, const $button = document.querySelector('#btn');). Следуйте единому стилю в команде — согласуйте стиль именования в проекте (через ESLint, Prettier или внутренний гайдлайн). Не пишите имена на кириллице — даже если JavaScript это позволяет, это снижает читаемость для международной команды и может вызвать проблемы с инструментами/редакторами. 💡 Рекомендация: «Не жалейте создавать лишнюю переменную» — лучше сделать код более читаемым через понятные имена, чем экономить на количестве строк. Например: const isEmailValid = validateEmail(userInput); // Читаемо и понятно вместо const v = validateEmail(userInput); // Неясно, что такое v ]]></description><link>материалы/подтемы/секция-1.-javascript/правила-наименования-переменных-в-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Правила наименования переменных в JavaScript.md</guid><pubDate>Fri, 12 Sep 2025 17:15:13 GMT</pubDate></item><item><title><![CDATA[Базовое понимание синтаксиса JavaScript]]></title><description><![CDATA[В рамках данной темы рассматриваются только базовые элементы синтаксиса JavaScript, необходимые для начала практической работы. Полный объём синтаксических конструкций — от операторов и структур управления до модулей, классов, асинхронности и деструктуризации — будет изучаться последовательно в последующих разделах курса. Настоящая часть служит фундаментом для понимания структуры кода, а не исчерпывающим руководством по языку.Комментарии не влияют на выполнение кода и предназначены исключительно для повышения читаемости и документирования.JavaScript поддерживает два типа комментариев: Однострочные — начинаются с //. Все, что следует после // до конца строки, игнорируется движком. // Это однострочный комментарий
let x = 5; // Можно писать и в конце строки Многострочные — заключаются между /* и */. Позволяют комментировать несколько строк или блоки кода. /*
Это многострочный комментарий
Используется для описания функций, модулей или временного отключения кода
*/
let y = 10;
JavaScript — язык, чувствительный к регистру. Это означает, что имена переменных, функций, ключевых слов и свойств различаются по написанию букв в верхнем и нижнем регистре.
Примеры: let name = "Анна";
let Name = "Иван"; // Это другая переменная
let NAME = "Олег"; // И ещё одна console.log(name); // "Анна"
console.log(Name); // "Иван"
console.log(NAME); // "Олег"
То же относится к ключевым словам: let — корректно, Let — ошибка (если не является именем переменной).
Также чувствительны к регистру названия свойств объектов: user.name ≠ user.Name.В JavaScript точки с запятой (;) используются для явного завершения инструкций. Хотя язык позволяет опускать их в большинстве случаев благодаря автоматической вставке точек с запятой (ASI — Automatic Semicolon Insertion), рекомендуется всегда использовать точки с запятой для предотвращения неочевидных ошибок. ]]></description><link>материалы/подтемы/секция-1.-javascript/базовое-понимание-синтаксиса-javascript.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Базовое понимание синтаксиса JavaScript.md</guid><pubDate>Fri, 12 Sep 2025 17:06:48 GMT</pubDate></item><item><title><![CDATA[Что такое JavaScript, история появления]]></title><description><![CDATA[JavaScript — это динамический, интерпретируемый язык программирования, изначально разработанный для добавления интерактивности на веб-страницы. Он является одним из трёх основных технологий веб-разработки (наряду с HTML и CSS) и позволяет управлять поведением веб-приложений: обрабатывать события, изменять содержимое страницы, взаимодействовать с сервером и многое другое. Сегодня JavaScript работает не только в браузерах, но и на стороне сервера, в мобильных приложениях, десктопных программах и даже в устройствах Интернета вещей.Это мультипарадигмальный язык, что означает, он поддерживает несколько стилей (парадигм) программирования, и разработчик может выбирать подход, наиболее подходящий для решения задачи. Основные поддерживаемые парадигмы: Функциональное программирование — функции являются первоклассными объектами, можно передавать их как аргументы, возвращать из других функций, создавать замыкания. Поддерживаются чистые функции, иммутабельность, высшие порядки (map, filter, reduce). Объектно-ориентированное программирование (ООП) — через прототипы и (с ES6) синтаксис классов реализуется инкапсуляция, наследование и полиморфизм. Объекты могут динамически расширяться, свойства и методы добавляются во время выполнения. Процедурное программирование — код может быть написан как последовательность инструкций без явного использования классов или функций высшего порядка, что удобно для простых скриптов. JavaScript обладает следующими ключевыми особенностями: Динамическая типизация — тип переменной определяется во время выполнения. Интерпретируемость — код выполняется без предварительной компиляции. Поддержка функционального и объектно-ориентированного стилей — позволяет писать код разными способами. Асинхронность — через колбэки, промисы и async/await обеспечивает неблокирующее выполнение операций. Кроссплатформенность — работает в браузерах, Node.js, React Native, Flutter (через плагины) и других средах. Пример простого кода на JavaScript: alert("Привет, мир!"); let name = "Анна"; console.log("Здравствуйте, " + name + "!"); Этот код отобразит всплывающее окно с сообщением, сохранит имя в переменную и выведет приветствие в консоль браузера.
Веб-браузеры — интерактивные формы, анимации, динамическая загрузка контента. Фронтенд-фреймворки — React, Vue, Angular. Бэкенд — Node.js для серверной логики. Мобильные приложения — React Native, Ionic, NativeScript. Десктопные приложения — Electron. Игры — с использованием Canvas или WebGL. IoT — управление устройствами через JavaScript-среды (например, Johnny-Five).
В середине 1990-х годов веб был преимущественно статичным: HTML описывал структуру, CSS — оформление, но не было инструментов для взаимодействия с пользователем. Нужен был язык, который позволил бы браузерам выполнять простые действия — проверку форм, анимации, реакцию на клики — без обращения к серверу. Netscape Communications, одна из ведущих компаний того времени, решила создать такой язык.В 1995 году Брендан Эйх, работающий в Netscape, за десять дней разработал язык, первоначально названный Mocha, затем LiveScript, а в конце года — JavaScript. Название было выбрано в маркетинговых целях — чтобы ассоциироваться с популярным Java (несмотря на то, что языки принципиально различны). JavaScript был внедрён в браузер Netscape Navigator 2.0.В 1996 году Netscape передала язык в Ecma International для стандартизации. В 1997 году был принят стандарт ECMAScript 1 (ES1). С тех пор язык развивается под управлением Ecma TC39. Каждые 12 месяцев выпускается новая версия стандарта (ES6/ES2015, ES2020, ES2024 и т.д.), которые добавляют новые возможности: стрелочные функции, модули, классы, промисы, деструктуризацию и другие.Сегодня JavaScript — один из самых популярных языков программирования в мире (по данным Stack Overflow, GitHub и других источников). Его экосистема включает тысячи библиотек и фреймворков. Благодаря Node.js он стал универсальным языком, применяемым как на клиенте, так и на сервере. В мобильной разработке JavaScript используется в таких фреймворках, как React Native, позволяя создавать нативные приложения для iOS и Android на единой кодовой базе. Развитие продолжается: активно внедряются новые API, улучшается производительность движков (V8, SpiderMonkey), растёт поддержка TypeScript как надмножества JavaScript.]]></description><link>материалы/подтемы/секция-1.-javascript/что-такое-javascript,-история-появления.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Что такое JavaScript, история появления.md</guid><pubDate>Fri, 12 Sep 2025 16:56:13 GMT</pubDate></item><item><title><![CDATA[Основные технологии для разработки мобильных приложений]]></title><description><![CDATA[Нативная разработка предполагает использование официальных языков программирования, сред разработки и фреймворков, предоставляемых производителями платформ — Apple и Google. Приложения компилируются напрямую в машинный код, обеспечивающий максимальную производительность и полный доступ к API устройства.Для разработки приложений под iOS используется Swift — язык, созданный Apple в 2014 году как современная замена Objective-C. Swift отличается чистым синтаксисом, безопасностью типов, поддержкой функционального программирования и высокой скоростью выполнения. Он активно развивается и является стандартом для новых проектов.Вместо него до сих пор встречается Objective-C — унаследованный от NeXTSTEP язык, который использовался в iOS до появления Swift. Он остаётся актуальным при поддержке старых проектов, но новые разработчики начинают с Swift.Инструмент разработки — Xcode, единственный официально поддерживаемый IDE от Apple. Он включает в себя редактор кода, симулятор устройств, инструменты отладки, профилирования производительности и систему управления версиями (Git). Xcode работает только на macOS, что делает разработку под iOS невозможной на Windows или Linux без виртуализации.Фреймворки интерфейса:
UIKit — традиционный фреймворк для создания пользовательских интерфейсов. Работает на основе иерархии представлений (UIView), требует детального описания макетов через код или Interface Builder. Подходит для сложных, детально настраиваемых интерфейсов.
SwiftUI — декларативный фреймворк, представленный в 2019 году. Позволяет описывать интерфейс как функцию состояния приложения — «что должно отображаться при данном состоянии», а не «как его построить». Упрощает разработку, обеспечивает автоматическую адаптацию под все размеры экранов и темы (светлая/тёмная), и полностью интегрирован с Swift. Считается будущим iOS-разработки.
Обе технологии работают с экосистемой Apple: Core Animation, Core Location, ARKit, HealthKit, Face ID, Push Notifications — всё доступно через единые API, документированные и стабильно поддерживающиеся Apple.Основным языком для Android сегодня является Kotlin — язык, разработанный JetBrains и официально объявленный Google предпочтительным для Android-разработки с 2019 года. Kotlin сочетает в себе функциональные и объектно-ориентированные парадигмы, обладает более безопасной системой типов (отсутствие null-pointer исключений по умолчанию), сжатым синтаксисом и полной совместимостью с Java.Java остаётся актуальной благодаря огромной базе legacy-приложений и корпоративных систем. Многие библиотеки, туториалы и инструкции всё ещё написаны на Java, но новые проекты рекомендуют начинать с Kotlin.Среда разработки — Android Studio, основанная на IntelliJ IDEA. Она предоставляет полноценный набор инструментов: эмулятор устройств, профайлер памяти и сети, анализатор производительности, инструменты для тестирования и поддержку Firebase. Работает на Windows, macOS и Linux — обеспечивает большую доступность, чем Xcode.Фреймворки интерфейса:
XML-разметка + View-система — классический подход. Интерфейс описывается в XML-файлах, а логика — в Kotlin/Java-классах. Требует явного связывания элементов UI с кодом (findViewById()), что создаёт больше шаблонного кода и потенциальных ошибок.
Jetpack Compose — современный декларативный фреймворк, аналог SwiftUI. Позволяет описывать интерфейс как функцию состояния, используя только Kotlin. Компоненты (Composables) перерисовываются автоматически при изменении данных. Упрощает создание динамических интерфейсов, снижает количество кода и повышает читаемость. С 2023 года считается основным стандартом для новых проектов.
Android также предлагает богатую экосистему Jetpack — набор библиотек (ViewModel, Room, Navigation, DataStore, WorkManager и др.), которые решают типовые задачи: управление жизненным циклом, работа с базами данных, фоновые задачи, маршрутизация между экранами — всё стандартизировано и поддерживается Google.Кроссплатформенные технологии позволяют писать один код, который компилируется в нативные приложения для iOS и Android. Отличие от гибридных — отсутствие WebView: вместо веб-страницы приложение использует настоящие нативные компоненты или собственные рендереры, что обеспечивает близкую к нативной производительность.Разработан Google и представлен в 2017 году. Основан на языке Dart — объектно-ориентированном языке с быстрой компиляцией и поддержкой JIT/AOT (Just-in-Time / Ahead-of-Time). Flutter компилирует код напрямую в нативный ARM-код, минуя виртуальную машину.Ключевая особенность — декларативная widget-архитектура. Весь интерфейс строится из деревьев виджетов — каждый элемент (кнопка, текст, список) — это виджет, который может быть изменён, вложен или переиспользован. Даже отступы и цвета — это виджеты.Flutter не использует нативные UI-компоненты iOS или Android. Вместо этого он рендерит собственные элементы с помощью графического движка Skia — то же, что используется в Chrome и Android. Это даёт:
Единый дизайн на всех платформах — приложение выглядит одинаково на iPhone и Samsung.
Высокую производительность — 60–120 FPS даже на сложных анимациях.
Гибкость дизайна — можно создавать уникальные интерфейсы, не привязанные к Material Design или Human Interface Guidelines.
Ограничения: больший размер приложения (включает рендер-движок), ограниченная интеграция с некоторыми нативными API без написания плагинов на Swift/Kotlin, менее «родной» UX на iOS, если не следовать гайдлайнам вручную.Flutter идеален для проектов с акцентом на дизайн: продукты с уникальной визуальной идентичностью, маркетплейсы, сервисы с частыми анимациями, MVP-стартапы, где важна скорость выхода на два рынка.Разработан Meta (ранее Facebook) в 2015 году. Основан на JavaScript и TypeScript — языках, уже знакомых миллионам веб-разработчиков. React Native использует принцип React — компонентный подход, где интерфейс строится из повторно используемых компонентов, реагирующих на изменения состояния.Архитектура React Native основана на JS-бриджe: JavaScript-код выполняется в отдельном потоке, а вызовы к нативным компонентам (кнопки, списки, камера) передаются через мост. Это позволяет использовать настоящие нативные UI-элементы, но создаёт задержки при частых взаимодействиях между JS и нативным кодом.Преимущества:
Высокая скорость разработки для команд с опытом в вебе.
Большое сообщество и множество готовых библиотек (npm).
Возможность частичного перехода: можно внедрять React Native-экраны в существующее нативное приложение.
Поддержка горячей перезагрузки (Hot Reload) — изменения видны мгновенно.
Ограничения:
Производительность ниже, чем у Flutter или нативных приложений — особенно при сложной анимации или работе с большим количеством данных.
Зависимость от сторонних библиотек для доступа к API — многие требуют установки и настройки нативных модулей (Native Modules).
Разница в поведении между iOS и Android — некоторые компоненты могут работать по-разному, требуя платформо-специфичного кода.
Сложность отладки: ошибки могут возникать как в JS, так и в нативном коде, затрудняя диагностику.
React Native популярен в компаниях, где есть команда веб-разработчиков, нуждающаяся в выходе на мобильный рынок без полного переобучения. Примеры: Facebook, Instagram, Skype, Walmart, Tesla.Разработан Microsoft, ранее известный как Xamarin Forms. Использует язык C# и фреймворк .NET — популярный в корпоративной разработке. В 2022 году Xamarin был объединён с .NET Multi-platform App UI (.NET MAUI) — современной версией, поддерживающей не только iOS и Android, но и Windows, macOS.Отличие от React Native и Flutter: Xamarin/.NET MAUI не использует мост. Код компилируется напрямую в нативный код через Mono или .NET runtime, что обеспечивает лучшую производительность и меньшие накладные расходы.Плюсы:
Полный доступ к нативным API через привязки (bindings) — почти все функции устройства доступны «из коробки».
Единая кодовая база для мобильных и десктопных приложений.
Интеграция с Visual Studio и Azure — удобна для корпоративных проектов.
Сильная типизация и безопасность C#.
Минусы:
Меньшее сообщество по сравнению с Flutter и React Native.
Более сложная настройка, особенно для новичков.
Менее гибкий UI — интерфейс часто выглядит «по-Windows», если не применять платформо-специфичные стили.
Медленнее развитие экосистемы по сравнению с Google и Meta.
.NET MAUI подходит для enterprise-решений: внутренние корпоративные приложения, ERP-системы, CRM, медицинские терминалы, приложения с интеграцией в облачные сервисы Microsoft (Azure, Office 365).]]></description><link>материалы/подтемы/секция-1.-javascript/основные-технологии-для-разработки-мобильных-приложений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Основные технологии для разработки мобильных приложений.md</guid><pubDate>Fri, 12 Sep 2025 16:11:15 GMT</pubDate></item><item><title><![CDATA[Основные типы мобильных приложений]]></title><description><![CDATA[Мобильное приложение — это не просто программа, запущенная на смартфоне. Его тип определяется тем, как оно создано, на чём работает и как взаимодействует с операционной системой и аппаратными компонентами устройства. Выбор типа приложения влияет на производительность, сроки разработки, стоимость поддержки и качество пользовательского опыта. Существует четыре основных типа: нативные, веб-приложения, гибридные и кроссплатформенные.Нативные приложения — это программы, разработанные специально для одной конкретной платформы с использованием официальных языков программирования, SDK и инструментов, предоставленных её создателем.Для iOS приложения пишутся на Swift или Objective-C с использованием фреймворков UIKit и SwiftUI, собираются в Xcode и компилируются напрямую в машинный код для архитектуры ARM процессоров Apple.
Для Android — на Kotlin или Java с использованием Android SDK, сборка происходит через Android Studio в APK или AAB-файлы, которые затем интерпретируются Android Runtime (ART).Преимущества: Максимальная производительность — код выполняется напрямую на устройстве без промежуточных слоёв. Полный доступ ко всем API устройства: камера, GPS, Bluetooth, сенсоры, биометрия, уведомления, фоновые задачи. Соответствие стандартам платформы (Human Interface Guidelines для iOS, Material Design для Android) — обеспечивает интуитивный и «родной» пользовательский опыт. Лучшая стабильность и поддержка обновлений ОС — разработчики получают ранний доступ к новым функциям через beta-версии SDK.
Ограничения: Требуется отдельная команда разработчиков для каждой платформы — удвоение затрат на разработку и тестирование. Дублирование логики и дизайна между версиями — увеличивает время выхода на рынок. Высокая зависимость от экосистемы: обновление API может потребовать переписывания значительной части кода.
Области применения:
Нативные приложения — стандарт для проектов, где важны скорость, надёжность и глубокая интеграция с устройством: банковские и финансовые приложения, игры, AR/VR-решения, медицинские системы, приложения с реальным временем (например, такси, доставка), корпоративные инструменты с высокими требованиями к безопасности.Веб-приложения — это сайты, спроектированные так, чтобы вести себя как мобильные приложения. Они работают в браузере, но могут быть добавлены на домашний экран, работать оффлайн и отправлять уведомления благодаря технологиям PWA.Основаны на стандартных веб-технологиях: HTML5, CSS3, JavaScript, а также Service Workers (для кэширования и работы без интернета), Web App Manifest (для определения иконки, имени, цвета темы) и Push API.Преимущества: Одна кодовая база — работает на всех устройствах с браузером (iOS, Android, даже десктоп). Нет необходимости проходить модерацию в магазинах приложений — публикация мгновенная. Низкие затраты на разработку и обслуживание. Не требует установки — пользователь сразу переходит по ссылке. Автоматическое обновление — изменения видны сразу после релиза.
Ограничения: Ограниченный доступ к аппаратным возможностям устройства: нет прямого доступа к контактам, файловой системе, Bluetooth Low Energy, NFC, гироскопу в некоторых случаях. Невозможность использовать многие нативные UI-компоненты — интерфейс выглядит как сайт, а не как приложение. Зависимость от браузера: производительность и совместимость различаются между Safari, Chrome, Firefox. Отсутствие в App Store и Google Play — потеря видимости, возможности рейтингов, рекомендаций и внутренних покупок через официальные каналы.
Области применения:
PWA подходят для контентных сервисов, информационных сайтов, электронной коммерции с простой логикой, корпоративных порталов, приложений с низким уровнем взаимодействия: онлайн-газеты, каталоги товаров, формы обратной связи, калькуляторы, лендинги. Особенно эффективны там, где важна скорость распространения и минимальные затраты — например, маркетинговые кампании или временные акции.Гибридные приложения — это веб-приложения, обёрнутые в «оболочку» нативного контейнера (WebView), который позволяет им запускаться как обычные мобильные приложения из магазинов. Они используют веб-технологии (HTML/CSS/JS), но имеют доступ к нативным API через плагины.Популярные фреймворки: Apache Cordova (ранее PhoneGap) и Ionic (основан на Angular/React/Vue + Cordova).Преимущества: Одна кодовая база для iOS и Android — снижение затрат на разработку. Возможность публикации в App Store и Google Play — как нативные приложения. Быстрая разработка для команд с опытом в вебе. Поддержка большинства базовых функций: камера, геолокация, уведомления, файловая система — через плагины.
Ограничения: Производительность ниже, чем у нативных — все операции проходят через WebView, что создаёт задержки, особенно при анимациях и сложной графике. Плагины часто устаревают или плохо документированы — могут вызывать баги на новых версиях ОС. UX редко достигает уровня «родного» приложения — интерфейс чувствуется как «веб-страница в обёртке». Ограниченный доступ к современным нативным функциям (например, Face ID, ARKit, Android Jetpack Compose).
Области применения:
Гибридные приложения подходят для прототипирования, MVP-проектов, внутренних корпоративных инструментов, приложений с простой логикой и минимальным взаимодействием с оборудованием: учётные системы, формы регистрации, CRM-клиенты, базовые лояльностные программы. Идеальны, когда бюджет ограничен, а сроки — жёсткие, и требуется быстрый выход на два рынка.Кроссплатформенные приложения — это приложения, написанные на одном языке и фреймворке, которые компилируются в нативный код для разных платформ. Это не обёртки, а генерация нативных компонентов на основе единого исходного кода.Популярные фреймворки: Flutter (Dart, от Google), React Native (JavaScript/TypeScript, от Meta), Xamarin (C#, от Microsoft), Kivy (Python, редко используется в коммерческой разработке).Отличие от гибридных: вместо WebView они используют настоящие нативные UI-компоненты (например, Flutter рисует собственные виджеты, React Native вызывает native UI элементы iOS/Android напрямую).Преимущества: Одна кодовая база — до 80–95% общего кода между iOS и Android. Производительность близка к нативной — особенно в Flutter и React Native с правильной оптимизацией. Доступ к большинству нативных API через библиотеки (например, Firebase, Mapbox, camera plugin). Современный UI — возможность создавать уникальный дизайн, не привязанный к стандартам платформы. Активное сообщество, регулярные обновления, хорошая документация.
Ограничения: Некоторые функции требуют написания нативного кода (Java/Kotlin, Swift/Objective-C) — если нужна глубокая интеграция с OS. Размер приложения больше, чем у чисто нативного (особенно в Flutter — включает движок рендеринга). Возможны баги на границах платформ — поведение одного и того же компонента может отличаться на iOS и Android. Обучение новому языку (Dart, TypeScript) требует времени для команд, привыкших к Java/Kotlin или Swift.
Области применения:
Кроссплатформенные решения — выбор большинства стартапов, компаний с ограниченным бюджетом, но амбициозными целями. Подходят для социальных сетей, мессенджеров, e-commerce, финтех-приложений, образовательных платформ, приложений с частыми обновлениями и необходимостью быстро масштабироваться. Примеры: Facebook, Instagram (частично), Uber Eats, Alibaba, Tencent.]]></description><link>материалы/подтемы/секция-1.-javascript/основные-типы-мобильных-приложений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Основные типы мобильных приложений.md</guid><pubDate>Fri, 12 Sep 2025 16:07:07 GMT</pubDate></item><item><title><![CDATA[Основные платформы мобильных приложений]]></title><description><![CDATA[Платформа мобильных приложений — это совокупность программного обеспечения, инструментов, стандартов и правил, которые определяют, как создаются, устанавливаются и работают мобильные приложения на конкретном устройстве. Это не просто операционная система (ОС), а целая экосистема: от ядра ОС и API-интерфейсов до магазинов приложений, систем подписок, политик безопасности и требований к разработчикам. Выбор платформы напрямую влияет на: доступные функции устройства (камера, GPS, биометрия); способы взаимодействия с пользователем; методы тестирования и отладки; стратегию монетизации и распространения; сроки и стоимость разработки. На сегодняшний день подавляющее большинство мобильных приложений создаётся для двух основных платформ — iOS и Android. Их доминирование обусловлено масштабами рынка, зрелостью инструментов и поддержкой со стороны крупнейших технологических компаний.iOS — экосистема Apple, работающая на устройствах iPhone, iPad и iPod touch. Закрытая, строго контролируемая платформа с единым стандартом качества, высокой безопасностью и стабильной производительностью. Основная аудитория — пользователи в развитых странах, с высоким уровнем дохода и лояльностью к бренду.Android — открытая операционная система от Google, используемая сотнями производителей (Samsung, Xiaomi, OnePlus, Motorola и др.). Обладает огромной фрагментацией устройств и версий, но обеспечивает максимальную доступность и гибкость для разработчиков и пользователей. Доминирует в развивающихся рынках и по объёму установленных устройств — более 70% глобального рынка смартфонов.Но, помимо iOS и Android, на протяжении истории мобильных технологий существовали и другие платформы, которые либо имели значительную долю рынка, либо обладали высоким потенциалом, но в итоге уступили место доминирующим системам.Windows Phone (Microsoft) — запущенная в 2010 году платформа, основанная на ядре Windows NT, предлагала уникальный пользовательский интерфейс с динамическими «живыми» плитками. Несмотря на техническую изящность и глубокую интеграцию с экосистемой Microsoft (Outlook, Office, OneDrive), она не смогла привлечь достаточное количество разработчиков. Отсутствие приложений, особенно популярных сервисов вроде Instagram или WhatsApp на ранних этапах, стало фатальным. Microsoft официально прекратила поддержку Windows Phone в 2017 году.BlackBerry OS / BlackBerry 10 — до середины 2000-х годов BlackBerry была синонимом корпоративной мобильности благодаря надёжной безопасности, физической клавиатуре и собственной сети Push Mail. Однако компания не сумела адекватно ответить на рост сенсорных экранов и экосистемы приложений. Попытка перезапуска с BlackBerry 10 в 2013 году, основанной на QNX, оказалась слишком поздней — к тому времени пользователи уже массово перешли на iOS и Android. В 2016 году BlackBerry перестала производить собственные устройства.Symbian — когда-то самая популярная мобильная ОС, особенно в Европе и Азии, Symbian использовалась Nokia, Samsung, Siemens и другими. Она доминировала на рынке до 2007 года, но её архитектура, унаследованная от эпохи кнопочных телефонов, не позволила эффективно адаптироваться к новым требованиям тачскринов и мультимедиа. После выхода iPhone и Android, Nokia в 2011 году перешла на Windows Phone, а Symbian была официально закрыта в 2014 году.WebOS (Palm, затем HP) — оригинальная и продвинутая система с многооконным интерфейсом, предшественник современных концепций многозадачности. Palm выпустила первые устройства на WebOS в 2009 году, а HP попыталась развивать платформу дальше, даже выпустив планшет TouchPad. Но недостаток приложений, маркетинговой поддержки и внутренние конфликты в HP привели к отказу от WebOS в 2011 году. Позже HP передала код проекта LG, который использовал его для своих смарт-телевизоров — но как мобильная ОС WebOS так и не возродилась.HarmonyOS (Huawei) — современный пример платформы, появившейся как ответ на геополитические ограничения. Разработанная Huawei в 2019 году после запрета Google на использование GMS (Google Mobile Services), HarmonyOS изначально позиционировалась как универсальная ОС для IoT-устройств, а позже — как замена Android на смартфонах. Хотя она технически совместима с Android-приложениями через App Pack, её глобальное распространение ограничено из-за отсутствия доступа к ключевым сервисам Google и западным приложениям. На сегодня — это важный региональный игрок (особенно в Китае), но не глобальная альтернатива iOS/Android.iOS и Android — две доминирующие мобильные платформы, отличающиеся не только архитектурой, но и философией разработки, подходом к безопасности, экосистеме и взаимодействию с пользователем. Их сравнение позволяет понять фундаментальные различия, которые влияют на процесс создания мобильных приложений.Языки программирования и инструменты разработки
iOS-приложения разрабатываются преимущественно на языке Swift (с 2014 года), а также на Objective-C — унаследованном от эпохи NeXTSTEP. Интегрированная среда разработки — Xcode, доступная исключительно на macOS. Это накладывает ограничения: разработка под iOS невозможна без устройства Apple или виртуальной машины с macOS.
Android-приложения пишутся на Kotlin (рекомендуемый язык с 2019 года) или Java (традиционный, но постепенно вытесняемый). Среда разработки — Android Studio, основанная на IntelliJ IDEA, работает на Windows, macOS и Linux, что обеспечивает большую доступность для разработчиков.Архитектура и управление ресурсами
iOS использует закрытую, унифицированную архитектуру: ограниченное количество моделей устройств с жёстко контролируемыми характеристиками (память, процессор, экран). Это позволяет оптимизировать приложения под конкретные аппаратные конфигурации, обеспечивая высокую производительность и стабильность.
Android, напротив, работает на тысячах устройств с разными процессорами, объёмами ОЗУ, плотностями пикселей и версиями ОС. Разработчику приходится учитывать фрагментацию — от старых смартфонов с Android 8 до новых с Android 14 — и применять адаптивные интерфейсы, проверять совместимость и использовать библиотеки поддержки (Android Support Library / AndroidX).Магазины приложений и политики распространения
Приложения для iOS распространяются исключительно через App Store — строго централизованный и контролируемый канал. Apple проводит ручную модерацию каждого приложения, требует соблюдения строгих гайдлайнов по дизайну, приватности и функциональности. Это повышает уровень безопасности для пользователей, но замедляет выпуск обновлений и ограничивает возможности монетизации (например, запрещены сторонние магазины и системы внутренних покупок вне App Store).
Android-приложения могут распространяться через Google Play, но также допускается установка из сторонних источников (APK-файлы). Google Play имеет автоматизированную модерацию, менее строгие требования, но более высокий риск распространения вредоносного ПО. Это делает Android более открытой, но требует от разработчика дополнительных мер по защите приложения и информированию пользователей о безопасности.Доля рынка и целевая аудитория
По количеству установленных устройств Android доминирует — около 70–75% глобального рынка смартфонов, особенно в Азии, Африке и Латинской Америке. При этом iOS занимает около 25–30%, но сосредоточена в странах с высоким уровнем дохода — США, Западная Европа, Япония, Австралия.
Это создаёт принципиально разные экономические модели: приложения для iOS чаще генерируют больше дохода на одного пользователя (высокий ARPU — Average Revenue Per User), тогда как Android обеспечивает больший охват аудитории, но с меньшей monetization. Для бизнес-приложений это означает выбор между качеством и количеством.Обновления и жизненный цикл устройств
Apple контролирует полный цикл — от железа до ПО — и обеспечивает массовые обновления ОС для устройств, выпущенных до 5–6 лет назад. Более 90% активных устройств iOS работают на последних двух версиях ОС.
Android-устройства получают обновления неравномерно: производители (Samsung, Xiaomi и др.) сами решают, какие модели поддерживают, а многие бюджетные устройства остаются на устаревших версиях (Android 8–10) годами. Это вынуждает разработчиков поддерживать совместимость с множеством версий API, увеличивая сложность тестирования и развертывания.Безопасность и приватность
iOS позиционируется как более безопасная платформа благодаря изолированной среде выполнения приложений (sandboxing), строгому контролю доступа к данным (персональные файлы, камера, микрофон), шифрованию данных на уровне ОС и обязательному использованию App Transport Security.
Android предоставляет аналогичные механизмы, но их реализация зависит от производителя. Многие OEM-производители добавляют собственные сервисы, фоновые процессы и права, которые могут компрометировать приватность. Кроме того, открытость Android делает его более уязвимым к вредоносным APK-файлам, загружаемым вне Google Play.Интеграция с экосистемой
iOS тесно интегрирован с другими продуктами Apple: iCloud, AirDrop, Handoff, Continuity, Apple Watch, HomeKit. Это позволяет создавать кросс-устройственные приложения с единым пользовательским опытом.
Android интегрируется с сервисами Google: Gmail, Google Maps, Drive, Firebase, Google Assistant, Wear OS. Эти сервисы предоставляют мощные инструменты для разработчиков — особенно для аналитики (Firebase), push-уведомлений, облачного хранения и машинного обучения. Однако интеграция с другими устройствами (TV, часы, авто) менее унифицирована, чем в Apple.]]></description><link>материалы/подтемы/секция-1.-javascript/основные-платформы-мобильных-приложений.html</link><guid isPermaLink="false">Материалы/Подтемы/Секция 1. JavaScript/Основные платформы мобильных приложений.md</guid><pubDate>Fri, 12 Sep 2025 15:58:25 GMT</pubDate></item><item><title><![CDATA[Pasted image 20250906080710]]></title><description><![CDATA[<img src="pasted-image-20250906080710.png" target="_self">]]></description><link>pasted-image-20250906080710.html</link><guid isPermaLink="false">Pasted image 20250906080710.png</guid><pubDate>Sat, 06 Sep 2025 05:07:10 GMT</pubDate><enclosure url="." length="0" type="false"/><content:encoded>&lt;figure&gt;&lt;img src="."&gt;&lt;/figure&gt;</content:encoded></item></channel></rss>