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

Cотрудничество: @energy_c
Download Telegram
📂 Напоминалка по архитектуре REST API!

Например, Stateless означает, что каждый запрос содержит всю необходимую информацию для его обработки, а Cacheable позволяет кэшировать ответы и снижать нагрузку на сервер.

На картинке — основные принципы REST: Client-Server, Stateless, Uniform Interface, Cacheable, Layered System и Code on Demand, а также примеры HTTP-методов и взаимодействия клиента с сервером.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥96👍6
ArrayBuffer.transfer() — переносим содержимое буфера!

При обработке файлов, изображений, аудио и сетевых данных часто приходится изменять размер бинарного буфера или передавать его содержимое в новый ArrayBuffer. Обычно для этого нужно создать новый буфер и вручную скопировать байты, а transfer() объединяет эти действия в одну операцию.

Для начала создадим небольшой буфер и запишем в него четыре значения:
const buffer = new ArrayBuffer(8);
const bytes = new Uint8Array(buffer);

bytes.set([10, 20, 30, 40]);
console.log(bytes);


ArrayBuffer хранит непосредственно бинарные данные, а Uint8Array предоставляет представление для чтения и записи отдельных байтов. Оба объекта используют одну область памяти, поэтому изменения через bytes сразу отражаются в buffer.

Теперь перенесём содержимое в новый буфер:
const moved = buffer.transfer();

console.log(moved.byteLength); // 8
console.log(buffer.byteLength); // 0


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

Проверим, что значения сохранились после переноса:
const movedBytes = new Uint8Array(moved);

console.log([...movedBytes]);
// [10, 20, 30, 40, 0, 0, 0, 0]


Новый Uint8Array создаётся уже поверх moved. Первые четыре байта содержат записанные значения, а оставшаяся часть буфера по-прежнему заполнена нулями.

Во время переноса можно сразу указать новый размер:
const expanded = moved.transfer(16);

console.log(expanded.byteLength); // 16
console.log([...new Uint8Array(expanded)]);


При увеличении размера существующее содержимое сохраняется, а дополнительная область заполняется нулями. Что удобно для постепенно растущих бинарных данных: не требуется отдельно создавать буфер нужного размера и вызывать TypedArray#set() для ручного копирования.

Уменьшение выполняется тем же способом:
const trimmed = expanded.transfer(4);

console.log(trimmed.byteLength); // 4
console.log([...new Uint8Array(trimmed)]);
// [10, 20, 30, 40]


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

🔥 ArrayBuffer.transfer() полезен там, где нужно передать владение бинарными данными или изменить размер буфера без ручного копирования. При этом важно помнить, что после каждого переноса исходный буфер становится недоступен для дальнейшего использования.

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥106👍4🤝3
📂 Шпаргалка по JavaScript Promise!

Например, then() используется для обработки успешного выполнения, catch() — для ошибок, а finally() позволяет выполнить код независимо от результата.

На картинке собраны основные методы Promise, работа с цепочками, обработка ошибок, состояния pending, fulfilled и rejected, а также методы для работы с несколькими Promise — all(), allSettled(), race() и any().

Сохрани, чтобы было под рукой!

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍95🤝2
📱 Iterator API — управление итерацией и ленивые преобразования!

Шпаргалка по основным возможностям Iterator API: ручное управление итерацией, досрочное завершение и передача ошибок, создание iterable-объектов и ленивые преобразования через Iterator Helpers. Полезная база для углубления знаний об итераторах, генераторах и обработке последовательностей данных.

📣 JS Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍7🤝52
👨‍💻 Мега занимательная статья на Хабре: «Как я перестал бояться и полюбил ассемблер»!

В этой статье:
• Узнаете, как сегодня разрабатывать программы и игры для легендарного Atari ST 1985 года;
• Разберёте оптимизацию кода под Motorola 68000 с помощью C и ассемблера;
• Посмотрите, как автор портировал DOOM на Atari ST и заставил его работать на железе с 8 МГц и несколькими мегабайтами памяти.

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

📣JS Ready | #статья
Please open Telegram to view this post
VIEW IN TELEGRAM
👍96🔥4🤝2
📂 Шпаргалка по Event Loop в JavaScript!

Например, Promise.then() выполняется через Microtask Queue и имеет более высокий приоритет, чем setTimeout(), который попадает в Task Queue.

На картинке — основные компоненты JavaScript Event Loop:
Call Stack, Web APIs, Microtask Queue, Task Queue и сам цикл событий, который управляет выполнением синхронных и асинхронных операций.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍5🤝51
📂 Шпаргалка по Git Merge vs Git Rebase!

Например, git merge используется для объединения веток с сохранением полной истории изменений, а git rebase позволяет перенести коммиты на новую базу и сделать историю проекта более линейной.

На картинке показана разница между двумя подходами работы с ветками Git: как выглядит история коммитов после merge, где появляется отдельный merge-коммит, и после rebase, где изменения перестраиваются поверх актуальной ветки.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍75
Не синхронизируйте состояние — вычисляйте его!

Одна из частых причин багов — хранить одно и то же состояние в нескольких представлениях:
let items = [];
let total = 0;

items.push(product);

// Теперь нужно не забыть обновить total


Рано или поздно один участок кода изменит items, но забудет обновить total. Появляются два источника истины.

Если значение однозначно получается из других данных — вычисляйте его:
const total = items.reduce(
(sum, item) => sum + item.price,
0
);


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

Если вычисление действительно дорогое, тогда уже имеет смысл мемоизировать его — но не создавать второе изменяемое состояние:
const visibleUsers = users.filter(
user => user.active && user.role === role
);


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

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥75
📂 Шпаргалка по Cache Systems!

Например, Redis используется как быстрый in-memory cache для хранения часто запрашиваемых данных, сессий и временных значений, чтобы уменьшить нагрузку на базу данных. А CDN Cache позволяет отдавать статический контент ближе к пользователю, сокращая задержки и количество запросов к основному серверу.

На картинке — основные уровни кэширования в современных системах.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
👍97🔥5
Используйте Proxy для создания объектов с поведением, а не просто данных!

Многие используют объекты только как хранилище:
const config = {
theme: 'dark',
lang: 'ru'
};


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

Для этого в JavaScript есть Proxy.
const user = new Proxy({}, {
get(target, property) {
console.log(`Reading ${property}`);

return target[property];
}
});


Теперь обычное обращение к свойству запускает вашу логику:
user.name;


Можно создавать объекты с автоматическими значениями:
const settings = new Proxy({}, {
get(target, key) {
return target[key] ?? 'default';
}
});

console.log(settings.theme);
// default


Или автоматически валидировать изменения:
const user = new Proxy({}, {
set(target, key, value) {
if (key === 'age' && value < 0) {
throw new Error('Invalid age');
}

target[key] = value;
return true;
}
});


Теперь:
user.age = -5;
// Error


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

🔥 Proxy позволяет превращать обычные объекты JavaScript в объекты с собственной логикой поведения, не меняя код, который с ними работает.

📣 JS Ready | #совет
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍5🤝51
📱 Proxy API — перехват операций с объектами и функциями!

Разбираем Proxy API, с помощью которого можно перехватывать и переопределять базовые операции с объектами и функциями: контролировать доступ и изменение данных, управлять видимостью и перечислением свойств, отслеживать вызовы функций и создание экземпляров. Используется для валидации, логирования, метапрограммирования и создания гибкого поведения объектов.

📣 JS Ready | #шпора
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥9🤝42
📂 Напоминалка по циклам в JavaScript!

Например, for удобно использовать, когда заранее известно количество итераций, а for...of — когда нужно пройтись по массиву или строке.

На картинке — 5 циклов, которые постоянно встречаются в коде.

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

📣 JS Ready | #ресурс
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍8🤝32
Создаём индекс данных из массива для быстрого поиска через Map!

При работе с данными из API часто требуется получать элементы массива по идентификатору. Самый простой вариант — использовать find(), но при большом количестве повторных поисков такой подход приводит к постоянному перебору коллекции.

Например, поиск пользователя по id:
const users = [
{
id: 1,
name: "Alex"
},
{
id: 2,
name: "John"
}
];

const user = users.find(
user => user.id === 2
);

console.log(user);


Метод find() последовательно проверяет элементы массива и возвращает первое совпадение.

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

Вместо этого можно заранее создать индекс, где идентификатор будет использоваться как ключ, а объект — как значение:
const usersById = new Map(
users.map(user => [
user.id,
user
])
);

console.log(
usersById.get(2)
);


Теперь получение пользователя выполняется через ключ без повторного перебора массива.

По сложности подходы отличаются:
find() - O(n)
Map.get() - O(1) в среднем


Поэтому такой паттерн особенно полезен при работе с большими коллекциями и частыми операциями чтения.

Например, пользователи и их настройки могут приходить отдельными запросами:
const settings = [
{
userId: 1,
theme: "dark"
},
{
userId: 2,
theme: "light"
}
];

const settingsByUser = new Map(
settings.map(item => [
item.userId,
item
])
);


После создания индекса можно собрать итоговую структуру данных без вложенных поисков внутри массива:
const result = users.map(user => ({
...user,
settings: settingsByUser.get(user.id)
}));

console.log(result);


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

Для создания индекса также можно использовать обычный объект:
const usersById = Object.fromEntries(
users.map(user => [
user.id,
user
])
);

console.log(usersById[2]);


Однако Map лучше подходит для динамических коллекций, где требуется часто добавлять, удалять или получать элементы. Кроме того, он поддерживает любые типы ключей, имеет встроенное свойство size и не зависит от прототипа объекта.

Важно учитывать, что индекс — это дополнительная структура в памяти. Если нужен один поиск, обычный find() может быть проще и понятнее. Но при многократном доступе к данным создание индекса позволяет значительно сократить количество лишних операций.

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

📣 JS Ready | #практика
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍6🔥5