<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Map.getOrInsert в ECMAScript 2026: атомарные операции для Map в Chrome 145]]></title><description><![CDATA[<p dir="auto">В ECMAScript 2026 появились методы <strong>Map.getOrInsert</strong> и <strong>Map.getOrInsertComputed</strong>. Они упрощают работу с Map, позволяя атомарно получать значение по ключу или вставлять новое, если ключа нет. Это решает проблему шаблонных проверок has/get/set, которые часто приводят к race conditions в многопоточных сценариях или асинхронном коде.</p>
<p dir="auto">Теперь не нужно писать if (map.has(key)) { return map.get(key); } else { map.set(key, value); return value; }. Один вызов метода делает всё сразу. Полезно для кэшей, группировки данных и конфигураций, где важна производительность и безопасность. В Chrome 145 эти методы уже работают нативно.</p>
<h2>Что такое Map.getOrInsert и зачем оно нужно</h2>
<p dir="auto">Метод <strong>Map.prototype.getOrInsert(key, value)</strong> проверяет наличие ключа в Map. Если ключ есть, возвращает связанное значение. Если нет - вставляет пару key/value и возвращает value. Всё происходит атомарно, без промежуточных проверок, что минимизирует ошибки в конкурентном доступе.</p>
<p dir="auto">Раньше разработчики писали boilerplate-код: проверяли has, потом get или set. Это не только verbose, но и рискованно - между has и set другой поток мог изменить Map. Новый метод устраняет эту проблему одним вызовом. Представьте группировку данных: вместо условий просто вызываете getOrInsert(key, []). В Chrome 145 это уже стандарт.</p>
<p dir="auto">Вот типичные сценарии использования:</p>
<ul>
<li><strong>Группировка элементов</strong>: let grouped = new Map(); grouped.getOrInsert(key, []).push(item);</li>
<li><strong>Кэширование</strong>: const cache = new Map(); result = cache.getOrInsert(key, computeExpensiveValue());</li>
<li><strong>Конфигурации</strong>: config.getOrInsert(‘theme’, ‘light’);</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Сценарий</th>
<th>Старый код</th>
<th>Новый код с getOrInsert</th>
</tr>
</thead>
<tbody>
<tr>
<td>Группировка</td>
<td>if (!grouped.has(key)) grouped.set(key, []); grouped.get(key).push(item);</td>
<td>grouped.getOrInsert(key, []).push(item);</td>
</tr>
<tr>
<td>Кэш</td>
<td>if (!cache.has(key)) cache.set(key, compute()); return cache.get(key);</td>
<td>cache.getOrInsert(key, compute());</td>
</tr>
<tr>
<td>Дефолт</td>
<td>val = map.get(key) ?? defaultValue; map.set(key, val);</td>
<td>map.getOrInsert(key, defaultValue);</td>
</tr>
</tbody>
</table>
<p dir="auto"><em>Важно</em>: Метод бросает TypeError, если Map невалиден. Работает с любыми ключами - примитивами и объектами.</p>
<h2>Map.getOrInsertComputed: ленивые вычисления</h2>
<p dir="auto"><strong>Map.prototype.getOrInsertComputed(key, callback)</strong> похож на getOrInsert, но значение вычисляется функцией callback только если ключа нет. Это идеально, когда дефолт - дорогое вычисление, типа создания объекта или API-запроса.</p>
<p dir="auto">Без этого приходилось проверять has, а потом в callback всегда вызывать compute - даже зря. Теперь callback вызывается лениво: только при отсутствии ключа. Производительность растёт, особенно в циклах. В спецификации ECMAScript 2026 это четко прописано с шагами: проверка MapData, поиск ключа, вызов closure если нужно.</p>
<p dir="auto">Примеры реального кода:</p>
<ul>
<li>Группировка с пустым массивом: grouped.getOrInsertComputed(key, () =&gt; []).push(item);</li>
<li>Кэш с функцией: cache.getOrInsertComputed(key, () =&gt; fetchData(key));</li>
<li>Объект-конфиг: map.getOrInsertComputed(key, () =&gt; new Options());</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Метод</th>
<th>Аргументы</th>
<th>Когда вызывается callback</th>
<th>Пример</th>
</tr>
</thead>
<tbody>
<tr>
<td>getOrInsert</td>
<td>key, value</td>
<td>Никогда (value статично)</td>
<td>getOrInsert(‘user’, {})</td>
</tr>
<tr>
<td>getOrInsertComputed</td>
<td>key, () =&gt; value</td>
<td>Только если !has(key)</td>
<td>getOrInsertComputed(‘user’, () =&gt; fetchUser())</td>
</tr>
</tbody>
</table>
<p dir="auto"><strong>Преимущества</strong>: Избегает ненужных вычислений. <em>Нюанс</em>: callback не принимает аргументы, захватывает контекст через closure.</p>
<h2>Атомарность и поддержка в Chrome 145</h2>
<p dir="auto">Атомарность - ключевой плюс: метод гарантирует, что get и insert не прервутся. В спецификации это internal slot &lsqb;&lsqb;MapData&rsqb;&rsqb; с циклом поиска и вставкой без race conditions. Подходит для SharedArrayBuffer или Worker’ов.</p>
<p dir="auto">В Chrome 145 методы landed: полная поддержка без флагов. Firefox с 144, Safari с 26.2. Это часть ECMAScript 2026, финализированной в декабре 2025. Старые версии требуют полифиллов из proposal-upsert.</p>
<p dir="auto">Поддержка браузеров:</p>
<ul>
<li>Chrome 145+: Полная</li>
<li>Firefox 144+: Полная</li>
<li>Safari 26.2+: Полная</li>
<li>Edge 145+: Полная</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Браузер</th>
<th>Версия поддержки</th>
<th>Статус</th>
</tr>
</thead>
<tbody>
<tr>
<td>Chrome</td>
<td>145</td>
<td><img src="https://forum.exlends.ru/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=a1e94250dac" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
</tr>
<tr>
<td>Firefox</td>
<td>144</td>
<td><img src="https://forum.exlends.ru/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=a1e94250dac" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
</tr>
<tr>
<td>Safari</td>
<td>26.2</td>
<td><img src="https://forum.exlends.ru/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=a1e94250dac" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
</tr>
<tr>
<td>Edge</td>
<td>145</td>
<td><img src="https://forum.exlends.ru/assets/plugins/nodebb-plugin-emoji/emoji/android/2705.png?v=a1e94250dac" class="not-responsive emoji emoji-android emoji--white_check_mark" style="height:23px;width:auto;vertical-align:middle" title="✅" alt="✅" /></td>
</tr>
</tbody>
</table>
<p dir="auto"><em>Совет</em>: Проверяйте caniuse для продакшена. Для WeakMap аналогичные методы.</p>
<h2>Перспективы upsert в JavaScript-экосистеме</h2>
<p dir="auto">Методы upsert меняют паттерны: меньше ошибок, чище код. Но остаётся вопрос с полифиллами для старых браузеров и интеграцией в фреймворки типа React/Vue. TC39 продолжает работу над keyed collections.</p>
<p dir="auto">Дальше ждём оптимизаций для больших Map и возможно расширений на Set. Это шаг к более выразительному API без лямбда-монстров. Стоит протестировать в реальных проектах - разница в читаемости огромна.</p>
]]></description><link>https://forum.exlends.ru/topic/1029/map.getorinsert-v-ecmascript-2026-atomarnye-operacii-dlya-map-v-chrome-145</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 04:05:56 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/1029.rss" rel="self" type="application/rss+xml"/><pubDate>Wed, 04 Mar 2026 06:22:17 GMT</pubDate><ttl>60</ttl></channel></rss>