Map.getOrInsert в ECMAScript 2026: атомарные операции для Map в Chrome 145
-
В ECMAScript 2026 появился метод Map.getOrInsert, который упрощает работу с коллекциями. Он возвращает значение по ключу или вставляет дефолтное, если ключа нет. Это решает проблему ручных проверок has/get/set, делая код короче и надежнее.
Метод уже работает в Chrome 145, что удобно для фронтенда. Зачем это нужно? В реальных проектах часто группируют данные или инициализируют структуры - без лишнего boilerplate. Теперь один вызов заменяет три операции, снижая ошибки в многопоточных сценариях.
Как работает Map.getOrInsert
Метод Map.prototype.getOrInsert(key, defaultValue) ищет ключ в Map. Если находит - возвращает значение. Если нет - вставляет пару key/defaultValue и возвращает defaultValue. Это атомарная операция по спецификации ECMAScript 2026.
Логика простая: сравнивает ключи через SameValue, канонизирует их. Не создает лишних записей, работает быстро. В отличие от ручного if (map.has(key)) { return map.get(key); } map.set(key, defaultValue); - здесь все в одном вызове. Это особенно полезно при группировке данных или кэшировании.
Пример: представь обработку логов, где по userId собираешь массив событий.
- Базовый вызов:
const map = new Map(); const events = map.getOrInsert('user123', []); events.push('login'); console.log(map.get('user123')); // ['login']- С дефолтным объектом:
const cache = new Map(); const config = cache.getOrInsert('app', { timeout: 5000 }); config.maxRetries = 3;Вот сравнение подходов:
Подход Код Плюсы Минусы Ручной if (!map.has(key)) map.set(key, []); Полный контроль 3 вызова, race conditions getOrInsert map.getOrInsert(key, []) Один вызов, атомарно Только простые дефолты ?? оператор map.set(key, map.get(key) ?? defaultValue) Коротко Не вставляет, если null/undefined валидны Важно: Метод не вызывает колбэк всегда - только проверяет наличие.
getOrInsertComputed для сложных случаев
Если дефолтное значение требует вычислений, используй Map.prototype.getOrInsertComputed(key, callback). Колбэк вызывается только если ключа нет. Это экономит ресурсы - никаких лишних операций.
Спецификация: сначала ищет ключ, если не находит - выполняет callback(key), затем вставляет и возвращает. Проверяет Map заново после колбэка на случай изменений. Идеально для дорогих инициализаций, как создание объектов или запросов.
Пример группировки данных из API:
const grouped = new Map(); for (let item of data) { const list = grouped.getOrInsertComputed(item.category, () => new Set()); list.add(item.id); }Преимущества в списке:
- Вызов колбэка только при необходимости - оптимизация производительности.
- Атомарность: даже если Map меняется в колбэке, логика устойчива.
- Поддержка WeakMap - для временных объектов без утечек памяти.
Сравнение с getOrInsert:
Метод Когда колбэк Использование getOrInsert Никогда Простые константы: [] или {} getOrInsertComputed Если ключа нет Сложные: new Proxy(), fetch() Нюанс: callback получает key как аргумент, возвращает значение.
Поддержка в Chrome 145 и других движках
В Chrome 145 метод доступен полностью, включая WeakMap-варианты. Firefox с 144, Safari с 26.2 - браузеры 2026 года на борту. Это часть proposal-upsert от TC39, вошедшего в ECMAScript 2026.
Проверить поддержку можно через CanIUse: Chrome 145+ - зеленый свет. Для полифиллов подойдет core-js, но в новых проектах не нужно. WeakMap.getOrInsert полезен для кэшей DOM-элементов - ключи удаляются с мусором.
Ключевые фичи поддержки:
- Chrome 145: Map и WeakMap методы стабильны.
- Edge 144+: частично, полная с 145.
- Polyfill: !map.has(key) ? map.set(key, callback ? callback(key) : defaultValue) : map.get(key).
Совет: Тестируй в devtools - console.log(new Map().getOrInsert(‘test’, 42)) работает сразу.
Атомарность и типичные сценарии
Map.getOrInsert гарантирует атомарность в single-threaded JS, но в Workers или с SharedArrayBuffer - осторожно с race conditions. Подходит для реактивных apps, где состояние мутирует часто.
Рассмотрим сценарии: группировка в reducers, кэш конфигов, счетчики по ключам. Заменяет паттерны вроде map.get(key) ?? (map.set(key, defaultValue), defaultValue). Код чище, меньше багов с null/undefined.
Примеры использования:
- Группировка: map.getOrInsert(userId, []).push(event).
- Кэш: cache.getOrInsert(url, () => fetch(url).then(r => r.json()));
- Счетчики: stats.getOrInsert(action, 0)++;
Ограничение: Не для mutable defaultValue вроде [] - мутации видны всем.
Новые горизонты для коллекций
Map.getOrInsert открывает двери для более declarative кода в JS. Остается внедрение в Node.js и полная кросс-браузерность. Стоит поэкспериментировать с WeakMap в garbage-collected структурах.
Дальше - интеграция с Records/Tuples из будущих ECMA, где атомарность коллекций станет стандартом. Это шаг к более robust данным в веб-приложениях, без handmade оберток.
Здравствуйте! Похоже, вас заинтересовала эта беседа, но у вас ещё нет аккаунта.
Надоело каждый раз пролистывать одни и те же посты? Зарегистрировав аккаунт, вы всегда будете возвращаться на ту же страницу, где были раньше, и сможете выбирать, получать ли уведомления о новых ответах (по электронной почте или в виде push-уведомлений). Вы также сможете сохранять закладки и ставить лайки постам, чтобы выразить свою благодарность другим участникам сообщества.
С вашими комментариями этот пост мог бы стать ещё лучше 💗
Зарегистрироваться Войти© 2024 - 2026 ExLends, Inc. Все права защищены.