Используйте optional chaining не только для чтения — он умеет больше!
Большинство знают
Но у
Например, раньше часто писали:
Теперь:
Если функции нет — ничего не произойдет.
То же самое работает с методами:
И с массивами:
Еще один полезный случай — безопасный доступ к динамическим ключам:
Без дополнительных проверок:
🔥
📣 JS Ready | #совет
Большинство знают
?. только как замену длинным проверкам:if (user && user.profile) {
console.log(user.profile.name);
}Но у
optional chaining есть менее очевидное применение — безопасный вызов методов и функций.Например, раньше часто писали:
if (callback) {
callback(data);
}Теперь:
callback?.(data);
Если функции нет — ничего не произойдет.
То же самое работает с методами:
const result = api.getUser?.(id);
И с массивами:
users.find?.(u => u.id === 10);
Еще один полезный случай — безопасный доступ к динамическим ключам:
const value = config.handlers?.[eventName];
Без дополнительных проверок:
if (
config &&
config.handlers &&
config.handlers[eventName]
) {
...
}
?. — это не просто короткая запись для вложенных объектов. Это механизм доступа к любым необязательным частям кода: функциям, методам, массивам и динамическим свойствам.Please open Telegram to view this post
VIEW IN TELEGRAM
❤13🔥9👍6
Собраны основные методы
Array: добавление и удаление элементов, поиск и проверка, преобразование, копирование, сортировка и операции, изменяющие исходный массив.Отдельно удобно видеть разницу между мутирующими методами вроде
splice(), sort() и reverse() и современными немутирующими альтернативами — toSpliced(), toSorted() и toReversed().Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍7❤5
В каких случаях может быть нужен Object.is()?
Большинство сравнений в JavaScript делают через
Но у этого поведения есть два исключения:
Если нужно сравнение по алгоритму
Полезно при написании собственных функций сравнения, мемоизации и библиотек, где важно отличать все значения так же, как это делают некоторые встроенные механизмы JS.
Например:
Теперь изменение
🔥
📣 JS Ready | #совет
Большинство сравнений в JavaScript делают через
===:console.log(NaN === NaN);
// false
console.log(+0 === -0);
// true
Но у этого поведения есть два исключения:
NaN никогда не равен самому себе, а +0 и -0 считаются одинаковыми.Если нужно сравнение по алгоритму
SameValue, используйте Object.is():console.log(Object.is(NaN, NaN));
// true
console.log(Object.is(+0, -0));
// false
Полезно при написании собственных функций сравнения, мемоизации и библиотек, где важно отличать все значения так же, как это делают некоторые встроенные механизмы JS.
Например:
function changed(prev, next) {
return !Object.is(prev, next);
}Теперь изменение
NaN → NaN не будет считаться изменением, а +0 и -0 будут различаться.Object.is() — не замена ===, а специализированный инструмент для случаев, когда нужны точные правила сравнения JS.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12❤7👍5
Например, Stateless означает, что каждый запрос содержит всю необходимую информацию для его обработки, а Cacheable позволяет кэшировать ответы и снижать нагрузку на сервер.
На картинке — основные принципы REST: Client-Server, Stateless, Uniform Interface, Cacheable, Layered System и Code on Demand, а также примеры HTTP-методов и взаимодействия клиента с сервером.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9❤6👍6
ArrayBuffer.transfer() — переносим содержимое буфера!
При обработке файлов, изображений, аудио и сетевых данных часто приходится изменять размер бинарного буфера или передавать его содержимое в новый
Для начала создадим небольшой буфер и запишем в него четыре значения:
Теперь перенесём содержимое в новый буфер:
Метод возвращает новый
Проверим, что значения сохранились после переноса:
Новый
Во время переноса можно сразу указать новый размер:
При увеличении размера существующее содержимое сохраняется, а дополнительная область заполняется нулями. Что удобно для постепенно растущих бинарных данных: не требуется отдельно создавать буфер нужного размера и вызывать
Уменьшение выполняется тем же способом:
Если новый размер меньше исходного, в результирующем буфере остаются только байты, которые помещаются в заданную длину. Буфер
🔥
📣 JS Ready | #практика
При обработке файлов, изображений, аудио и сетевых данных часто приходится изменять размер бинарного буфера или передавать его содержимое в новый
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() полезен там, где нужно передать владение бинарными данными или изменить размер буфера без ручного копирования. При этом важно помнить, что после каждого переноса исходный буфер становится недоступен для дальнейшего использования.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤6👍4🤝3
Например,
then() используется для обработки успешного выполнения, catch() — для ошибок, а finally() позволяет выполнить код независимо от результата.На картинке собраны основные методы Promise, работа с цепочками, обработка ошибок, состояния
pending, fulfilled и rejected, а также методы для работы с несколькими Promise — all(), allSettled(), race() и any().Сохрани, чтобы было под рукой!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10👍9❤5🤝2
Шпаргалка по основным возможностям Iterator API: ручное управление итерацией, досрочное завершение и передача ошибок, создание iterable-объектов и ленивые преобразования через Iterator Helpers. Полезная база для углубления знаний об итераторах, генераторах и обработке последовательностей данных.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9👍7🤝5❤2
В этой статье:
• Узнаете, как сегодня разрабатывать программы и игры для легендарного Atari ST 1985 года;• Разберёте оптимизацию кода под Motorola 68000 с помощью C и ассемблера;• Посмотрите, как автор портировал DOOM на Atari ST и заставил его работать на железе с 8 МГц и несколькими мегабайтами памяти.Продолжай читать на Habr!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6🔥4🤝2
Например,
Promise.then() выполняется через Microtask Queue и имеет более высокий приоритет, чем setTimeout(), который попадает в Task Queue. На картинке — основные компоненты JavaScript Event Loop:
Call Stack, Web APIs, Microtask Queue, Task Queue и сам цикл событий, который управляет выполнением синхронных и асинхронных операций.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥12👍5🤝5❤1
Например,
git merge используется для объединения веток с сохранением полной истории изменений, а git rebase позволяет перенести коммиты на новую базу и сделать историю проекта более линейной.На картинке показана разница между двумя подходами работы с ветками Git: как выглядит история коммитов после
merge, где появляется отдельный merge-коммит, и после rebase, где изменения перестраиваются поверх актуальной ветки.Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11👍7❤5
Не синхронизируйте состояние — вычисляйте его!
Одна из частых причин багов — хранить одно и то же состояние в нескольких представлениях:
Рано или поздно один участок кода изменит
Если значение однозначно получается из других данных — вычисляйте его:
Тот же принцип работает для отфильтрованных списков,
Если вычисление действительно дорогое, тогда уже имеет смысл мемоизировать его — но не создавать второе изменяемое состояние:
🔥 Чем меньше состояний приходится синхронизировать вручную, тем меньше невозможных комбинаций может появиться в программе.
📣 JS Ready | #совет
Одна из частых причин багов — хранить одно и то же состояние в нескольких представлениях:
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
);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🔥7❤5
Например, Redis используется как быстрый in-memory cache для хранения часто запрашиваемых данных, сессий и временных значений, чтобы уменьшить нагрузку на базу данных. А CDN Cache позволяет отдавать статический контент ближе к пользователю, сокращая задержки и количество запросов к основному серверу.
На картинке — основные уровни кэширования в современных системах.
Сохрани, чтобы не потерять!
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤7🔥5
Используйте Proxy для создания объектов с поведением, а не просто данных!
Многие используют объекты только как хранилище:
Но иногда нужно, чтобы объект сам выполнял логику при чтении или изменении данных.
Для этого в JavaScript есть
Теперь обычное обращение к свойству запускает вашу логику:
Можно создавать объекты с автоматическими значениями:
Или автоматически валидировать изменения:
Теперь:
Такой подход используется внутри Vue 3 для реактивности, а также часто применяется в SDK, конфигурациях и слоях валидации.
🔥
📣 JS Ready | #совет
Многие используют объекты только как хранилище:
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 в объекты с собственной логикой поведения, не меняя код, который с ними работает.Please open Telegram to view this post
VIEW IN TELEGRAM
🔥13👍5🤝5❤1
Разбираем Proxy API, с помощью которого можно перехватывать и переопределять базовые операции с объектами и функциями: контролировать доступ и изменение данных, управлять видимостью и перечислением свойств, отслеживать вызовы функций и создание экземпляров. Используется для валидации, логирования, метапрограммирования и создания гибкого поведения объектов.Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥9🤝4❤2