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

В ECMAScript 2026 появились методы Map.getOrInsert() и Map.getOrInsertComputed(). Они упрощают работу с Map, избавляя от проверок has() и set(). Теперь код становится короче и надежнее - без лишних if.
Эти методы решают проблему дублирования логики: раньше для каждого ключа приходилось проверять наличие и вставлять значение вручную. С ними один вызов возвращает значение или создает его на лету. Полезно в группировке данных, счетчиках и кэшах, где ошибки из-за null или undefined приводили к багам.
Как работает Map.getOrInsert()
Метод getOrInsert(key, defaultValue) ищет ключ в Map. Если находит - возвращает значение. Если нет - вставляет пару key/defaultValue и возвращает defaultValue. Это атомарная операция: никаких промежуточных проверок.
Пример: группировка элементов по ключу. Раньше писали if (map.has(key)) { map.get(key).push(value); } else { map.set(key, [value]); }. Теперь достаточно map.getOrInsert(key, []).push(value). Код короче в три раза, и работает без ошибок даже с null-значениями.
Логика простая, как в спецификации: метод канонизирует ключ, ищет совпадение по SameValue, вставляет если нужно. Поддерживает любые типы ключей - объекты сравниваются по ссылке.
- Преимущества в производительности: Одна операция вместо has + get + set. Движки JS легко оптимизируют такой паттерн.
- Безопасность с null/undefined: В отличие от map.get(key) ?? defaultValue, getOrInsert всегда вставляет именно defaultValue.
- Применение в циклах: Идеально для for…of по данным, где строят словари на лету.
Традиционный подход С getOrInsert if (!map.has(key)) map.set(key, []); map.get(key).push(value); map.getOrInsert(key, []).push(value); 3 вызова Map 1 вызов Риск race condition в async Атомарно Map.getOrInsertComputed() для ленивых вычислений
Этот метод похож, но defaultValue вычисляется функцией: getOrInsertComputed(key, callback). Callback(key) вызывается только если ключа нет. Экономит ресурсы на дорогих операциях.
Представьте создание объектов или запросы к API по умолчанию. С getOrInsert defaultValue создается всегда, даже зря. Computed вернет существующее значение без вызова callback. Пример: map.getOrInsertComputed(key, () => new ExpensiveObject(key)).
В спецификации: проверка IsCallable(callback), вызов только при отсутствии ключа, обновление если Map изменился во время callback. Плюс проверка после - на случай мутаций.
- Экономия: Callback не вызывается, если ключ есть. Логгируйте внутри - увидите разницу.
- Гибкость: Callback получает key, может зависеть от него (default for ${key}).
- TypeError: Кидает, если callback не функция - защита от ошибок.
const defaultCreator = (key) => `default for ${key}`; map.getOrInsertComputed('baz', defaultCreator); // Создает только разПримеры в реальных сценариях
Счетчики - классика. Раньше: if (counts.has(key)) counts.set(key, counts.get(key) + 1); else counts.set(key, 1). С getOrInsert: counts.set(key, counts.getOrInsert(key, 0) + 1). Читаемо и оптимизируемо.
Группировка данных из массива: for (let [key, value] of data) { grouped.getOrInsert(key, []).push(value); }. Работает для строк, объектов, массивов. Для WeakMap то же самое - gc-friendly.
Подсчет символов: const map = new Map(); for (const char of string) { const obj = map.getOrInsert(char, {char, count: 0}); obj.count++; }. С computed - объект создается лениво.
- Кэш с вычислением: map.getOrInsertComputed(key, () => computeExpensive(key));
- Словари в реакте/Vue: Хранить компоненты по id без проверок.
- WeakMap для приватных данных: getOrInsert в классах для метаданных.
Сценарий До ECMAScript 2026 После Счетчик if/else + get/set getOrInsert(key, 0) + 1 Группировка has/get/set getOrInsert(key, []) Объект по умолчанию ?? оператор (риски) getOrInsertComputed Что дает ECMAScript 2026 Map
Методы упрощают код на 50-70% в типичных случаях с Map. Поддержка в Firefox 144+, Chrome 145+, Safari 26.2 - уже можно тестировать. WeakMap версии идентичны.
Осталось место для оптимизаций в многопоточности, но для single-thread JS это шаг вперед. Думайте о миграции шаблонов - has/get/set уйдут в прошлое.
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.