Извлекаем и обрабатываем выделенный текст — Selection API
Selection API позволяет получать выделение пользователя в DOM (кроме
Получаем выделенный текст:
Отслеживаем изменения выделения:
Извлекаем детали выделения:
Удобный хелпер:
Использование:
🔥 Такой пример полезен для практики работы с браузерными
📣 JS Ready | #практика
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, реакцией на системные события и динамическим управлением интерфейсом.Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤9🔥6🤝2
This media is not supported in your browser
VIEW IN TELEGRAM
Это не обучающие статьи, а глубокие разборы архитектуры, устройства языка, качества кода и масштабируемых решений. Здесь много про то, как писать код: принципы, ограничения языка, реальные инженерные компромиссы.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍7🤝7
Проверяем наличие свойства без ловушек прототипа!
Часто нужно проверить, есть ли у объекта собственное свойство.
Некоторые пишут так:
Проблема в том, что этот способ небезопасен: метод может быть переопределён, объекта может вообще не быть прототипа и код становится хрупким в edge-кейсах.
В современном JavaScript есть корректный и нативный способ —
Он не зависит от прототипа объекта, не ломается, если
Для сравнения,
🔥
📣 JS Ready | #совет
Часто нужно проверить, есть ли у объекта собственное свойство.
Некоторые пишут так:
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 проверяет только то, что реально лежит в объекте.Please open Telegram to view this post
VIEW IN TELEGRAM
❤11👍8🔥7
Map — это удобная структура данных для хранения пар ключ - значение, где ключом может быть что угодно, а порядок элементов сохраняется.
На картинке — часто используемые методы Map: от добавления и получения значений до перебора данных.
Сохрани, чтобы не забыть!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13❤7👍7🤝2
map vs reduce — различие по назначению и семантике!
Методы
Рассмотрим массив данных:
Использование
Использование
Область применения
Пример агрегации:
Здесь
Ошибка — применение
В таком случае нарушается контракт метода:
Корректный вариант:
🔥
📣 JS Ready | #практика
Методы
map и reduce относятся к базовым инструментам работы с массивами в JavaScript. Несмотря на внешнее сходство, они решают принципиально разные задачи.Рассмотрим массив данных:
const payments = [
{ id: 1, amount: 100 },
{ id: 2, amount: 200 },
{ id: 3, amount: 150 }
];
Использование
map:const amounts = payments.map(p => p.amount);
map предназначен для детерминированного преобразования элементов массива. Каждый входной элемент соответствует одному выходному значению, без накопления состояния и побочных эффектов.Использование
reduce для той же задачи:const amounts = payments.reduce((acc, p) => {
acc.push(p.amount);
return acc;
}, []);reduce используется как универсальный аккумулятор вместо специализированного инструмента.Область применения
reduce начинается там, где появляется агрегирование.Пример агрегации:
const totalAmount = payments.reduce(
(sum, p) => sum + p.amount,
0
);
Здесь
reduce выражает свёртку массива в одно значение, что невозможно корректно описать через map.Ошибка — применение
map без использования результата:payments.map(p => {
console.log(p.amount);
});В таком случае нарушается контракт метода:
map предполагает формирование нового массива, а не выполнение побочных действий.Корректный вариант:
payments.forEach(p => {
console.log(p.amount);
});map следует использовать для чистых преобразований структуры данных. reduce — для агрегаций и свёрток, где результат зависит от совокупности элементов массива.Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍9🔥7
В этой статье:
• Разберётесь, почему при обычном throw new Error(...) часто теряется исходный тип ошибки;
• Научитесь оборачивать ошибки правильно, сохраняя первопричину;
• Узнаете, как логировать полную цепочку ошибок и выводить стеки вручную;
• Поймёте, как использовать cause в кастомных классах ошибок и писать более точные проверки в тестах.🔊 Продолжайте читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥7🤝7
Быстро приводим значение к числу!
Часто данные приходят строками: из формы, URL, localStorage.
Один из способов привести значение к числу — унарный +:
На выходе получаем обычный Number:
Важно понимать:
+ приводит значение именно к Number, а не к целому числу:
Также работает с boolean — удобно для нормализации данных:
Иногда в коде встречается альтернативный приём — двойная тильда ~~. Она приводит значение к целому числу через 32-битную побитовую арифметику:
📣 JS Ready | #совет
Часто данные приходят строками: из формы, URL, localStorage.
Один из способов привести значение к числу — унарный +:
let value = "15";
value = +value;
На выходе получаем обычный Number:
typeof value; // "number"
Важно понимать:
+ приводит значение именно к Number, а не к целому числу:
+"15.7" // 15.7
+"15px" // NaN
Также работает с boolean — удобно для нормализации данных:
+true; // 1
+false; // 0
Иногда в коде встречается альтернативный приём — двойная тильда ~~. Она приводит значение к целому числу через 32-битную побитовую арифметику:
~~"15" // 15
~~15.9 // 15
~~-1.9 // -1
+value — простой способ привести значение к Number.~~value — нишевый трюк для целых чисел, только если понимаете его ограничения.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥14❤9👍8😁2
This media is not supported in your browser
VIEW IN TELEGRAM
Здесь собраны структурированные документации по JS и смежным технологиям, ориентироваться в темах быстро и удобно. Можно подтянуть понимание языка: методы массивов, строки, даты, поведение консоли, обработка событий и многое другое. Открываешь документацию, понимаешь механику, ограничения и реальные сценарии использования.
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍18🔥8❤7
Работаем с LocalStorage в браузере!
Сохранение и чтение строки — самый базовый сценарий, подходит для флагов UI или режимов отображения:
При чтении JSON стоит защитить парсинг от ошибок, и проверить
Обновление отдельных полей без потери остальных ключей — частая задача для хранения пользовательских предпочтений:
Событие
🔥
📣 JS Ready | #практика
LocalStorage используют для сохранения небольших данных на клиенте: состояния интерфейса, фильтров, тем, настроек или кэша состояния пользователя. Лимит хранения — несколько мегабайт (зависит от браузера).Сохранение и чтение строки — самый базовый сценарий, подходит для флагов UI или режимов отображения:
localStorage.setItem("view", "list");
console.log(`Текущий view: ${localStorage.getItem("view")}`);LocalStorage хранит только строки, поэтому для объектов нужна сериализация. Это стандарт при работе с конфигами и кэшем состояния:const session = { user: "admin", ttl: 600 };
localStorage.setItem("session", JSON.stringify(session));При чтении JSON стоит защитить парсинг от ошибок, и проверить
null перед парсингом, чтобы приложение не падало при битых данных или пустом ключе:const raw = localStorage.getItem("session");
let data = null;
if (raw) {
try {
data = JSON.parse(raw);
} catch {
data = null;
}
}
console.log("Пользователь:", data?.user);Обновление отдельных полей без потери остальных ключей — частая задача для хранения пользовательских предпочтений:
const prefs = JSON.parse(localStorage.getItem("prefs") || "{}");
prefs.theme = "dark";
prefs.updatedAt = Date.now();
localStorage.setItem("prefs", JSON.stringify(prefs));
console.log("Предпочтения сохранены");Событие
storage помогает синхронизировать состояние между вкладками (но не срабатывает в той же вкладке, где вызван setItem):window.addEventListener("storage", (e) => {
console.log(`Обновлён ключ: ${e.key}, значение: ${e.newValue}`);
});LocalStorage объединяет хранение и быстрый доступ на клиенте, что упрощает восстановление UI и ускоряет работу интерфейса.Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥12❤9👍8
В этой шпаргалке собраны основные методы и свойства Mutation Observer API для отслеживания структурных и атрибутных изменений DOM. Здесь отражены инструменты, позволяющие наблюдать за добавлением и удалением узлов, изменениями атрибутов и текстового содержимого, а также управлять жизненным циклом наблюдателя в прикладных сценариях.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥16❤9👍9
“Одноразовый” import для быстрого теста без бандлера и лишних файлов!
В браузере HTTP-ответы ESM могут попадать в
Чтобы гарантировать запрос свежей версии, добавляем динамический query-параметр (
Теперь при каждом вызове браузер будет запрашивать модуль заново, и вы сразу видите последние правки:
Никаких рестартов и ручной очистки кеша:
🔥 Динамический import с cache-buster меняет URL и помогает получать свежую версию модуля без сборки и ручной очистки кеша. На поведение могут влиять Service Worker, прокси и политики HTTP-кеша.
📣 JS Ready | #совет
В браузере HTTP-ответы ESM могут попадать в
memory/disk cache, поэтому после правки файла обычный import может не подхватить изменения:await import('./module.js');Чтобы гарантировать запрос свежей версии, добавляем динамический query-параметр (
cache-buster), который меняет URL:await import(`./module.js?u=${Date.now()}`);Теперь при каждом вызове браузер будет запрашивать модуль заново, и вы сразу видите последние правки:
const mod = await import(`./calc.js?u=${Date.now()}`);
mod.test();Никаких рестартов и ручной очистки кеша:
await import(`./config.js?u=${Date.now()}`).then(m => m.init());Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤8🔥7
Желаю каждому провести новый 2026 год намного лучше и выполнить все планы. Моя цель: набрать более 15 тысяч подписчиков.
Please open Telegram to view this post
VIEW IN TELEGRAM
5❤20👍8🤝6🔥1
Генератор QR-кодов прямо в браузере!
QR-коды часто нужны в разработке: передача ссылок, упаковка тестовых данных, автоматизация, обмен данными для ботов. Сделаем генератор на чистом JavaScript с помощью
Подключаем библиотеку в браузер через CDN как ES-модуль:
Создаём функцию генерации QR в
Генерируем QR для ссылки или текста:
Формально вызовы идут параллельно (fire-and-forget). Если нужен контроль завершения — используем
Генерация QR для JSON:
Можно кодировать JSON, токены и любые строковые данные.
🔥 В итоге получаем простой инструмент для генерации QR-кодов под большинство данных прямо в браузере. Легко встраивается в проекты, тестовые утилиты и ботов.
📣 JS Ready | #практика
QR-коды часто нужны в разработке: передача ссылок, упаковка тестовых данных, автоматизация, обмен данными для ботов. Сделаем генератор на чистом JavaScript с помощью
qrcode.Подключаем библиотеку в браузер через CDN как ES-модуль:
<script type="module">
import QRCode from "https://cdn.jsdelivr.net/npm/qrcode@1.5.3/+esm";
// Делаем доступным глобально, чтобы примеры ниже работали при копипасте
window.QRCode = QRCode;
</script>
Создаём функцию генерации QR в
DataURL (data:image/png;base64,... по умолчанию):async function generateQR(text) {
try {
const url = await QRCode.toDataURL(text, { width: 300 });
console.log("QR DataURL:", url);
return url;
} catch (e) {
console.error("Ошибка генерации QR:", e);
return null;
}}Генерируем QR для ссылки или текста:
generateQR("https://example.com").then(qr => {
if (qr) console.log("QR успешно создан");
});Формально вызовы идут параллельно (fire-and-forget). Если нужен контроль завершения — используем
Promise.all, но для простых задач достаточно forEach:["Alpha", "Beta", "Gamma"].forEach(t => {
generateQR(t).then(qr => console.log(`QR для ${t}:`, !!qr));
});Генерация QR для JSON:
const payload = JSON.stringify({ id: 123, role: "tester", active: true });
generateQR(payload).then(qr => console.log("QR для JSON готов:", !!qr));Можно кодировать JSON, токены и любые строковые данные.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15👍9🤝7
Мы постоянно используем
for..of, ...spread, Array.from(), но редко задумываемся, как работает протокол итераторов, который можно реализовать вручную для любых структур. В этом посте:
• Поймём устройство Symbol.iterator и next();
• Сделаем свои перебираемые объекты, не похожие на массивы;
• Управляем моментом остановки обхода;
• Строим линейный API для предсказуемого перебора данных.
Iterator Protocol — это способ описать объект так, чтобы движок понимал его как источник данных с управляемым обходом, а не как статичную коллекцию.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
❤10🔥8👍7