Map.getOrInsert в ECMAScript 2026: атомарные операции для Map
-
В ECMAScript 2026 появился метод Map.getOrInsert. Он возвращает значение по ключу или вставляет дефолтное, если ключа нет. Это упрощает работу с коллекциями и избавляет от boilerplate-кода с проверками has и set.
Зачем это нужно? В реальных проектах часто приходится группировать данные или инициализировать структуры. Без getOrInsert приходится писать if-else, что увеличивает ошибки и усложняет код. Новый метод делает всё атомарно - одной строкой. Плюс есть версия getOrInsertComputed для ленивых вычислений.
Как работает Map.getOrInsert
Метод map.getOrInsert(key, defaultValue) ищет ключ в Map. Если находит - возвращает значение. Нет ключа - вставляет пару [key, defaultValue] и возвращает defaultValue. Всё происходит за один проход, без лишних вызовов has или get.
Это эквивалентно коду:
if (map.has(key)) { return map.get(key); } map.set(key, defaultValue); return defaultValue;Но короче и надёжнее, особенно если значения могут быть null или undefined. Пример: группировка данных по ключам. Проходим массив, для каждого ключа получаем массив или создаём новый - и пушим значения.
Вот базовый синтаксис и поведение:
- key: любой объект, сравнивается по ссылке.
- defaultValue: вставляется только при отсутствии ключа.
- Возвращает всегда значение по ключу после операции.
Сценарий Код до Код с getOrInsert Простая инициализация if (!map.has(k)) map.set(k, []); map.get(k).push(v); map.getOrInsert(k, []).push(v); С объектом по умолчанию if (!map.has(k)) map.set(k, {}); map.getOrInsert(k, {}); С null/undefined map.set(k, map.get(k) ?? def); map.getOrInsert(k, def); Отличия getOrInsert и getOrInsertComputed
getOrInsert подходит, когда дефолт прост - число, строка, пустой массив. defaultValue вычисляется всегда при вызове, даже если ключ есть. Но если создание дефолта дорогое - объект с вычислениями или запрос - лучше getOrInsertComputed.
Этот метод принимает колбэк: map.getOrInsertComputed(key, () => expensiveValue). Колбэк вызывается только если ключа нет. После вставки возвращает значение. Идеально для счётчиков или сложных структур, где не хочешь тратить ресурсы зря. В спецификации учтено, что Map может измениться во время колбэка - метод перепроверяет.
Преимущества в списке:
- Ленивое вычисление: колбэк не вызывается при наличии ключа.
- Атомарность: вставка без гонок в однопотоке.
- Поддержка в WeakMap для тех же сценариев.
Пример подсчёта символов:
const map = new Map(); for (const char of "hello") { const counter = map.getOrInsertComputed(char, () => ({char, count: 0})); counter.count++; }Реальные примеры использования
Представь группировку логов по пользователям. Для каждого ID пользователя нужен массив событий. Без getOrInsert: проверка has, get, push или set. С методом - чистая строка. Ещё кейс: кэш вычислений, где дефолт - результат функции.
В многопоточных окружениях (Web Workers) атомарность помогает избежать дублей. Хотя JS однопоточный, в асинхронных сценариях это спасает от race conditions при параллельных вставках. Плюс WeakMap.getOrInsert для объектов без утечек памяти.
Популярные паттерны:
- Группировка: map.getOrInsert(key, []).push(value);
- Счётчики: map.getOrInsert(key, 0) + 1;
- Объекты: map.getOrInsertComputed(key, () => computeObject(key));
Паттерн До ECMAScript 2026 С 2026 Группировка массивов if (!m.has(k)) m.set(k,[]); m.get(k).push(v); m.getOrInsert(k,[]).push(v); Инициализация счётчика m.set(k, (m.get(k) 0) +1); m.getOrInsert(k,0) +1; Кэш с вычислением if(!m.has(k)) m.set(k, heavyFn(k)); m.getOrInsertComputed(k, () => heavyFn(k)); Что меняется в проектах с ECMAScript 2026
Теперь код чище, меньше ошибок от забытых проверок. Браузеры и Node.js поддержат это нативно - забудь полифилы из core-js. Для TypeScript типы уже готовы. Нюанс: ключи сравниваются SameValue, как в Map - по ссылке для объектов.
Методы усиливают Map как основной инструмент для словарей. Раньше полагались на lodash или самописные хелперы. Теперь стандарт. Стоит обновить гайдлайны: предпочитай getOrInsert простым случаям, Computed - дорогим.
Останутся вопросы по WeakMap-версиям или интеграции с Proxy. Там похожая логика, но для слабых ссылок - тема для разборов.
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.