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

Автор: @energy_it

Реклама на бирже:
https://telega.in/c/javascript_readyy
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
🤔 Code JavaScript — большой учебник и практикум по JS!

На сайте собрана полноценная база материалов по JavaScript: от базового синтаксиса и работы с DOM до более сложных тем вроде замыканий, событий, async/await и ООП. Материал построен в формате уроков и практических заданий, поэтому подходит не только для чтения, но и для закрепления знаний на практике.

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

📣 JS Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝118👍5
Почему Object.freeze() не делает объект полностью immutable?

Object.freeze() часто воспринимают как "защитить объект от любых изменений". Но есть нюанс: он работает только поверхностно.
const config = Object.freeze({
api: { retry: 3 }
});

config.api.retry = 10;

console.log(config.api.retry);
// 10


На первый взгляд странно: объект же frozen. Но заморожен только сам config. Свойство api действительно нельзя переназначить, удалить или изменить его descriptor. А вот объект, на который оно ссылается, остаётся обычным mutable-объектом.

То есть вот так уже нельзя:
config.api = null;

console.log(config.api);
// { retry: 10 }


И тут важный момент: в обычном режиме js просто проигнорирует такую попытку; в "use strict" будет TypeError.

Пример:
"use strict";

const user = Object.freeze({
name: "Alex"
});

user.name = "John";
// TypeError: Cannot assign to read only property 'name'


Но вложенные объекты всё равно можно менять, если их отдельно не заморозить. Для базовой глубокой заморозки можно написать небольшой хэлпер:
function deepFreeze(obj) {
if (obj && typeof obj === "object" && !Object.isFrozen(obj)) {
Object.values(obj).forEach(deepFreeze);
Object.freeze(obj);
}

return obj;
}

const settings = deepFreeze({
api: { retry: 3 }
});


И теперь:
settings.api.retry = 10;

console.log(settings.api.retry);
// 3


В обычном режиме присваивание будет молча проигнорировано. В "use strict" — упадёт с TypeError.

Важно: это упрощённая версия deepFreeze. В реальном коде могут всплыть Symbol-свойства, non-enumerable свойства, циклические ссылки и другие детали. Для production-версии обычно используют Reflect.ownKeys() и защиту от циклических ссылок через WeakSet.

Но для понимания главной идеи этого достаточно: Object.freeze() не делает объект глубоко immutable. Он замораживает только первый уровень.

🔥 Полезно помнить для конфигов, enum-подобных объектов и любых структур, которые не должны случайно мутироваться во время выполнения.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍6🤝5
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Для удобной работы с .sass-синтаксисом в VS Code!

Sass (.sass only)
добавляет полноценную поддержку indented-синтаксиса Sass: подсветку, автодополнение, навигацию и корректное распознавание .sass-файлов без фигурных скобок и точек с запятой. Помогает комфортно работать со старыми и современными Sass-проектами прямо в редакторе.

📣 JS Ready | #vscode
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝12👍4🔥31
Создаём управляемый Promise без boilerplate!

Раньше, чтобы получить resolve и reject снаружи Promise, приходилось писать так:
let resolve;

const promise = new Promise(res => {
resolve = res;
});


Это работает, но создаёт лишние переменные и выглядит менее аккуратно.

Теперь в JavaScript есть нативный Promise.withResolvers():
const { promise, resolve, reject } =
Promise.withResolvers();


Он сразу возвращает готовый Promise и функции управления им.
resolve('done');
await promise;


Особенно удобно для очередей, WebSocket, Stream API, событийной логики и мостов между callback/event API и async-await.

await в примере работает внутри async-функции или ES-модуля с top-level await. Также проверь поддержку Promise.withResolvers() в своей среде выполнения.

🔥 Promise.withResolvers() убирает boilerplate и делает создание управляемых Promise намного чище и читаемее.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
11👍6🔥5
🧐 Наткнулся на годную статью на Хабре: «TTF-DOOM: как я запустил 3D-рейкастер внутри TrueType-шрифта»!

В этой статье:
• Показывается, как TrueType hinting VM можно использовать не только для рендеринга шрифтов, но и как полноценную вычислительную среду;
• Разбирается архитектура запуска 3D-рейкастера внутри TTF-шрифта с использованием JavaScript, bytecode и собственного DSL-компилятора;
• Объясняются неожиданные особенности и ограничения TrueType VM.


🔊 Продолжайте читать на Habr!


📣JS Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍135🔥5
📂 Напоминалка по JavaScript Date и времени!

Например, new Date() создаёт объект даты, toISOString() помогает получить дату в UTC-формате, а getTime() — работать с таймстампами и вычислениями.

На картинке — методы и операции для работы с датами, временем, UTC и форматированием.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🤝12👍65
Как красиво выводить списки без ручных запятых?

Часто нужно показать список технологий, авторов, тегов или участников.

Обычно это начинают собирать вручную:
names.join(', ')


Но в JS есть нативный API — Intl.ListFormat.
newIntl.ListFormat('ru').format(names);


Он сам расставляет запятые, союзы и учитывает правила языка.
newIntl.ListFormat('en').format(names);
// React, Vue, and Svelte


Можно менять тип списка: обычное перечисление, выбор или разделение.
new Intl.ListFormat('ru', {
type: 'disjunction'
}).format(['наличные', 'карта']);
// наличные или карта


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

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥15👍5🤝52
This media is not supported in your browser
VIEW IN TELEGRAM
👩‍💻 Стили пишутся прямо в React-компонентах.

vscode-styled-components
делает работу со styled-components намного удобнее: появляются подсказки CSS, подсветка цветов, автодополнение свойств и форматирование прямо внутри JS/TS-файлов. Всё работает почти как в отдельном CSS-файле.

📣 JS Ready | #vscode
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥6🤝4
URL.canParse + URL API — проверка URL без try/catch и regex!

Частая задача в JS: проверить URL перед fetch, редиректом, сохранением в БД, проксированием или обработкой пользовательского ввода.

Обычно многие делают так:
function isValid(url) {
try {
new URL(url);

return true;
} catch {
return false;
}
}


Способ рабочий, но со временем такие проверки начинают размножаться по проекту в десятках мест. Минусы:— try/catch ради обычной проверки читается тяжеловато— многие потом начинают дописывать сверху regex— появляются разные реализации одной и той же логики.

Но в платформе есть нативный способ — URL.canParse().
URL.canParse("https://example.com");
// true

URL.canParse("not-a-url");
// false


Без исключений и без самописных проверок. Просто получаешь boolean.

Но тут есть важный момент, про который многие забывают — относительные URL. Например:
URL.canParse("/api/users");
// false


Это не ошибка метода. Просто относительный путь нельзя распарсить без base URL. Поэтому правильно так:
URL.canParse(
"/api/users",
"https://example.com"
);
// true


И потом этот же base используешь при создании URL:
const url = new URL(
"/api/users",
"https://example.com"
);


Это особенно полезно в SSR, middleware, proxy и серверных обработчиках, где часто работают именно с относительными путями.

Ещё хороший кейс — фильтрация пользовательского ввода.
const input = [
"https://a.com",
"ftp://b.com",
"invalid"
];

const valid = input.filter(u =>
URL.canParse(u)
);


Но тут есть нюанс, canParse() проверяет только то, что строка корректно парсится как URL с точки зрения WHATWG URL parser. Это не проверка безопасности и не проверка того, что URL подходит именно для вашего кейса.

Например ftp: или даже javascript: тоже могут успешно парситься. Поэтому для API, fetch и редиректов обычно дополнительно проверяют protocol:
function parseHttpUrl(u) {
if (!URL.canParse(u)) {
return null;
}

const url = new URL(u);

return (
url.protocol === "http:" ||
url.protocol === "https:"
)
? url
: null;
}


А для редиректов и proxy этого тоже часто недостаточно — обычно дополнительно проверяют hostname/origin через allowlist.

Ещё один полезный момент — нормализация URL. Очень часто одинаковые ссылки приходят в разном виде:
https://example.com
https://example.com/


Через URL API это можно привести к одному формату:
function normalize(u) {
if (!URL.canParse(u)) {
return null;
}

return new URL(u).href;
}

normalize("https://example.com");
normalize("https://example.com/");


🔥 В итоге: если нужно проверить, разобрать или нормализовать URL — лучше сразу использовать стандартный URL API. Кода меньше, поведение предсказуемее и меньше шансов словить странные баги на парсинге.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
9👍5🔥4
This media is not supported in your browser
VIEW IN TELEGRAM
💅 Ravesli JavaScript — курс по основам JS для начинающих!

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

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

📣 JS Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🤝65
📂 Напоминалка по сетевым протоколам!

Например, HTTP/1.1 и HTTP/2 работают через TCP, обеспечивая надёжную доставку данных, а HTTP/3 использует QUIC поверх UDP, что позволяет уменьшить задержки и ускорить загрузку страниц.

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

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍54
Сортировка строк без ручных костылей!

Обычный sort() сортирует строки лексикографически, поэтому числа внутри строк идут не так, как ожидает пользователь.
['file2', 'file10', 'file1'].sort();
// ['file1', 'file10', 'file2']


Для более понятной сортировки в JS есть Intl.Collator.
const collator = new Intl.Collator('ru', {
numeric: true
});


Опция numeric: true заставляет сравнивать числа внутри строк как числа, а не как символы.
['v2', 'v10', 'v1'].sort(collator.compare);
// ['v1', 'v2', 'v10']


А sensitivity: 'base' помогает не цепляться к регистру и мелким различиям при сравнении.
new Intl.Collator('ru', {
sensitivity: 'base'
});


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

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍176🔥6
This media is not supported in your browser
VIEW IN TELEGRAM
❤️ Web Links — огромная подборка ресурсов по JavaScript и веб-разработке!

На сайте собрана большая коллекция полезных ссылок для разработчиков: учебники, документация, статьи, блоги, инструменты, библиотеки и сервисы по JavaScript, HTML, CSS, React, Node.js и другим технологиям веб-разработки. Всё удобно структурировано по категориям, что позволяет быстро находить нужные материалы для изучения или работы.

📌 Оставляю ссылочку: vallek.github.io

📣 JS Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥97👍5
Object.hasOwn() — способ проверить, есть ли у объекта собственное свойство!

Чаще всего для этого используют hasOwnProperty():
const user = {
name: "Анна"
};

console.log(user.hasOwnProperty("name")); // true


Способ рабочий, но есть один нюанс. hasOwnProperty — обычный метод объекта. Если он был переопределён, результат проверки уже может оказаться неожиданным.
const user = {
name: "Анна",
hasOwnProperty: () => false
};

console.log(user.hasOwnProperty("name")); // false


Именно поэтому долгое время надёжным вариантом считался вызов через прототип:
const user = {
name: "Анна"
};

console.log(
Object.prototype.hasOwnProperty.call(user, "name")
); // true


Такой код работает корректно независимо от содержимого объекта, но выглядит довольно громоздко. Сейчас для этой задачи есть отдельный метод:
const user = {
name: "Анна"
};

console.log(
Object.hasOwn(user, "name")
); // true


По сути это более удобная запись той же проверки. Особенно полезен Object.hasOwn() при работе с объектами без прототипа:
const cache = Object.create(null);

cache.users = [];

console.log(
Object.hasOwn(cache, "users")
); // true


У таких объектов метода hasOwnProperty нет вовсе:
const cache = Object.create(null);

console.log(cache.hasOwnProperty);
// undefined


Ещё один пример — необходимость отличить собственные свойства от унаследованных:
const user = {
name: "Анна"
};

console.log(
Object.hasOwn(user, "toString")
); // false


Хотя доступ к toString есть, само свойство находится в прототипе.
По этой же причине Object.hasOwn() нередко используют внутри for...in, чтобы обрабатывать только собственные свойства объекта.
for (const key in data) {
if (Object.hasOwn(data, key)) {
console.log(key);
}
}


🔥 Если нужно проверить наличие свойства именно у объекта, а не где-то в его прототипной цепочке, Object.hasOwn() сегодня является самым понятным и читаемым решением.

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

Htmltagwrap —
позволяет выделить любой фрагмент и за секунду обернуть его в нужный тег: div, span, section и любой другой, без ручного написания. Особенно удобно при верстке, работе с JSX и быстром редактировании разметки.

📣 JS Ready | #vscode
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍6🤝5😁1
📂 Напоминалка для работы с микросервисами!

Например, Load Balancer распределяет запросы между несколькими серверами, а API Gateway управляет доступом к API, маршрутизацией и ограничением запросов.

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

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍106🔥4
Красивый диапазон дат без ручной склейки!

Очень частая задача в интерфейсе: показать период акции, бронь, событие или дедлайн.

Обычно начинают собирать строку руками:
`${start} - ${end}`


Но так быстро появляются проблемы с локалями, месяцами и повторяющимися частями даты.

В JS есть нативный метод formatRange() у Intl.DateTimeFormat.
fmt.formatRange(startDate, endDate)


Он сам форматирует диапазон по правилам выбранной локали.
fmt.formatRange(
new Date('2026-03-10'),
new Date('2026-03-14')
);


Если даты в одном месяце, результат будет компактным.
// 10–14 марта


А если диапазон пересекает месяцы — формат тоже останется корректным.
fmt.formatRange(
new Date('2026-03-30'),
new Date('2026-04-02')
);
// 30 марта – 2 апреля


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

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍16🤝65
Разбираем разницу между Promise.all() и Promise.allSettled()!

Отличия между ними проявляются в момент ошибки. Если использовать Promise.all(), то достаточно одного rejected-промиса, чтобы весь результат тоже стал rejected:
await Promise.all([
fetchUser(),
fetchPosts(),
fetchComments()
]);


При этом остальные операции не отменяются. Запросы, таймеры и прочая асинхронщина продолжают выполняться. Просто Promise.all() больше не ждёт общий успешный результат.

Когда нужен результат каждой операции независимо от исхода, есть Promise.allSettled():
const results = await Promise.allSettled([
fetchUser(),
fetchPosts(),
fetchComments()
]);


На выходе получится массив объектов со статусом каждого промиса:
[
{ status: "fulfilled", value: {...} },
{ status: "rejected", reason: Error(...) },
{ status: "fulfilled", value: [...] }
]


Это удобно для независимых задач. Например, страница загружает профиль пользователя, уведомления и рекомендации. Если рекомендации упали с ошибкой, профиль и уведомления всё равно можно показать. Или пакетная обработка:
const results = await Promise.allSettled(
users.map(user => sendEmail(user))
);


После выполнения можно отдельно посмотреть успешные и неуспешные операции, собрать статистику или повторно обработать ошибки.

🔥 Promise.all() отвечает на вопрос: «Все операции завершились успешно?». Promise.allSettled() отвечает на другой вопрос: «Чем закончилась каждая операция?». Из-за этого они не заменяют друг друга и используются для разных сценариев.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11🔥65
This media is not supported in your browser
VIEW IN TELEGRAM
💅 Frontend Stuff — коллекция полезных ресурсов для frontend-разработчиков!

На сайте собрана большая база материалов для JavaScript-разработчиков: статьи, библиотеки, фреймворки, инструменты, полезные сервисы и обучающие ресурсы. От базовых инструментов до React, Vue, Node.js и др. Отличный ресурс для веб-разработчиков, которые хотят ускорить работу или найти новые инструменты.

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

📣 JS Ready | #сайт
Please open Telegram to view this post
VIEW IN TELEGRAM
👍106🔥5
📂 Напоминалка по деструктуризации объектов!

При деструктуризации можно задавать значения по умолчанию — они применяются только когда значение свойства равно undefined (включая случай, когда свойства нет в объекте).

На картинке показано, как работает извлечение значений из объекта person, как подставляются fallback-значения при отсутствии данных, а также разбор кейсов с undefined, null и другими типами значений.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🔥5🤝3