JavaScript Ready | Программирование
8.17K subscribers
832 photos
48 videos
370 links
Авторский канал по разработке на JavaScript.
Ресурсы, обучения, задачи, шпаргалки.
Ежедневно информация пополняется!

Автор: @energy_it

Реклама на бирже:
https://telega.in/c/javascript_readyy
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Нужно запустить тесты в редакторе?

Jest — расширение для VS Code, которое показывает статус тестов рядом с кодом и позволяет запускать их по одному клику: весь файл, отдельный тест или даже конкретный кейс. Подсветка тестов и быстрый переход к проблемному месту.

📣 JS Ready | #vscode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🔥109
Дедупликация массива объектов по ключу!

При работе с 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());


🔥 Небольшой нюанс: если у части объектов нет нужного поля, они получат ключ undefined и схлопнутся в один элемент. Иногда это ожидаемо, иногда — источник багов, поэтому стоит учитывать.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
10👍9🔥8
Что же выведет консоль?
Anonymous Quiz
13%
A
23%
B
41%
C
23%
D
🤝15🔥12👍10😁1
Деструктуризация параметров в Callback!

Когда в колбэк приходит объект, не обязательно сначала принимать его целиком, а потом вытаскивать поля:
users.forEach(user => {
console.log(user.id, user.name);
});


Можно сразу распаковать нужные свойства в параметрах функции:
users.forEach(({ id, name }) => {
console.log(id, name);
});


Это делает код короче и сразу показывает, какие данные используются внутри колбэка.

🔥 Особенно полезно в map, filter, reduce, обработчиках событий и работе с API-данными.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍209🔥8🤝2👎1
This media is not supported in your browser
VIEW IN TELEGRAM
😎 JS Basic Tasks — практический задачник по JavaScript и DOM!

Репозиторий содержит набор заданий и учебный проект по работе с JavaScript, интерфейсами и браузерным API. Здесь последовательная практика: манипуляции с DOM, события, формы, работа с данными и построение интерактивных элементов. Отличный вариант, если хочешь попрактиковаться.

Оставляю ссылочку: GitHub 📱


📣 JS Ready | #репозиторий
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥18👍9🤝8
Делаем undo / redo для состояния через стек!

Отмена и повтор действий — частый интерактивный сценарий: формы, редакторы, фильтры, админки. Реализуется через два стека: past и future.

Создаём простое состояние и кнопку изменения:
const output = document.createElement("div");
const btn = document.createElement("button");
btn.textContent = "Изменить";


Добавляем элементы на страницу, чтобы можно было взаимодействовать с интерфейсом и видеть результат изменений:
document.body.append(btn, output);


Создаём состояние приложения — в примере это простой счётчик — и сразу отображаем его текущее значение:
let state = { count: 0 };
output.textContent = state.count;


Добавляем историю состояний. Будем хранить прошлые состояния в past, а состояния для возможного повтора — в future.
const past = [];
const future = [];


Функция изменения состояния. Перед каждым обновлением сохраняем текущий state в историю, затем применяем новое значение и очищаем redo-историю, потому что она больше не актуальна:
function setState(next) {
past.push(structuredClone(state));
state = structuredClone(next); // чтобы избежать мутаций по ссылке
future.length = 0;
output.textContent = state.count;
}


Изменение состояния по кнопке — просто увеличиваем счётчик на единицу:
btn.addEventListener("click", () => {
setState({ count: state.count + 1 });
});


Undo — возвращает предыдущее состояние. Текущее состояние при этом переносится в future, чтобы его можно было восстановить обратно:
function undo() {
if (!past.length) return;
future.push(structuredClone(state));
state = past.pop();
output.textContent = state.count;
}


Redo — восстанавливает состояние из стека future и делает его текущим:
function redo() {
if (!future.length) return;
past.push(structuredClone(state));
state = future.pop();
output.textContent = state.count;
}


Основные моменты: past хранит прошлые состояния, future очищается при новом изменении, structuredClone делает глубокую копию без общих ссылок, подход масштабируется (diff, лимит истории, отдельный менеджер).

🔥 В итоге получаем полноценный undo/redo-механизм на чистом JavaScript без сторонних библиотек.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍8🤝8
📂 Шпаргалка по методам поиска в строках!

Например, startsWith(), endsWith() и includes() используются для логических проверок содержимого строки, а indexOf() и lastIndexOf() — для получения позиции первого и последнего вхождения подстроки.

На изображении собраны базовые методы строкового поиска, которые покрывают большинство повседневных задач при работе с текстом и данными.

Сохраните, чтобы не забыть!

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥107🤝2
Значение по умолчанию при деструктуризации!

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

Без дефолтов придётся страховаться вручную:
function printUser(user) {
const name = user.name || "Unknown";
const age = user.age || 0;

console.log(name, age);
}


Проблема в том, что оператор || подменяет любые falsy-значения — пустую строку, 0 или false, даже если они валидны.

Корректнее задать значения по умолчанию прямо в параметрах функции. Они применяются только если свойство равно undefined:
function printUser({ name = "Unknown", age = 0 }) {
console.log(name, age);
}


Теперь передача неполных данных не ломает логику:
printUser({ name: "Alex" }); // Alex 0
printUser({ age: 25 }); // Unknown 25
printUser({}); // Unknown 0


Частый кейс — безопасная обработка параметров опционального объекта. Чтобы функция не падала при вызове без аргументов, задаём дефолт всему параметру:
function createUser({ name = "Guest", role = "user" } = {}) {
return { name, role };
}


Теперь корректны все варианты вызова:
createUser({ name: "Mira" });
createUser({});
createUser();


Подход делает сигнатуру функции самодокументируемой и избавляет от защитного кода внутри тела.

🔥 Особенно полезно в API-обёртках, утилитах, React-компонентах и обработчиках конфигурации.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍189🤝8
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Не хочется каждый раз писать базовую структуру вручную?

Simple React Snippets — добавляет быстрые шаблоны для React: функциональные компоненты, импорт React, хуки, export по умолчанию и другие часто используемые конструкции. Вводишь короткое сокращение, получаешь готовый каркас компонента.

📣 JS Ready | #vscode
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥20👍149👎1
Сглаживание массивов без reduce и рекурсии!

Когда массив содержит вложенные массивы, можно не писать сложные циклы или рекурсивные функции — flat делает это проще:
nested.flat(2); // сглаживает на глубину 2


Если нужно полностью полностью развернуть вложенную структуру любой глубины, можно указать Infinity:
nested.flat(Infinity);


Когда требуется не просто сгладить, а сначала преобразовать элементы, используйте flatMap — он объединяет map и flat(1) в одну операцию:
[1, 2, 3].flatMap(x => [x, x * 2]);


🔥 Такой примем пригодится для обработки результатов API, древовидных структур, списков и любых вложенных данных.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1411👍10
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ Teamtreehouse — базовый курс по основам языка JS!

Структурированная программа обучения, охватывающая ключевые концепции языка: синтаксис, условные конструкции, функции и основы отладки. Материал подаётся через видеоуроки и задания, что позволяет закреплять теорию на практике и формировать базу для дальнейшего изучения веб-разработки.

📌 Оставляю ссылочку: teamtreehouse.com

📣 JS Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍10🔥9🤝1
📱 Числа: преобразование, проверки и парсинг!

В шпаргалке собраны основные способы работы с числовыми значениями. Рассматриваются явное приведение типов, строгие проверки корректности и конечности чисел, а также разбор строковых представлений целых и дробных значений. Материал охватывает примеры валидации, безопасной работы с целыми числами и корректного извлечения чисел из строк.

📣 JS Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1410🔥10
Как убрать undefined / null поля из объекта?

Частая проблема, в объекте есть пустые поля, которые ломают API-запросы, формы или сериализацию.

Получаем пары ключ-значение:
Object.entries(obj)


Фильтруем только реальные значения, убирая null и undefined:
.filter(([, v]) => v != null)


Собираем обратно в объект:
Object.fromEntries(...)


🔥 Идеально перед fetch, сохранением настроек, формами и любыми динамическими параметрами, очищает данные без циклов и мутаций.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍159🤝9
📱 Напоминалка по работе с массивами!

Например методы map(), filter(), find() и другие — это быстрый способ трансформировать, искать и фильтровать данные в массивах.

На картинке — 7 ключевых методов массивов.

Сохрани, чтобы не забыть!

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2112🤝9
event.target и event.currentTarget — правильная работа с делегированием!

В обработчиках событий часто путают два разных элемента: тот, по которому пользователь действительно кликнул, и тот, на котором висит слушатель. В DOM это разные роли, и для них существуют свойства event.target и event.currentTarget.

event.target — источник события (самый глубокий элемент):
list.addEventListener("click", e => {
console.log("target:", e.target);
});


Если кликнуть по кнопке внутри списка, target будет тем узлом, по которому пришёлся клик. Если внутри кнопки есть вложенные элементы, target может оказаться ими, а не самой кнопкой.

event.currentTarget — элемент, на котором висит обработчик:
list.addEventListener("click", e => {
console.log("currentTarget:", e.currentTarget);
});


Он всегда равен list, потому что обработчик привязан именно к этому элементу, независимо от места клика внутри него.

Практический пример делегирования:
document
.querySelector("#menu")
.addEventListener("click", e => {
if (e.target.matches("button")) {
console.log("Нажата кнопка:", e.target.textContent);
}
});


Если внутри кнопки есть вложенные элементы, условие может не сработать, потому что target будет не кнопкой.

Надёжнее использовать closest():
document
.querySelector("#menu")
.addEventListener("click", e => {
const btn = e.target.closest("button");
if (!btn || !e.currentTarget.contains(btn)) return;
console.log("Нажата кнопка:", btn.textContent);
});


Проверка contains гарантирует, что найденная кнопка действительно находится внутри текущего контейнера.

Когда нужен именно контейнер — используем currentTarget:
container.addEventListener("click", e => {
e.currentTarget.classList.toggle("active");
});


Класс изменится у контейнера, даже если клик был по вложенному элементу.

🔥 Понимание различия особенно важно при делегировании событий и работе с динамическим DOM. Основа надёжной обработки событий без навешивания обработчиков на каждый элемент.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
13👍9🔥8
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Нужно быстро понять, когда и как менялся код?

Git History — показывает историю изменений прямо в VS Code: коммиты по файлу, авторов правок, различия между версиями и изменения строк. Можно быстро посмотреть старый код, найти причину бага или понять логику изменений.

📣 JS Ready | #vscode
Please open Telegram to view this post
VIEW IN TELEGRAM
14🔥8🤝8