Array.prototype.some — простой метод, который часто недоиспользуют!
В JavaScript-коде до сих пор часто встречается ручной перебор с флагами,
Он отвечает на простой вопрос: есть ли в массиве хотя бы один элемент, который подходит под условие.
То же самое часто пишут через
Работает, но в большинстве случаев это лишнее состояние. Через
Пример с объектами:
Так удобно проверять наличие нужного состояния, флага или признака в коллекции.
Проверка ролей:
А если список разрешённых ролей уже вынесен отдельно, можно сделать так:
Валидация данных:
Как только найдено некорректное значение, дальнейший обход прекращается.
Отличие от
На пустом массиве:
Это ожидаемое поведение: в массиве нет ни одного элемента, который мог бы удовлетворить условию.
Важный момент — ранний выход:
В отличие от
Поэтому вместо такой цепочки:
часто лучше написать так:
Так массив не фильтруется заранее, не создаётся промежуточная коллекция, и проверка может завершиться раньше.
Альтернатива через
Так тоже пишут, но если нужен только boolean-ответ,
🔥
📣 JS Ready | #практика
В JavaScript-коде до сих пор часто встречается ручной перебор с флагами,
break и лишними переменными. Хотя для многих таких проверок уже есть готовый метод — some.Он отвечает на простой вопрос: есть ли в массиве хотя бы один элемент, который подходит под условие.
const arr = [1, 2, 3, 4];
const hasEven = arr.some(n => n % 2 === 0);
console.log(hasEven); // true
some проходит по массиву и возвращает true, как только предикат впервые вернул true. Если ни один элемент не подошёл — результат будет false.То же самое часто пишут через
for:let hasEven = false;
for (const n of arr) {
if (n % 2 === 0) {
hasEven = true;
break;
}
}
Работает, но в большинстве случаев это лишнее состояние. Через
some намерение видно сразу.Пример с объектами:
const users = [
{ id: 1, active: false },
{ id: 2, active: true }
];
const hasActive = users.some(user => user.active);
console.log(hasActive); // true
Так удобно проверять наличие нужного состояния, флага или признака в коллекции.
Проверка ролей:
const roles = ["user", "editor"];
const canEdit = roles.some(role => role === "admin" || role === "editor");
console.log(canEdit); // true
А если список разрешённых ролей уже вынесен отдельно, можно сделать так:
const allowedRoles = ["admin", "editor"];
const roles = ["user", "editor"];
const canEdit = roles.some(role => allowedRoles.includes(role));
Валидация данных:
const inputs = ["ok", "", "valid"];
const hasEmpty = inputs.some(value => value.trim() === "");
console.log(hasEmpty); // true
Как только найдено некорректное значение, дальнейший обход прекращается.
Отличие от
every:const arr = [2, 4, 6];
arr.some(n => n > 5); // true
arr.every(n => n > 5); // false
some — хотя бы один элемент; every — все элементы.На пустом массиве:
[].some(() => true); // false
Это ожидаемое поведение: в массиве нет ни одного элемента, который мог бы удовлетворить условию.
Важный момент — ранний выход:
arr.some(expensiveCheck);
В отличие от
map или filter, метод some не обязан проходить весь массив. Если условие уже выполнено, обход сразу прекращается. Это особенно полезно, если внутри предиката есть дорогая операция.Поэтому вместо такой цепочки:
const result = data
.filter(x => x.enabled)
.some(x => x.value > 100);
часто лучше написать так:
const result = data.some(x => x.enabled && x.value > 100);
Так массив не фильтруется заранее, не создаётся промежуточная коллекция, и проверка может завершиться раньше.
Альтернатива через
find:const exists = arr.find(x => x > 10) !== undefined;
Так тоже пишут, но если нужен только boolean-ответ,
some обычно точнее выражает намерение:const exists = arr.some(x => x > 10);
some — базовый инструмент для проверок. Когда нужно понять, есть ли в массиве хотя бы один подходящий элемент, он часто чище и понятнее ручных циклов с флагами.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
CSV to Table — позволяет отобразить содержимое CSV как таблицу прямо в VS Code. Данные выравниваются по столбцам, становятся наглядными и удобными для анализа без открытия сторонних инструментов. Полезно при работе с выгрузками, логами и любыми табличными данными.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🤝8❤7
Деструктуризация с rest как альтернатива slice!
Когда нужно взять первый элемент и всё остальное, обычно пишут через индексы и slice:
Получается лишний код и промежуточные переменные.
Деструктуризация решает это одной строкой:
Первый элемент забирается отдельно, остальные автоматически собираются в массив:
Работает с любыми массивами и результатами функций:
🔥 Часто используется в парсинге, работе со строками, аргументами функций и любом коде, где нужно разделить первое значение и остаток без лишней логики.
📣 JS Ready | #совет
Когда нужно взять первый элемент и всё остальное, обычно пишут через индексы и slice:
const parts = data.split(',');
const first = parts[0];
const rest = parts.slice(1);Получается лишний код и промежуточные переменные.
Деструктуризация решает это одной строкой:
const [first, ...rest] = data.split(',');Первый элемент забирается отдельно, остальные автоматически собираются в массив:
first // 'a'
rest // ['b', 'c']
Работает с любыми массивами и результатами функций:
const [head, ...tail] = arr;
Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍7🤝5🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
JS Challenger — сайт с короткими задачами по JavaScript — от простых до реально коварных. Отличный способ прокачаться без регистрации и лишнего UI.
📌 Оставляю ссылочку: jschallenger.com
📣 JS Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13🔥10🤝6❤3
Например, cookies используются для хранения данных на клиенте, sessions — для stateful-логики на сервере, JWT — для stateless-аутентификации, а PASETO — более безопасная альтернатива токенам.
На картинке — основные подходы: cookies, sessions, JWT и PASETO, их структура и базовые схемы работы.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥7🤝7❤3
Разбираем способ объединять отмену из нескольких источников!
Ситуация: есть
Когда условий больше одного, код часто начинает разрастаться: вручную прокидываются отмены, добавляются таймауты, появляется лишняя синхронизация. Это работает, но плохо масштабируется и легко ломается.
Нативное решение —
Мы просто описываем правило: отмени, если сработает любой из сигналов. Теперь операция отменится либо вручную через
Использование с
Если
Разбираем кейс — последний запрос побеждает + таймаут:
Что это даёт: старые запросы отменяются и текущий не висит бесконечно. Важно: в этом примере при отмене
Комбинация с lifecycle:
Ты не завязываешься на конкретный источник отмены — просто собираешь сигналы.
Причина берётся от первого сработавшего сигнала:
если
API относительно новый. В Node:
🔥 Как только появляется больше одного условия отмены —
📣 JS Ready | #практика
Ситуация: есть
async операция, и её нужно отменять по разным причинам: пользователь ушёл со страницы / компонент размонтировался, истёк таймаут, пришёл новый запрос.Когда условий больше одного, код часто начинает разрастаться: вручную прокидываются отмены, добавляются таймауты, появляется лишняя синхронизация. Это работает, но плохо масштабируется и легко ломается.
Нативное решение —
AbortSignal.any():const controller = new AbortController();
const signal = AbortSignal.any([
controller.signal,
AbortSignal.timeout(3000)
]);
Мы просто описываем правило: отмени, если сработает любой из сигналов. Теперь операция отменится либо вручную через
controller.abort(), либо по таймауту.Использование с
fetch:try {
const res = await fetch("/api/data", { signal });
const data = await res.json();
} catch (err) {
if (signal.aborted) {
// отмена: manual abort, timeout или другой источник
return;
}
throw err;
}
Если
reject не обработан — будет unhandled rejection. Поведение: если вызвать controller.abort() раньше таймаута — сработает он, если не вызывать — операция завершится по таймауту. Комбинированный сигнал абортится один раз — по первому событию.Разбираем кейс — последний запрос побеждает + таймаут:
let controller;
async function load() {
controller?.abort();
controller = new AbortController();
const signal = AbortSignal.any([
controller.signal,
AbortSignal.timeout(5000)
]);
try {
const res = await fetch("/api", { signal });
return res.json();
} catch (err) {
if (signal.aborted) return;
throw err;
}
}
Что это даёт: старые запросы отменяются и текущий не висит бесконечно. Важно: в этом примере при отмене
load() вернёт undefined, потому что мы явно делаем return в catch. Это нужно учитывать в вызывающем коде.Комбинация с lifecycle:
function load(signalFromUI) {
const signal = AbortSignal.any([
signalFromUI,
AbortSignal.timeout(3000)
]);
return fetch("/api", { signal });
}
Ты не завязываешься на конкретный источник отмены — просто собираешь сигналы.
AbortSignal.any() создаёт новый сигнал со своим lifecycle.Причина берётся от первого сработавшего сигнала:
const controller = new AbortController();
const signal = AbortSignal.any([
controller.signal,
AbortSignal.timeout(3000)
]);
controller.abort("manual");
console.log(signal.reason); // "manual"
если
abort() без аргумента, то обычно будет AbortError, если сработал AbortSignal.timeout() — будет TimeoutError, если abort("manual") — reason будет "manual".API относительно новый. В Node:
AbortSignal.timeout() есть с Node 16.14.0 / 17.3.0; AbortSignal.any() есть с Node 18.17.0 / 20.3.0AbortSignal.any() упрощает код и убирает ручную синхронизацию.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤7🔥7
This media is not supported in your browser
VIEW IN TELEGRAM
ESLint — это не просто подсветка ошибок, а инструмент анализа кода. Он находит потенциальные баги, антипаттерны и несоответствие правилам проекта, а также умеет автоматически исправлять часть проблем. Работает через конфиги и плагины (React, Next.js и др.), помогает держать код единообразным.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤6🤝6
Почему объекты не равны и как их сравнить без библиотек?
В JavaScript объекты сравниваются по ссылке, а не по содержимому.
Даже если структура полностью совпадает — это разные объекты.
Для простых данных можно использовать JSON.stringify.
Но важно понимать ограничения:
Также не работает с undefined, функциями, Symbol и BigInt.
🔥 Приём для тестов, простых кешей и сравнений JSON-данных.
📣 JS Ready | #совет
В JavaScript объекты сравниваются по ссылке, а не по содержимому.
{ x: 1 } === { x: 1 } // falseДаже если структура полностью совпадает — это разные объекты.
Для простых данных можно использовать JSON.stringify.
JSON.stringify(a) === JSON.stringify(b) // true
Но важно понимать ограничения:
JSON.stringify({ a: 1, b: 2 }) === JSON.stringify({ b: 2, a: 1 })
// false (порядок ключей важен)Также не работает с undefined, функциями, Symbol и BigInt.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤8🔥7
Например, TTFB показывает, как быстро сервер начинает отвечать, а FCP помогает понять, когда пользователь впервые видит контент на экране.
На картинке — 9 основных метрик производительности сайта, которые полезно держать под рукой каждому разработчику.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
❤9👍6🤝5
Proxy — перехватываем изменения объекта!
Proxy — одна из возможностей JS, про которую многие знают только поверхностно. На практике он позволяет перехватывать чтение, запись, удаление и даже вызовы функций, превращая обычный объект в управляемую структуру данных.
Создадим объект и обернём его в Proxy:
Теперь любое изменение объекта можно контролировать централизованно.
Перехватываем запись значений:
Пробуем изменить объект:
Даже новые свойства автоматически проходят через обработчик.
Через Proxy удобно валидировать данные до записи:
Теперь объект сам защищает свои данные от невалидных значений.
Завершаем логику и тестируем:
Такой подход часто используют в системах реактивности, конфиг-движках, ORM и инструментах разработки, где важно централизованно контролировать изменения данных.
🔥 Proxy позволяет буквально вклиниться между кодом и объектом, превращая обычные структуры данных в управляемые и расширяемые механизмы с собственной логикой поведения.
📣 JS Ready | #практика
Proxy — одна из возможностей JS, про которую многие знают только поверхностно. На практике он позволяет перехватывать чтение, запись, удаление и даже вызовы функций, превращая обычный объект в управляемую структуру данных.
Создадим объект и обернём его в Proxy:
const user = { name: "Alex" };
const proxy = new Proxy(user, {
set(target, key, value) {Теперь любое изменение объекта можно контролировать централизованно.
Перехватываем запись значений:
console.log(` ${key} = ${value}`);
target[key] = value;
return true; }}
);set вызывается каждый раз при изменении свойства — это основа реактивности во многих frontend-фреймворках.Пробуем изменить объект:
proxy.name = "John";
proxy.age = 30;
// name = John
// age = 30
Даже новые свойства автоматически проходят через обработчик.
Через Proxy удобно валидировать данные до записи:
const settings = new Proxy({}, {
set(obj, key, value) {
if (key === "port" && value > 65535)
throw Error("Некорректный порт");Теперь объект сам защищает свои данные от невалидных значений.
Завершаем логику и тестируем:
obj[key] = value;
return true;
}
});
settings.port = 3000;
Такой подход часто используют в системах реактивности, конфиг-движках, ORM и инструментах разработки, где важно централизованно контролировать изменения данных.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤4👍4
This media is not supported in your browser
VIEW IN TELEGRAM
На сайте собраны не только шпаргалки, но и полноценные статьи с разбором разных тем: работа с массивами и объектами, функции, замыкания, методы JS и практические нюансы разработки. Материал подаётся с примерами кода и краткими пояснениями.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15👍7🤝6
Разбираем как не словить утечку памяти на обработчиках событий!
Одна из частых причин утечек — обработчик повесили, а снять забыли. Особенно это неприятно, когда событие висит не на локальном элементе, а на чём-то долгоживущем:
Компонента уже нет, а
Правильнее сразу закладывать
Главное — снимать нужно ту же самую функцию.
Вот так не сработает:
Это две разные функции, даже если выглядят одинаково.
Нормальный вариант:
Ещё момент —
Так обработчик не снимется, потому что
Когда обработчиков несколько, удобно использовать
А если обработчик нужен только один раз:
После первого вызова он удалится сам. Важный нюанс: удалённый DOM сам по себе ещё не утечка. Если на него нет внешних ссылок — GC его заберёт.
🔥 Проблемы начинаются, когда: обработчик висит на
📣 JS Ready | #практика
Одна из частых причин утечек — обработчик повесили, а снять забыли. Особенно это неприятно, когда событие висит не на локальном элементе, а на чём-то долгоживущем:
window, document, глобальный event bus и т.п.
function mount() {
window.addEventListener('resize', onResize);
}
function unmount() {
// забыли снять обработчик
}
Компонента уже нет, а
onResize всё ещё вызывается. Плюс callback может держать в замыкании старое состояние, DOM-ноды, данные — и GC не сможет это нормально прибрать.Правильнее сразу закладывать
cleanup:
function mount() {
window.addEventListener('resize', onResize);
}
function unmount() {
window.removeEventListener('resize', onResize);
}
Главное — снимать нужно ту же самую функцию.
Вот так не сработает:
el.addEventListener('click', () => doSomething());
el.removeEventListener('click', () => doSomething());
Это две разные функции, даже если выглядят одинаково.
Нормальный вариант:
function handler() {
doSomething();
}
el.addEventListener('click', handler);
el.removeEventListener('click', handler);
Ещё момент —
capture.
el.addEventListener('click', handler, true);
el.removeEventListener('click', handler, false);
Так обработчик не снимется, потому что
capture отличается. Для удаления браузер сравнивает type, listener и capture.passive, once, signal в этом сравнении не участвуют.Когда обработчиков несколько, удобно использовать
AbortController:
const controller = new AbortController();
window.addEventListener('resize', onResize, {
signal: controller.signal
});
document.addEventListener('visibilitychange', onVisible, {
signal: controller.signal
});
// cleanup
controller.abort();
abort() снимет все обработчики, которые были добавлены с этим signal.А если обработчик нужен только один раз:
button.addEventListener('click', handler, { once: true });
После первого вызова он удалится сам. Важный нюанс: удалённый DOM сам по себе ещё не утечка. Если на него нет внешних ссылок — GC его заберёт.
window / document; callback держит старое состояние в замыкании; DOM-нода или данные лежат в массиве, store или кэше.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤8🔥6
This media is not supported in your browser
VIEW IN TELEGRAM
Colorize — подсвечивает все цветовые значения прямо в редакторе: HEX, RGB, HSL, CSS-переменные и другие форматы. Вместо набора символов ты сразу видишь реальный цвет рядом с кодом. Удобно при работе с UI, темами и большими CSS/SCSS-файлами, где важно быстро ориентироваться в палитре проекта.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10👍10🤝7
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤6👍6
Например, REST отлично подходит для простых CRUD API, GraphQL позволяет получать только нужные данные одним запросом, а gRPC обеспечивает максимально быстрое взаимодействие между микросервисами через HTTP/2 и Protobuf.
На картинке — основные отличия REST, GraphQL и gRPC: принципы работы, структура запросов, особенности передачи данных и сценарии использования.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍6🤝4❤1
Почему await внутри forEach не работает как ожидается?
Многие думают, что
Из-за этого легко получить гонки, неожиданный порядок выполнения и баги.
Правильный способ —
Теперь каждая операция действительно ждёт предыдущую.
Если нужна параллельность — используйте
🔥 Это одна из самых частых async-ловушек в JavaScript. Особенно полезно в API, очередях задач, миграциях и любом коде, где важен контроль выполнения.
📣 JS Ready | #совет
Многие думают, что
await внутри forEach остановит выполнение цикла. Но forEach не работает с Promise и не ждёт завершения callback.console.log('done'); // выполнится раньше запросовИз-за этого легко получить гонки, неожиданный порядок выполнения и баги.
Правильный способ —
for...of.for (const id of ids) {
await fetch(`/user/${id}`);
}Теперь каждая операция действительно ждёт предыдущую.
Если нужна параллельность — используйте
Promise.all.await Promise.all(
ids.map(id => fetch(`/user/${id}`))
);
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍6🤝5❤1
Please open Telegram to view this post
VIEW IN TELEGRAM
👍17❤6🔥5