Code Ready | Frontend
Авторский канал по Frontend разработке. Ресурсы, гайды, задачи, шпаргалки. Информация ежедневно пополняется! Cотрудничество: @energy_c РКН: https://clck.ru/3NJCKs
نمایش بیشتر📈 تحلیل کانال تلگرام Code Ready | Frontend
کانال Code Ready | Frontend (@code_ready) در بخش زبانی روسی بازیگری فعال است. در حال حاضر جامعه شامل 21 545 مشترک است و جایگاه 6 157 را در دسته فناوری و برنامهها و رتبه 30 472 را در منطقه روسيا دارد.
📊 شاخصهای مخاطب و پویایی
از زمان ایجاد در невідомо، پروژه رشد سریعی داشته و 21 545 مشترک جذب کرده است.
بر اساس آخرین دادهها در تاریخ 26 اکتبر, 2026، کانال فعالیت پایداری دارد. در ۳۰ روز گذشته تغییر اعضا برابر -42 و در ۲۴ ساعت گذشته برابر -20 بوده و همچنان دسترسی گستردهای حفظ شده است.
- وضعیت تأیید: تأیید نشده
- نرخ تعامل (ER): میانگین تعامل مخاطب 6.43% است و در ۲۴ ساعت نخست پس از انتشار، محتوا معمولاً 4.29% واکنش نسبت به کل مشترکان کسب میکند.
- دسترسی پستها: هر پست به طور میانگین 1 386 بازدید دریافت میکند. در اولین روز معمولاً 925 بازدید جمعآوری میشود.
- واکنشها و تعامل: مخاطبان بهطور فعال حمایت میکنند؛ میانگین واکنش به هر پست 23 است.
- علایق موضوعی: محتوا بر موضوعات کلیدی مانند css, браузер, интерфейс, загрузка, api تمرکز دارد.
📝 توضیح و سیاست محتوایی
نویسنده این فضا را محل بیان دیدگاههای شخصی توصیف میکند:
“Авторский канал по Frontend разработке.
Ресурсы, гайды, задачи, шпаргалки.
Информация ежедневно пополняется!
Cотрудничество: @energy_c
РКН: https://clck.ru/3NJCKs”
به لطف بهروزرسانیهای پرتکرار (آخرین داده در تاریخ 27 اکتبر, 2026)، کانال همواره بهروز و دارای دسترسی بالاست. تحلیلها نشان میدهد مخاطبان بهطور فعال با محتوا تعامل دارند و آن را به نقطه اثرگذاری مهم در دسته فناوری و برنامهها تبدیل کردهاند.
<small> используется для отображения второстепенного текста, который имеет меньшее значение по сравнению с основным содержимым. Он подходит для информации, которая полезна пользователю, но не является частью основного сообщения.
Для чего <small> подойдёт идеально:
• пояснения;
• комментарии;
• дисклеймеры;
• предостережения;
• копирайт;
• информация о лицензии;
• прочая правовая информация.
Важно: <small> имеет семантическое значение, а не просто уменьшает размер текста. Для изменения визуального размера обычного текста лучше использовать CSS.
📣 Code Ready | #атрибутconst element = {
value: "button"
};
element.state = {
mounted: true
};
Если свойство state уже существует в объекте, новое значение перезапишет старое. В больших приложениях такие ситуации могут быть сложными для поиска, особенно когда объект расширяется несколькими независимыми модулями.
Для решения этой задачи существует Symbol — это примитивный тип данных, который создаёт уникальные ключи свойств объектов. Каждый созданный символ является уникальным, поэтому он не может случайно совпасть с обычным строковым свойством или другим символом.
const internalState = Symbol("internalState");
const component = {
value: "button",
[internalState]: {
mounted: true
}
};
console.log(component[internalState]);
// { mounted: true }
Теперь внутренние данные хранятся по уникальному ключу. Объект можно расширять дополнительным состоянием, не изменяя его публичную структуру.
Даже если другой код добавит свойство с похожим названием, конфликт не возникнет:
component.internalState = false;
console.log(component[internalState]);
// { mounted: true }
Symbol-свойства имеют ещё одну особенность: они не отображаются в большинстве стандартных способов перебора объектов. Например, Object.keys() возвращает только строковые ключи:
Object.keys(component);
// ["value"]
Это позволяет хранить дополнительные данные внутри объекта, не добавляя их в обычное представление объекта и его публичный API. При необходимости получить символьные свойства можно явно:
Object.getOwnPropertySymbols(component);
Такой подход часто используется в библиотеках и компонентах, которым необходимо хранить внутренние данные, связанные с объектом. Например, можно добавить метаданные компонента:
const meta = Symbol("meta");
function initComponent(component) {
component[meta] = {
id: crypto.randomUUID(),
createdAt: Date.now()
};
}
После этого объект получает внутреннюю информацию, но его внешний интерфейс остаётся неизменным:
component.id;
// undefined
component[meta].id;
// UUID
Кроме пользовательских символов, JavaScript содержит встроенные Symbol, которые позволяют изменять стандартное поведение объектов:
Symbol.iterator
Symbol.asyncIterator
Symbol.toPrimitive
Например, Symbol.iterator позволяет объекту поддерживать цикл for...of:
const collection = {
items: ["a", "b"],
[Symbol.iterator]() {
return this.items[Symbol.iterator]();
}
};
for (const item of collection) {
console.log(item);
}
Важно понимать: Symbol не является механизмом настоящей приватности. Символьные свойства можно найти через:
Object.getOwnPropertySymbols();
Reflect.ownKeys();
Основная задача Symbol — создавать уникальные ключи и безопасно расширять объекты без риска конфликтов имён. Для настоящей приватности в классах JavaScript используются #private fields.
🔥 Symbol — практический инструмент для создания библиотек, компонентов и больших frontend-систем, где требуется добавлять внутренние данные, сохраняя чистый публичный API объекта.
📣 Code Ready | #практикаnovalidate используется у тега <form> и отключает стандартную валидацию полей браузером при отправке формы.
По умолчанию браузер сам проверяет такие ограничения, как:
• обязательные поля (required);
• корректность email (type="email");
• формат данных (pattern);
• минимальные и максимальные значения (min, max).
После добавления novalidate эта проверка не выполняется, и отправка формы передаётся полностью под контроль JS или серверной логики. Важно: novalidate не отключает атрибуты в HTML, а только запрещает браузеру автоматически проверять их при отправке.
📣 Code Ready | #атрибутtouchmove может вызвать event.preventDefault() и заблокировать стандартный жест браузера. Если обработчик считается непассивным, браузеру может потребоваться дождаться завершения его выполнения, прежде чем начать или продолжить прокрутку. Обычный обработчик события:
window.addEventListener(
'touchmove',
event => {
const touch = event.touches[0];
console.log(
touch.clientX,
touch.clientY
);
},
{
passive: false
}
);
В этом случае браузер должен учитывать, что обработчик потенциально может вызвать preventDefault(). Поэтому прокрутка может быть отложена до завершения выполнения JavaScript-кода.
Чтобы явно указать, что обработчик не будет отменять стандартное поведение, используется параметр passive.
window.addEventListener(
'touchmove',
event => {
const touch = event.touches[0];
console.log(
touch.clientX,
touch.clientY
);
},
{
passive: true
}
);
Теперь браузер знает, что обработчик не вызовет preventDefault(), и может обрабатывать прокрутку без ожидания завершения JavaScript-кода.
Следует учитывать, что современные браузеры в некоторых случаях автоматически используют пассивный режим для обработчиков touchstart, touchmove, wheel и mousewheel, зарегистрированных на window, document или body. Конкретное поведение зависит от браузера, события и целевого элемента. Поэтому, если обработчик должен гарантированно вызывать preventDefault(), лучше явно указать:
{
passive: false
}
Событие scroll отличается тем, что возникает после изменения позиции прокрутки и не может быть отменено через preventDefault(). Поэтому использование passive для scroll не даёт преимуществ производительности. Например:
window.addEventListener(
'scroll',
() => {
const position = window.scrollY;
document.querySelector(
'.header'
).style.opacity = Math.min(
position / 500,
1
);
}
);
В данном примере при каждом вызове обработчика выполняется поиск элемента в DOM и изменяется его стиль. При высокой частоте событий это создаёт дополнительную нагрузку на основной поток.
В подобных случаях эффективнее заранее сохранить ссылку на элемент, сократить объём выполняемой работы и при необходимости использовать requestAnimationFrame или throttling.
const header = document.querySelector('.header');
let scheduled = false;
window.addEventListener('scroll', () => {
if (scheduled) {
return;
}
scheduled = true;
requestAnimationFrame(() => {
header.style.opacity = Math.min(
window.scrollY / 500,
1
);
scheduled = false;
});
});
debounce обычно применяют для действий, которые должны выполняться после завершения прокрутки, например для отправки аналитики или сохранения состояния интерфейса.
Также важно учитывать, что passive: true запрещает отмену стандартного поведения события. Вызов:
event.preventDefault();
Внутри пассивного обработчика не остановит стандартное поведение браузера и обычно приведёт к предупреждению в консоли.
window.addEventListener(
'touchmove',
event => {
event.preventDefault();
},
{
passive: true
}
);
passive: true целесообразно использовать, если обработчик только анализирует событие или обновляет интерфейс и ему не требуется вызывать preventDefault(). Если обработчик должен отменять стандартное поведение браузера, его нельзя делать пассивным.
🔥 Passive Event Listeners уменьшают задержки при обработке touch- и wheel-событий, поскольку браузеру не требуется ожидать возможного вызова preventDefault(). При этом они не устраняют проблемы, связанные с тяжёлыми JavaScript-обработчиками.
📣 Code Ready | #практика• работу с Linux и командной строкой • Git и контроль версий в реальных проектах • создание Docker-образов и запуск контейнеров • автоматизацию сборки, тестирования и деплоя в GitLab CI/CD • развёртывание и управление приложениями в Kubernetes • сети, хранилища, конфигурации и секреты • диагностику инфраструктуры и автоматизацию рутинных задач ... и многое другоеВсе знания закрепляются на практике с помощью заданий с автопроверкой. Материал подаётся последовательно и понятным языком: с примерами, схемами и демонстрациями. Во время обучения можно задавать вопросы по урокам и заданиям, получать обратную связь и помощь при возникновении сложностей. После прохождения программы вы получите сертификат, который можно добавить в резюме. Скидка 20% на 48 часов: по промокоду
READY20 стоимость всей программы составит 10 392 ₽.
Открыть программу на Stepik:valid и :invalid в CSS позволяют стилизовать поля формы в зависимости от результата встроенной HTML-валидации. Они работают с ограничениями вроде required, pattern, min, max, type="email" и другими.
Как это используется:
• :valid — поле заполнено корректно;
• :invalid — значение не прошло проверку;
• можно менять цвет рамки, фона или отображать состояние поля.
Это простой способ сделать форму более понятной для пользователя, не прибегая к JS.
📣 Code Ready | #свойство<h1>Новый<br>релиз CSS</h1>
Или вставляют , <wbr> и другие ручные переносы.
Теперь с этим может помочь сам браузер.
h1 {
text-wrap: balance;
}
Браузер старается более равномерно распределить текст между строками, чтобы заголовок выглядел аккуратнее. Лучше всего использовать это для коротких текстов: заголовков, подзаголовков, цитат и подписей.
Для длинных абзацев есть отдельный режим.
p {
text-wrap: pretty;
}
Он старается избегать неудачных переносов и слишком коротких последних строк. Если браузер его не поддерживает, текст просто будет переноситься как обычно.
🔥 text-wrap: balance и text-wrap: pretty позволяют заметно улучшить типографику буквально одной строкой CSS.
📣 Code Ready | #советRange позволяет описать участок документа между двумя точками в DOM и выполнять операции именно над этим фрагментом. Важно понимать разницу между Selection и Range.
Selection хранит то, что пользователь выделил мышкой, а Range описывает конкретные границы этого выделения и даёт инструменты для работы с ним. Например, получим текущее выделение пользователя:
const selection = window.getSelection();
if (selection.rangeCount > 0) {
const range = selection.getRangeAt(0);
console.log(range.toString());
}
После получения Range мы можем работать с выбранным участком документа.
Метод toString() удобен, когда нужен только текст выделения. Но он возвращает обычную строку и не сохраняет HTML-структуру внутри этого фрагмента. Например, есть такой DOM:
<p>
Hello <strong>JavaScript</strong>
</p>
Если получить текст через:
range.toString();
мы получим: Hello JavaScript. Вся внутренняя структура будет потеряна, потому что результатом является просто строка.
Если нужно сохранить HTML-узлы внутри выделенного участка, используется cloneContents(). Этот метод создаёт копию выбранного фрагмента в виде DocumentFragment, сохраняя вложенные элементы:
const fragment = range.cloneContents();
document.body.appendChild(fragment);
Теперь вместе с текстом сохранится и структура:
<strong>JavaScript</strong>
Range можно не только получать из пользовательского выделения, но и создавать вручную. Например, можно программно выделить всё содержимое определённого элемента:
const element = document.querySelector('#editor');
const range = document.createRange();
range.selectNodeContents(element);
Теперь диапазон знает, какой фрагмент DOM нужно выделить.
Остаётся передать его в объект Selection, чтобы браузер показал это выделение пользователю:
const selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(range);
После выполнения браузер выделит всё содержимое элемента. Но Range нужен не только для чтения выделений. С его помощью можно изменять DOM в конкретной позиции.
Например, заменить выделенный пользователем текст:
const range = window
.getSelection()
.getRangeAt(0);
const span = document.createElement('span');
span.textContent = 'Новый текст';
range.deleteContents();
range.insertNode(span);
Сначала deleteContents() удаляет выбранный фрагмент, а затем insertNode() вставляет новый элемент точно туда, где находился диапазон. Это особенно полезно в редакторах текста, где нужно сохранить структуру документа и позицию изменения.
Есть ещё один похожий метод — extractContents(). В отличие от cloneContents(), который создаёт копию, extractContents() забирает содержимое из DOM и удаляет его с текущего места:
const fragment = range.extractContents();
Полученный DocumentFragment можно затем вставить в другой участок документа. Range API используется внутри rich text редакторов, систем подсветки поиска, комментариев и любых интерфейсов, где требуется работать с отдельными частями документа.
🔥 Range API — инструмент для точной работы с фрагментами DOM: выделять, копировать, извлекать, удалять и заменять части документа без полной пересборки элемента.
📣 Code Ready | #практикаЭта шпаргалка по ключевым приёмам работы с RegExp: квантификаторы, группы, классы символов, флаги и проверки начала или конца строки. Подойдёт для валидации данных, парсинга текста и оптимизации поиска.
📣 Code Ready | #шпора<search> используется для обозначения секции страницы, которая содержит поиск или элементы фильтрации. Он помогает браузерам, поисковым системам и вспомогательным технологиям лучше понимать структуру страницы.
Использовать <search> можно для:
• формы поиска по сайту;
• фильтров каталога;
• панели поиска по таблицам или спискам;
• блока с настройками фильтрации.
Важно: тег относительно новый, поэтому поддержка в некоторых браузерах и вспомогательных технологиях пока развивается. При необходимости можно дополнительно использовать role="search".
📣 Code Ready | #атрибутconst fade = element.animate(
[
{ opacity: 0 },
{ opacity: 1 }
],
{
duration: 300
}
);
const move = element.animate(
[
{ transform: 'translateY(20px)' },
{ transform: 'translateY(0)' }
],
{
duration: 300
}
);
Браузер создаёт отдельные Animation-объекты и объединяет их эффекты при расчёте итогового стиля элемента.
У каждой анимации есть собственное состояние:
console.log(fade.playState);
console.log(move.currentTime);
currentTime позволяет управлять прогрессом вручную:
fade.currentTime = 150;
Анимация сразу перейдёт примерно к середине выполнения. Это полезно для синхронизации анимаций с внешним состоянием, например с прогрессом загрузки:
animation.currentTime =
progress * animation.effect.getTiming().duration;
Также Web Animations API позволяет изменять параметры уже созданного эффекта:
animation.effect.updateTiming({
duration: 1000
});
При этом не нужно пересоздавать анимацию. Отдельно стоит учитывать композицию свойств. Если два эффекта изменяют один и тот же параметр:
element.animate(
[
{ transform: 'translateX(100px)' }
],
{
duration: 1000
}
);
element.animate(
[
{ transform: 'scale(1.2)' }
],
{
duration: 1000
}
);
Оба эффекта работают с одним CSS-свойством transform. Итоговое поведение зависит от правил композиции анимаций, поэтому параллельное изменение одного свойства может дать неожиданный результат.
Для сложных случаев можно управлять композицией через composite:
element.animate(
[
{
transform: 'translateX(100px)'
}
],
{
duration: 500,
composite: 'add'
}
);
В этом режиме новое значение добавляется к существующему, а не заменяет его.
🔥 Element.animate() — это не просто замена CSS keyframes. Web Animations API предоставляет полноценную модель управления анимациями: состояние, время выполнения, изменение параметров и правила композиции эффектов.
📣 Code Ready | #практика• Показывается, как создать интерактивные презентации, которые работают полностью офлайн в одном HTML-файле без установки программ и регистрации;
• Разбираются возможности редактора: встроенные видео, анимации, таймеры, интерактивные элементы и др;
• Объясняется, как с помощью AI был создан полноценный инструмент, ориентированный на преподавателей, спикеров и всех, кто проводит презентации.
🔊 Продолжайте читать на Habr!
📣 Code Ready | #статьяjoin():
const users = [
'Alex',
'Maria',
'John'
];
users.join(', ');
Такой подход работает только для простого разделения элементов. Но он не знает правил конкретного языка. В английском между последними элементами используется and, в русском — и, а в других локалях могут быть свои правила форматирования.
Если приложение поддерживает несколько языков, обычно появляются ручные проверки:
if (locale === 'en') {
// добавить and
}
if (locale === 'ru') {
// добавить и
}
Поддерживать такую логику сложно, поэтому для подобных задач в JavaScript существует стандартный API Intl.ListFormat.
Создаём форматтер и передаём нужную локаль:
const formatter =
new Intl.ListFormat('ru');
formatter.format([
'JavaScript',
'TypeScript',
'Python'
]);
Результат: JavaScript, TypeScript и Python.
При изменении локали правила форматирования изменятся автоматически:
const formatter =
new Intl.ListFormat('en');
formatter.format([
'JavaScript',
'TypeScript',
'Python'
]);
Результат: JavaScript, TypeScript, and Python.
Intl.ListFormat использует встроенные правила локализации JavaScript, поэтому не нужно самостоятельно реализовывать союзы, разделители и особенности разных языков.
Кроме обычного перечисления можно форматировать варианты выбора. Например, когда пользователь выбирает один из способов оплаты:
const formatter =
new Intl.ListFormat(
'ru',
{
type: 'disjunction'
}
);
formatter.format([
'Карта',
'PayPal',
'Перевод'
]);
Результат: Карта, PayPal или Перевод.
По умолчанию используется conjunction — обычное перечисление через союз "и". Значение disjunction используется для альтернатив через "или".
Также важно понимать, что Intl.ListFormat не изменяет исходные данные. Он только создаёт новую строку:
const tags = [
'Frontend',
'Backend',
'DevOps'
];
const text =
new Intl.ListFormat('ru')
.format(tags);
Массив tags останется без изменений, что удобно при работе с состоянием приложения и неизменяемыми данными. В реальных проектах этот API полезен для отображения пользователей, тегов, фильтров, категорий и любых списков, которые должны выглядеть естественно для пользователей из разных стран.
🔥 Intl.ListFormat позволяет использовать стандартные правила локализации JavaScript вместо ручной сборки строк через join() и множества условий для разных языков.
📣 Code Ready | #практика