ECMAScript 2026 — одно из крупнейших обновлений JavaScript за последние годы. От автоматического управления ресурсами до pattern matching — всё, что нужно знать, с реальными примерами кода.
Каждый год в июне TC39 — технический комитет, стандартизирующий JavaScript — публикует новую редакцию спецификации ECMAScript. ES2026 (ECMAScript 2026) — одно из самых значительных обновлений за последние годы, включающее возможности, которых JavaScript-разработчики ждали десятилетиями.
В этом году спецификация включает практические улучшения: автоматическое освобождение
ресурсов с using, точные вычисления с Math.sumPrecise(),
надёжную проверку типов ошибок с Error.isError() и несколько предложений
на Stage 3 — Pattern Matching и Pipeline Operator — которые близки к завершению. А
долгожданный Temporal API — полная замена печально известного объекта Date —
достиг Stage 4 и войдёт в ES2027.
using и await using
Stage 4
Самая значимая функция, входящая в ES2026 — explicit resource management.
Если вы хоть раз писали try { ... } finally { resource.close(); }, эта
возможность устраняет этот шаблонный код полностью.
using
Ключевое слово using объявляет переменную блочной области видимости, чей
метод Symbol.dispose автоматически вызывается при выходе из области —
аналогично Python with или C# using:
// До ES2026 — ручная очистка
function readConfig(path) {
const file = fs.openSync(path, 'r');
try {
return JSON.parse(fs.readFileSync(file, 'utf-8'));
} finally {
fs.closeSync(file);
}
}
// С ES2026 — автоматическая очистка
function readConfig(path) {
using file = fs.openSync(path, 'r');
return JSON.parse(fs.readFileSync(file, 'utf-8'));
// file автоматически закрывается при выходе из области
}
await using
Для асинхронных ресурсов (подключения к БД, файловые потоки) используйте
await using с Symbol.asyncDispose:
class DatabaseConnection {
async [Symbol.asyncDispose]() {
await this.close();
console.log('Соединение закрыто');
}
async query(sql) { /* … */ }
}
async function getUser(userId) {
await using db = new DatabaseConnection(config);
return db.query(`SELECT * FROM users WHERE id = ${userId}`);
// db.close() вызывается автоматически
}
Утечки ресурсов — одни из самых частых багов в production-приложениях. Файловые
дескрипторы, соединения с БД и сетевые сокеты, которые не были корректно закрыты,
вызывают утечки памяти и истощение пула соединений. using устраняет
целую категорию багов, делая освобождение ресурсов автоматическим и детерминированным.
Stage 4 Каждый JavaScript-разработчик сталкивался с quirks арифметики с плавающей точкой:
0.1 + 0.2; // 0.30000000000000004 (не 0.3!)
Math.sumPrecise() использует компенсированный алгоритм суммирования
(Kahan-Babuška-Neumaier), который значительно уменьшает ошибки накопления при сложении
массивов чисел с плавающей точкой:
const prices = [0.1, 0.2, 0.3, 0.4];
// Традиционный подход — накопление ошибок
const naiveSum = prices.reduce((a, b) => a + b, 0);
// 0.1 + 0.2 + 0.3 + 0.4 = 1.0000000000000002
// ES2026 — точное суммирование
const preciseSum = Math.sumPrecise(prices);
// 0.0 + 0.1 + 0.2 + 0.3 + 0.4 = 1.0 (точно!)
Это важно для финансовых расчётов, статистических операций и научных вычислений.
Math.sumPrecise() принимает любой итерируемый объект и возвращает
0 для пустых коллекций.
Stage 4
Проверка, является ли значение экземпляром Error, была удивительно
сложной из-за кросс-реалмных проблем (ошибки из iframe или worker не проходят
instanceof Error):
// Старый подход — ненадёжный
try {
await riskyOperation();
} catch (err) {
if (err instanceof Error) { // не работает между realm!
console.error(err.message);
}
// Запасной вариант: duck-typing
if (err && typeof err.message === 'string') {
console.error(err.message);
}
}
// ES2026 — надёжный
try {
await riskyOperation();
} catch (err) {
if (Error.isError(err)) {
console.error(err.message);
console.error(err.stack);
}
}
Error.isError() работает надёжно в кросс-реалмных контекстах (iframe,
workers, VM) и корректно определяет нативные экземпляры Error, включая
подклассы TypeError, RangeError и SyntaxError.
Stage 3
Pattern Matching — возможно, самая ожидаемая функция JavaScript за многие годы. Она
вводит выражение match, позволяющее деструктурировать и проверять значения
по шаблонам декларативно — подобно match в Rust или Haskell:
// До — вложенные if-else или switch
function getShapeArea(shape) {
if (shape.type === 'circle') {
return Math.PI * shape.radius ** 2;
} else if (shape.type === 'rectangle') {
return shape.width * shape.height;
} else if (shape.type === 'triangle') {
return (shape.base * shape.height) / 2;
}
throw new Error('Unknown shape');
}
// С Pattern Matching
function getShapeArea(shape) {
return match (shape) {
{ type: 'circle', radius } => Math.PI * radius ** 2,
{ type: 'rectangle', width, height } => width * height,
{ type: 'triangle', base, height } => (base * height) / 2,
_ => throw new Error('Unknown shape'),
};
}
_x when x > 100 | false | null|> — читаемая композиция функцийStage 3 Pipeline Operator вводит чистый синтаксис слева направо для цепочек вызовов функций. Вместо глубоко вложенных выражений, которые читаются изнутри наружу:
// До — глубоко вложено, сложно читать
const result = formatCurrency(
applyDiscount(
calculateTotal(
getCartItems(userId)
),
promoCode
),
'USD'
);
// С Pipeline Operator — читается сверху вниз
const result = getCartItems(userId)
|> calculateTotal(%)
|> applyDiscount(%, promoCode)
|> formatCurrency(%, 'USD');
Stage 3
import defer откладывает выполнение модуля до первого использования,
улучшая производительность запуска:
// Обычный импорт — выполняется сразу
import { heavyLibrary } from './heavy-library.js';
// Отложенный импорт — выполняется при первом использовании
import defer { markdownParser } from './markdown-parser.js';
function renderPage(content) {
// Модуль markdown-parser загружается только здесь,
// при первом вызове renderPage
return markdownParser.parse(content);
}
Stage 4
Войдёт в ES2027
Хотя Temporal не успел в ES2026, это самое значительное добавление в JavaScript за
десятилетие. Temporal исправляет всё, что сломано в Date:
// Date — болезненно и с ошибками
const d = new Date(2026, 4, 16); // 16 мая — но месяцы с нуля!
d.setMonth(5); // Мутирует оригинал — сюрприз!
// Temporal — явно и правильно
const date = Temporal.PlainDate.from({ year: 2026, month: 5, day: 16 });
// => 2026-05-16 (чётко, без путаницы с индексами)
const zoned = Temporal.ZonedDateTime.from({
timeZone: 'Europe/Minsk',
year: 2026,
month: 5,
day: 16,
hour: 10,
minute: 0,
});
// => 2026-05-16T10:00:00+03:00[Europe/Minsk]
// Иммутабельные операции
const nextMonth = date.add({ months: 1 });
// date не изменился — nextMonth новый экземпляр
| Функция | Стадия | Версия ES | Статус |
|---|---|---|---|
Explicit Resource Mgmt (using) |
Stage 4 | ES2026 | Node 24+, Chrome 126+, Babel |
| Math.sumPrecise() | Stage 4 | ES2026 | Node 24+, Chrome 127+, полифилл |
| Error.isError() | Stage 4 | ES2026 | Node 24+, полифилл |
| Pattern Matching | Stage 3 | ES2027 (ожидается) | Babel plugin, V8 в работе |
Pipeline Operator (|>) |
Stage 3 | ES2027 (ожидается) | Babel plugin, консенсус TC39 |
| Import Defer | Stage 3 | ES2027 (ожидается) | Babel plugin, поддержка бандлеров |
| Temporal API | Stage 4 | ES2027 | Полифилл, Node 24+ experimental |
Возможности ES2026 доступны уже сегодня:
Используйте Node.js 24+ для using/await using и
Math.sumPrecise() без транспиляции. Для браузеров добавьте Babel-пресет:
npm install --save-dev @babel/preset-env @babel/plugin-proposal-explicit-resource-management
// babel.config.js
module.exports = {
presets: [
['@babel/preset-env', {
targets: { esmodules: true },
}],
],
plugins: [
'@babel/plugin-proposal-explicit-resource-management',
],
};
Начните с Error.isError() и Math.sumPrecise() — они не сломают
существующий код. Затем инкрементально внедряйте using в ресурсоёмких
модулях. Pattern Matching и Pipeline Operator оставьте для нового кода.
ES2026 приносит значительные изменения в JavaScript. Если вы модернизируете существующий код, начинаете новый проект или нуждаетесь в консультации по инструментам — я могу помочь.
Я — senior full-stack разработчик с 20+ годами опыта в JavaScript, React, Node.js и современной веб-разработке. Работаю в Минске и по всему миру. Свяжитесь со мной для обсуждения вашего проекта.
Для более широкого взгляда на экосистему JavaScript также прочитайте моё сравнение React vs Vue.js vs Angular, анализ атаки на npm 2026 и руководство по Chrome Prompt API для браузерной AI-интеграции.
Расскажите о задаче — предложу оптимальное решение и предварительную оценку. Бесплатно.