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

Автор: @energy_it

Реклама на бирже:
https://telega.in/c/javascript_readyy
Download Telegram
Как легко писать функции с любым количеством аргументов?

Бывает, заранее неизвестно, сколько аргументов придёт в функцию. Некоторые используют arguments, но у него есть минусы: это не массив, нет методов, и ведёт себя неочевидно.

Более современный и правильный способ — rest parameter (...args):
function sum(...args) {
return args.reduce((total, n) => total + n, 0);
}


Все аргументы автоматически собираются в массив args, с ним можно работать как с обычным массивом — map, filter, reduce
sum(1, 2, 3, 4); // 10


Важно не путать rest и spread:
rest — собирает аргументы внутри функции;
spread — разворачивает массив при вызове;
sum(...[1, 2, 3, 4]);


🔥 Rest parameter удобен тем, что аргументы сразу ведут себя как массив, без дополнительных шагов.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍9🤝81
Throttle — контроль частоты выполнения!

В браузере есть события, которые срабатывают десятки и сотни раз в секунду: scroll, mousemove, resize. Если выполнять логику на каждый вызов, это быстро приводит к просадкам FPS, дёрганому UI и лишним вычислениям.

Throttle позволяет задать верхний предел частоты выполнения обработчика.

Базовая реализация throttle (leading-only):
function throttle(fn, delay = 300) {
let last = 0;

return (...args) => {
const now = Date.now();
if (now - last >= delay) {
last = now;
fn(...args);
}
};
}


Функция будет вызываться не чаще одного раза за delay миллисекунд.
Важно: это leading-throttle — вызов происходит в начале интервала, а последнее событие в окне может быть проигнорировано.

Использование для scroll:
window.addEventListener(
"scroll",
throttle(() => {
console.log(window.scrollY);
}, 200),
{ passive: true }
);


Типичные сценарии: обновление прогресс-бара прокрутки, подсветка текущей секции, вычисление позиций элементов при скролле.

Использование для mousemove:
window.addEventListener(
"mousemove",
throttle(e => {
console.log(e.clientX);
}, 100)
);


🔥 Такой подход особенно важен, когда обработчик содержит вычисления, работу с DOM или потенциально тяжёлую логику.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥117🤝7
📱 Finite State Machine: наводим порядок в логике интерфейса!

Большинство багов в UI появляются не из-за рендера или данных, а из-за неявных и конфликтующих состояний.

В этом посте:
Покажем, как описывать состояния и допустимые переходы;

Реализуем минимальный движок FSM;

Применим его к реальному сценарию загрузки данных;

Отделим состояние от эффектов и упростим логику UI.


FSM позволяет превратить хаотичные условия в строгую модель поведения, где невозможные сценарии просто не могут произойти.

📣 JS Ready | #гайд
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍7🤝61
This media is not supported in your browser
VIEW IN TELEGRAM
😎 freeCodeCamp — бесплатная база для удобного изучения языка!

Здесь собраны различные курсы по JS: от самых основ до уверенной практики. Всё построено просто — читаешь, пишешь код и сразу закрепляешь знания на заданиях. Отличный вариант, если не знаешь с чего начать или хочешь укрепить базу.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥108
Фон, реагирующий на звук через Web Audio API

С помощью Web Audio API можно в реальном времени анализировать входящий аудиопоток с микрофона и использовать полученные данные для динамического изменения фона.

Добавим кнопку:
<button id="start">Включить микрофон</button>


Подключаем микрофон и создаём источник:
const btn = document.getElementById("start");

btn.onclick = async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const ctx = new AudioContext();
await ctx.resume(); // требуется в некоторых браузерах
const src = ctx.createMediaStreamSource(stream);


Создаём анализатор:
  const analyser = ctx.createAnalyser();
const data = new Uint8Array(analyser.frequencyBinCount);
src.connect(analyser);


Меняем фон в зависимости от уровня сигнала:
  function animate() {
analyser.getByteFrequencyData(data);
const volume = data.reduce((a, b) => a + b, 0) / data.length;
const hue = Math.min(360, volume * 3);
document.body.style.background = `hsl(${hue}, 80%, 50%)`;
requestAnimationFrame(animate);
}


Запускаем:
  animate();
btn.remove();
};


🔥 Говорите — и фон реагирует в реальном времени. Такой эффект можно использовать в музыкальных визуализациях, интро-анимациях или как интерактивную деталь интерфейса.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍97🤝1
Отмена запросов через AbortController — контроль асинхронности!

При активном взаимодействии с интерфейсом старые запросы могут перезаписывать новые данные. Решение — корректно отменять такие запросы. Для этого в браузере есть нативный AbortController.

Создаём контроллер, передаём signal в fetch и при необходимости отменяем запрос.

Базовый пример:
const controller = new AbortController();

fetch("/api/data", { signal: controller.signal })
.catch(err => {
if (err.name === "AbortError") {
console.log("Запрос отменён");
return;
}
throw err; // остальные ошибки не глушим
});

// где-то позже, когда запрос стал неактуален:
controller.abort();


Частый сценарий — каждый новый запрос отменяет предыдущий. Это актуально для поиска, фильтров и автокомплита.

Решение — простая утилита с AbortController в замыкании.

Компактная утилита с авто-отменой:
function createCancelableFetch() {
let controller;

return (url, init) => {
controller?.abort();
controller = new AbortController();

return fetch(url, { ...init, signal: controller.signal }).then(async r => {
if (!r.ok) {
throw new Error(`HTTP ${r.status}`);
}
return r.json();
});
};
}


Использование — пример «живого» ввода. Каждый новый ввод автоматически отменяет предыдущий запрос, поэтому в обработку попадают только актуальные данные:
const fetchUsers = createCancelableFetch();

input.addEventListener("input", e => {
fetchUsers(`/api/users?q=${encodeURIComponent(e.target.value)}`)
.then(console.log)
.catch(err => {
if (err.name === "AbortError") return; // это ожидаемо
console.error(err); // остальные ошибки важны
});
});


🔥 Такой подход устраняет гонки ответов, упрощает управление асинхронностью и обеспечивает корректное обновление состояния интерфейса.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍8🤝73
📂 Напоминалка для работы с DOM!

DOM — это то, через что JavaScript управляет HTML: ищет элементы, создаёт новые узлы, вешает события и реагирует на действия пользователя.

На картинке — базовые методы document и node, а также самые часто используемые события мыши, клавиатуры и форм.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍9🤝81
Быстро приводим значение к boolean — без лишних проверок!

В JS логические значения — это не только true и false.
Любое значение в условии считается либо truthy, либо falsy.

По умолчанию falsy всего несколько значений:
false
0
''
null
undefined
NaN


Всё остальное — truthy, даже пустые объекты и массивы.

Если нужно явно получить boolean, а не полагаться на неявные приведения, используют оператор логического отрицания.

Одно ! инвертирует значение:
!0    // true
!1 // false


Два ! подряд делают именно то, что нужно — приводят значение к true или false:
!!0        // false
!!1 // true
!!'text' // true
!!null // false


Это часто удобнее и короче, чем Boolean(value):
Boolean(value); // то же самое, но длиннее


🔥 Поэтому, !!value — быстрый и наглядный способ получить boolean в коде.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍108
This media is not supported in your browser
VIEW IN TELEGRAM
☕️ CodeAbbey — тренажёр алгоритмического мышления!

Сайт с огромной коллекцией задач по программированию, от самых простых до тех, что реально заставят подумать.
Учиться можно на абсолютно любом языке. Отличный способ подтянуть логику, научиться писать аккуратный код и подготовиться к собесам.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍137🤝7
Ленивая инициализация логики (Lazy Initialization)!

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

Пример обычной инициализации:
function initAnalytics() {
console.log("init analytics");
return {
track: e => console.log("track:", e)
};
}


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

Добавим ленивую обёртку с кэшированием результата:
function lazy(fn) {
let initialized = false;
let value;

return () => {
if (!initialized) {
value = fn();
initialized = true;
}
return value;
};
}


Функция выполнится только при первом вызове, результат сохранится внутри замыкания и будет переиспользоваться.

Подключение:
const getAnalytics = lazy(initAnalytics);


Пока getAnalytics() не вызван, инициализация не происходит.

Использование:
getAnalytics().track("page_view");


Инициализация происходит в этой точке и больше не повторяется.

Пример с DOM (предполагается, что DOM уже доступен):
const getModal = lazy(() => {
const el = document.createElement("div");
el.textContent = "Modal";
document.body.append(el);
return el;
});


Элемент создаётся только при первом обращении:
getModal().style.display = "block";


🔥 Подход удобен для логики, которая должна инициализироваться один раз и использоваться по требованию.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥129👍9
Извлекаем и обрабатываем выделенный текст — Selection API

Selection API позволяет получать выделение пользователя в DOM (кроме <input> и <textarea>, где нужно использовать selectionStart/selectionEnd). API подходит для подсветки, анализа, сохранения выделений и запуска контекстных действий.

Получаем выделенный текст:
const text = window.getSelection().toString();
console.log("Выделено:", text);


Отслеживаем изменения выделения:
document.addEventListener("selectionchange", () => {
const t = window.getSelection().toString();
if (t) console.log("Новое выделение:", t);
});


Извлекаем детали выделения:
const sel = window.getSelection();

console.log("anchorNode:", sel.anchorNode);
console.log("focusNode:", sel.focusNode);
console.log("rangeCount:", sel.rangeCount);


Удобный хелпер:
function onSelect(callback) {
const handler = () => {
const text = window.getSelection().toString().trim();
if (text) callback(text);
};

document.addEventListener("selectionchange", handler);
return () => document.removeEventListener("selectionchange", handler);
}


Использование:
const unsubscribe = onSelect(selected => {
console.log("Пользователь выделил:", selected);
});


🔥 Такой пример полезен для практики работы с браузерными API, реакцией на системные события и динамическим управлением интерфейсом.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍119🔥6🤝2
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ Human Who Codes — блог Николаса Закаса, одного из самых влиятельных программистов в мире JS!

Это не обучающие статьи, а глубокие разборы архитектуры, устройства языка, качества кода и масштабируемых решений. Здесь много про то, как писать код: принципы, ограничения языка, реальные инженерные компромиссы.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍7🤝7
Проверяем наличие свойства без ловушек прототипа!

Часто нужно проверить, есть ли у объекта собственное свойство.
Некоторые пишут так:
obj.hasOwnProperty('key');


Проблема в том, что этот способ небезопасен: метод может быть переопределён, объекта может вообще не быть прототипа и код становится хрупким в edge-кейсах.

В современном JavaScript есть корректный и нативный способ — Object.hasOwn:
Object.hasOwn(obj, 'key');


Он не зависит от прототипа объекта, не ломается, если hasOwnProperty затёрт и работает даже с Object.create(null).
const dict = Object.create(null);
dict.x = 1;

Object.hasOwn(dict, 'x'); // true


Для сравнения, in ведёт себя иначе:
'a' in obj; // true — даже если свойство в прототипе


🔥 Object.hasOwn проверяет только то, что реально лежит в объекте.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍8🔥7
📂 Напоминалка для работы с Map!

Map — это удобная структура данных для хранения пар ключ - значение, где ключом может быть что угодно, а порядок элементов сохраняется.

На картинке — часто используемые методы Map: от добавления и получения значений до перебора данных.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥137👍7🤝2