This media is not supported in your browser
VIEW IN TELEGRAM
Это полноценный справочник с чёткими объяснениями, примерами кода и интерактивными демо. Каждая тема сопровождается примерами, которые можно сразу попробовать и понять, как именно работает та или иная конструкция. Очень полезно и новичкам, и тем, кто хочет освежить знания или быстро найти пример по конкретной задаче.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤10🔥9
Пишем консольную мини-игру «Быки и коровы»!
Для тех, кто не знает или забыл правила: игрок угадывает 4-значное число без повторов. Бык - цифра угадана и стоит на своём месте. Корова - цифра есть в числе, но позиция неверная.
Подключаем консольный ввод и генерируем секретное число: 4 разные цифры в случайном порядке:
Здесь важно, что число создаётся один раз и не меняется до конца игры.
Главная часть игры: сравниваем ввод игрока с секретом и считаем совпадения.
Если цифра совпала по индексу - это бык, если просто присутствует - корова.
Каждый ход - это запрос числа, валидация и подсчёт результата:
Принимаем только корректный ввод, ровно 4 цифры, иначе ход повторяется.
Если все цифры угаданы на своих местах, игра заканчивается, иначе показываем подсказку:
Финал и точка входа максимально простые:
🔥 Эта игра помогает попрактиковать работу с состоянием, пользовательским вводом и управлением асинхронным потоком
📣 JS Ready | #практика
Для тех, кто не знает или забыл правила: игрок угадывает 4-значное число без повторов. Бык - цифра угадана и стоит на своём месте. Корова - цифра есть в числе, но позиция неверная.
Подключаем консольный ввод и генерируем секретное число: 4 разные цифры в случайном порядке:
const rl = require("readline").createInterface({
input: process.stdin, output: process.stdout
});
const secret = [...new Set(
Array.from({ length: 10 }, (_, i) => i)
)].sort(() => 0.5 - Math.random()).slice(0, 4).join("");Здесь важно, что число создаётся один раз и не меняется до конца игры.
Главная часть игры: сравниваем ввод игрока с секретом и считаем совпадения.
const score = g => {
let b = 0, c = 0;
for (let i = 0; i < 4; i++)
secret[i] === g[i] ? b++ : secret.includes(g[i]) && c++;
return [b, c];
};Если цифра совпала по индексу - это бык, если просто присутствует - корова.
Каждый ход - это запрос числа, валидация и подсчёт результата:
const turn = () => rl.question("Число: ", g => {
if (!/^\d{4}$/.test(g)) return turn();
const [b, c] = score(g);Принимаем только корректный ввод, ровно 4 цифры, иначе ход повторяется.
Если все цифры угаданы на своих местах, игра заканчивается, иначе показываем подсказку:
if (b === 4) return win();
console.log(`🐂 ${b} | 🐄 ${c}`);
turn();
});
Финал и точка входа максимально простые:
const win = () => {
console.log(`🏆 Победа! Было: ${secret}`);
rl.close();
};
turn();Please open Telegram to view this post
VIEW IN TELEGRAM
❤12👍9🔥8
This media is not supported in your browser
VIEW IN TELEGRAM
Это необычное руководство по JS, построенное так, чтобы его было легко читать и понимать. Материал объясняет базовые концепции языка простым языком, с примерами и объяснениями. Ресурс подойдёт для знакомства с синтаксисом или для повторения основ без излишне сложной теории.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14❤10👍8
Дополнительные функции обратного вызова!
Иногда функция должна быть универсальной и вызывать колбэк только если он передан, при этом не увеличивая код проверками:
В JS это делается напрямую через optional chaining, без условий и лишней логики:
Если колбэк не передан, код просто пропускается, если передан — вызывается как обычная функция:
🔥 Такой приём позволяет проектировать API с опциональным поведением без перегрузок функций и условий.
📣 JS Ready | #совет
Иногда функция должна быть универсальной и вызывать колбэк только если он передан, при этом не увеличивая код проверками:
if (callback) {
callback(data);
}В JS это делается напрямую через optional chaining, без условий и лишней логики:
callback?.(data);
Если колбэк не передан, код просто пропускается, если передан — вызывается как обычная функция:
fetchData('/api/user');
fetchData('/api/user', data => console.log(data));Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤9🤝8
This media is not supported in your browser
VIEW IN TELEGRAM
Markdown Preview Enhanced — расширяет стандартный предпросмотр Markdown в VS Code. Поддерживает диаграммы, формулы, графики, Mermaid, подсветку кода, экспорт в PDF и HTML. Сразу видишь, как будет выглядеть README, документация или статья, без внешних инструментов и лишних шагов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤6🤝5
Реализуем древовидную структуру, моделирующую файловую систему, и напишем универсальный механизм поиска по этому дереву.
В этой задаче:
• Работаем с вложенными объектами как с деревом;
• Реализуем рекурсивный обход;
• Строим чистую функцию поиска без глобального состояния;
• Разделяем механизм обхода и критерий фильтрации.
Это разбор базового паттерна обхода структур, который лежит в основе множества реальных инструментов.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍9🔥8🤝1
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь по шагам объясняют, как создаются html-страницы, как работают теги, формы, таблицы, семантика. А также как оформлять всё это с помощью CSS: селекторы, цвета, layout, Flexbox, Grid и адаптивный дизайн. Материалы поданы простым языком и с примерами, удобно для новичков и тех, кто хочет повторить базу.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14🔥9👍7
Простой поиск по массиву объектов с поддержкой нескольких полей!
Частая задача в интерфейсах — быстрый клиентский поиск: таблицы, списки пользователей, товары. Ниже — универсальная функция фильтрации без библиотек для substring-поиска по нескольким полям.
Допустим, есть массив:
Требование: регистронезависимый поиск по
Функция поиска:
Использование:
Поиск работает через
Если пользователь вводит несколько слов, часто логично требовать совпадение каждого, но разрешать нахождение слов в разных полях:
Здесь:
alex совпадает в
🔥 Для списков до нескольких тысяч элементов обычно достаточно без сторонних библиотек. Если данных больше или поиск вызывается очень часто — имеет смысл кэшировать нормализованные значения или строить индекс.
📣 JS Ready | #практика
Частая задача в интерфейсах — быстрый клиентский поиск: таблицы, списки пользователей, товары. Ниже — универсальная функция фильтрации без библиотек для substring-поиска по нескольким полям.
Допустим, есть массив:
const users = [
{ id: 1, name: "Alex Ivanov", email: "alex@mail.com" },
{ id: 2, name: "Maria Petrova", email: "maria@mail.com" },
{ id: 3, name: "John Smith", email: "john@mail.com" }
];
Требование: регистронезависимый поиск по
name и email с частичным совпадением.Функция поиска:
function normalize(value) {
return String(value ?? "")
.toLowerCase()
// Удаление диакритики (если это нужно в проекте)
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "");
}
function search(items, query, fields) {
const q = normalize(query).trim();
if (!q) return items;
return items.filter(item =>
fields.some(field => normalize(item[field]).includes(q))
);
}normalize делает безопасное приведение к строке, единый регистр и (опционально) удаление диакритики. trim() исключает пустые запросы, some реализует OR по полям.Использование:
console.log(search(users, "alex", ["name", "email"]));
// [{ id: 1, name: "Alex Ivanov", ... }]
console.log(search(users, "mail.com", ["name", "email"]));
// все пользователи
Поиск работает через
includes, поэтому это именно substring-поиск: частичные совпадения, простое поведение.Если пользователь вводит несколько слов, часто логично требовать совпадение каждого, но разрешать нахождение слов в разных полях:
function searchMulti(items, query, fields) {
const tokens = normalize(query)
.trim()
.split(/\s+/)
.filter(Boolean);
if (!tokens.length) return items;
return items.filter(item =>
tokens.every(token =>
fields.some(field => normalize(item[field]).includes(token))
)
);
}Здесь:
every задаёт AND по словам запроса, some сохраняет OR по полям.searchMulti(users, "alex mail", ["name", "email"]);
alex совпадает в
name, mail — в email, поэтому объект будет найден.Please open Telegram to view this post
VIEW IN TELEGRAM
🤝10👍9🔥9❤3
This media is not supported in your browser
VIEW IN TELEGRAM
Faker — позволяет легко вставлять случайные имена, адреса, номера телефонов, даты и другие данные прямо в ваш код.
Очень удобно при разработке и тестировании, особенно если нужно наполнить макеты реалистичными значениями.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍12🤝7❤1
FormData — нативная работа с данными форм и файлами!
Создание
В
Пример 1 — чтение значений:
Пример 2 — несколько значений одного поля:
Актуально для: checkbox-групп;
Пример 3 — добавление и изменение данных:
Пример 4 — работа с файлами:
Файл передаётся как File (подтип
Пример 5 — отправка через
Не нужно вручную задавать Content-Type, браузер автоматически установит
Пример 6 — перебор всех данных:
🔥
📣 JS Ready | #практика
FormData — базовый Web API для сбора и отправки данных HTML-форм. Позволяет работать с текстовыми полями и файлами без ручной сериализации и напрямую передаётся в fetch или XMLHttpRequest.Создание
FormData из формы:const form = document.querySelector('form');
const formData = new FormData(form);В
FormData попадают только successful controls: элементы с name и без disabled, checked checkbox/radio, выбранные файлы и submit-кнопка при реальном submit; без name — не попадают.Пример 1 — чтение значений:
formData.get('email');
formData.get('password');get() возвращает первое значение по ключу. Для полей с несколькими значениями используется getAll().Пример 2 — несколько значений одного поля:
formData.getAll('tags');Актуально для: checkbox-групп;
<select multiple>; динамических списков (повторяющиеся ключи).Пример 3 — добавление и изменение данных:
formData.set('role', 'admin');
formData.append('token', 'abc123');set() удаляет все предыдущие значения по ключу и устанавливает новое; append() добавляет ещё одно значение (важно для повторяющихся ключей и файлов)Пример 4 — работа с файлами:
const fileInput = document.querySelector('input[type="file"]');
if (fileInput.files.length > 0) {
formData.append('avatar', fileInput.files[0]);
}Файл передаётся как File (подтип
Blob) с именем, MIME-типом и размером. При выборе нескольких файлов (multiple) FormData содержит несколько записей с одинаковым ключом.Пример 5 — отправка через
fetchfetch('/api/profile', {
method: 'POST',
body: formData
});Не нужно вручную задавать Content-Type, браузер автоматически установит
multipart/form-data с корректным boundary.Пример 6 — перебор всех данных:
for (const [key, value] of formData.entries()) {
console.log(key, value);
}FormData — стандартный и часто незаменимый инструмент для веб-приложений с формами, файлами и реальными пользовательскими данными.Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤9🤝8🔥1
Например,
charAt() возвращает символ по индексу, includes() проверяет наличие подстроки, а slice() извлекает часть строки без изменения оригинала.На картинке — часто используемые методы для работы со строками: поиск, сравнение, замена, разбиение, изменение регистра и форматирование.
Сохрани, чтобы не забыть!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍12🤝8
NodeList — это не массив, но его легко им сделать!
Spread-оператор делает то же самое короче и читаемее:
После этого можно использовать весь арсенал массивов без ограничений:
🔥 Это один из самых частых реальных кейсов в DOM-коде, особенно при обработке списков, таблиц и UI-компонентов. Превращает псевдомассив в полноценный массив.
📣 JS Ready | #совет
querySelectorAll возвращает NodeList, у которого нет map, filter и других методов массива. Раньше приходилось писать через Array.from:const items = Array.from(document.querySelectorAll('.item'));Spread-оператор делает то же самое короче и читаемее:
const items = [...document.querySelectorAll('.item')];После этого можно использовать весь арсенал массивов без ограничений:
const visible = items.filter(el => el.offsetParent !== null);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤7🔥5🤝3
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥10❤9
Дедупликация массива объектов по ключу!
При работе с API, кэшем, пагинацией или объединении данных дубликаты появляются постоянно. Почти всегда нужно оставить только один объект для каждого уникального значения поля (чаще всего id).
Допустим, есть массив пользователей:
Задача: оставить только по одному объекту для каждого id.
По сути мы строим индекс: если ключ встретился впервые — сохраняем объект, если повторно — игнорируем. В результате остаются первые версии элементов:
Такой вариант особенно полезен, когда порядок данных важен и нужно сохранить именно первый пришедший объект.
Если важен последний дубликат (например, пришло обновление), достаточно перезаписывать значение в Map — сохранится последняя версия объекта:
Теперь при повторном ключе старый объект заменяется новым, и в итоге остаются последние версии:
Это часто используется при мердже страниц пагинации или обновлений из веб-сокета.
Если уникальность задаётся не полем, а вычислением (например, комбинацией значений), можно передать функцию получения ключа:
Например, можно убрать дубликаты по имени без учёта регистра:
🔥 Небольшой нюанс: если у части объектов нет нужного поля, они получат ключ undefined и схлопнутся в один элемент. Иногда это ожидаемо, иногда — источник багов, поэтому стоит учитывать.
📣 JS Ready | #практика
При работе с API, кэшем, пагинацией или объединении данных дубликаты появляются постоянно. Почти всегда нужно оставить только один объект для каждого уникального значения поля (чаще всего id).
Допустим, есть массив пользователей:
const users = [
{ id: 1, name: "Alex" },
{ id: 2, name: "Maria" },
{ id: 1, name: "Alex (duplicate)" },
{ id: 3, name: "John" },
{ id: 2, name: "Maria (duplicate)" }
];
Задача: оставить только по одному объекту для каждого id.
Map удобен для дедупа: ключи не кастуются к строке, доступ работает за O(1), весь алгоритм — один проход O(n), а реализация остаётся простой и читаемой:const uniqueBy = (items, key) => {
const map = new Map();
for (const item of items) {
const k = item[key];
if (!map.has(k)) map.set(k, item);
}
return [...map.values()];
};По сути мы строим индекс: если ключ встретился впервые — сохраняем объект, если повторно — игнорируем. В результате остаются первые версии элементов:
uniqueBy(users, "id");
/*
[
{ id: 1, name: "Alex" },
{ id: 2, name: "Maria" },
{ id: 3, name: "John" }
]
*/
Такой вариант особенно полезен, когда порядок данных важен и нужно сохранить именно первый пришедший объект.
Если важен последний дубликат (например, пришло обновление), достаточно перезаписывать значение в Map — сохранится последняя версия объекта:
const uniqueByLast = (items, key) => {
const map = new Map();
for (const item of items) map.set(item[key], item);
return [...map.values()];
};Теперь при повторном ключе старый объект заменяется новым, и в итоге остаются последние версии:
uniqueByLast(users, "id");
/*
[
{ id: 1, name: "Alex (duplicate)" },
{ id: 2, name: "Maria (duplicate)" },
{ id: 3, name: "John" }
]
*/
Это часто используется при мердже страниц пагинации или обновлений из веб-сокета.
Если уникальность задаётся не полем, а вычислением (например, комбинацией значений), можно передать функцию получения ключа:
const uniqueByFn = (items, getKey) => {
const map = new Map();
for (const item of items) {
const k = getKey(item);
if (!map.has(k)) map.set(k, item);
}
return [...map.values()];
};Например, можно убрать дубликаты по имени без учёта регистра:
uniqueByFn(users, u => u.name.toLowerCase());
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍9🔥8
🤝15🔥12👍10😁1
Деструктуризация параметров в Callback!
Когда в колбэк приходит объект, не обязательно сначала принимать его целиком, а потом вытаскивать поля:
Можно сразу распаковать нужные свойства в параметрах функции:
Это делает код короче и сразу показывает, какие данные используются внутри колбэка.
🔥 Особенно полезно в
📣 JS Ready | #совет
Когда в колбэк приходит объект, не обязательно сначала принимать его целиком, а потом вытаскивать поля:
users.forEach(user => {
console.log(user.id, user.name);
});Можно сразу распаковать нужные свойства в параметрах функции:
users.forEach(({ id, name }) => {
console.log(id, name);
});Это делает код короче и сразу показывает, какие данные используются внутри колбэка.
map, filter, reduce, обработчиках событий и работе с API-данными.Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤9🔥8🤝2👎1