Map.getOrInsert в ECMAScript 2026: атомарные операции для Map
-

В ECMAScript 2026 появились методы Map.getOrInsert и Map.getOrInsertComputed. Они упрощают работу с Map, позволяя получать значение по ключу или вставлять дефолтное, если ключа нет. Это решает проблему ручных проверок has/get/set, которые часто приводят к ошибкам в многопоточной среде или при частых обращениях.
Такие атомарные операции ускоряют код и делают его чище. Особенно полезно для группировки данных, кэширования или инициализации структур. Забудьте о boilerplate - теперь всё в одном вызове.
Как работает Map.getOrInsert
Метод getOrInsert(key, defaultValue) возвращает значение по ключу, если оно есть. Если ключа нет, вставляет defaultValue и возвращает его. Это атомарная операция - никаких race conditions между проверкой и вставкой.
Раньше приходилось писать if (map.has(key)) return map.get(key); else map.set(key, defaultValue); return defaultValue;. Теперь всё в одном методе. Логика простая: поиск, вставка если нужно, возврат. Поддерживает любые ключи, сравнение по SameValue.
Представьте группировку данных по ключам. Вместо проверок используем map.getOrInsert(key, []).push(value). Код короче и надёжнее. В спецификации ECMAScript 2026 это описано в разделе 24.1.3.7.
- Преимущества getOrInsert:
- Атомарность: вставка без промежуточных проверок.
- Простота: заменяет 3-4 строки на одну.
- Универсальность: работает с примитивными и объектными ключами.
Традиционный подход getOrInsert if (!map.has(key)) map.set(key, []); map.get(key).push(value); map.getOrInsert(key, []).push(value); Риск race condition в асинхронном коде Атомарно, без риска Длинный код Одна строка Map.getOrInsertComputed для ленивых вычислений
getOrInsertComputed(key, callback) похож на getOrInsert, но дефолтное значение вычисляется только если нужно. Callback получает key и возвращает значение. Идеально, когда создание дефолта дорогое - например, объект или массив с инициализацией.
В отличие от getOrInsert, здесь callback вызывается лениво. Если ключ есть, ничего не считается. В спецификации шаги: проверка callable, поиск, вызов callback(key), вставка или обновление. Если во время callback Map изменился, обновляет существующую запись.
Пример: группировка с дорогим дефолтом. map.getOrInsertComputed(key, () => new Set()).add(value). Экономит ресурсы, если ключ уже был. Логирует создание только при необходимости.
- Когда использовать getOrInsertComputed:
- Дефолт требует вычислений (объекты, массивы).
- Частые вызовы с существующими ключами.
- Избежать ненужных аллокаций.
Метод Вычисление дефолта Пример getOrInsert Всегда map.getOrInsert(key, expensiveObject) getOrInsertComputed Только если нужно map.getOrInsertComputed(key, k => expensiveObject(k)) Реальные сценарии и сравнение подходов
В повседневной разработке Map.getOrInsert упрощает кэш, группировку, инициализацию. Для фронтенда - хранение состояний по ID. На бэкенде - агрегация логов или метрик. Атомарность важна в Web Workers или Node.js с кластерами.
Сравним с WeakMap: там тоже есть getOrInsert, но ключи - только объекты, сборка мусора автоматическая. Полезно для приватных данных. Старые паттерны вроде map.get(key) ?? default не атомарны и ломаются на null/undefined.
Пример группировки:
const data = [['a', 1], ['b', 2], ['a', 3]]; const grouped = new Map(); for (let [key, value] of data) { grouped.getOrInsert(key, []).push(value); } console.log(grouped.get('a')); // [1, 3]Код короче, без if-else.
- Сценарии применения:
- Группировка массивов: getOrInsert(key, []).
- Кэш с дефолтом: getOrInsertComputed(key, () => compute(key)).
- Словари с инициализацией: объекты по умолчанию.
Почему это шаг вперёд в ECMAScript 2026
Эти методы закрывают пробелы в API Map, делая его конкурентным коллекциям других языков. Proposal-upsert от TC39 прошёл все стадии. Поддержка в Chrome 145+, Safari 26.2. Код становится declarative и менее подверженным ошибкам.
Остаётся пространство для WeakMap-вариантов в продакшене и оптимизаций под V8. Стоит протестировать производительность на больших Map - атомарность может дать прирост в многопоточности.
- Преимущества getOrInsert:
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.