<?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]]></title><description><![CDATA[<p dir="auto"><img src="/assets/uploads/files/81/01/52/1773726193903-generated_1773726163517-resized.webp" alt="Обложка: Map.getOrInsert в ECMAScript 2026: атомарные операции для упрощения кода" class=" img-fluid img-markdown" /></p>
<p dir="auto">В ECMAScript 2026 появились методы <strong>Map.getOrInsert()</strong> и <strong>Map.getOrInsertComputed()</strong>. Они упрощают работу с Map, избавляя от проверок has() и set(). Теперь код становится короче и надежнее - без лишних if.</p>
<p dir="auto">Эти методы решают проблему дублирования логики: раньше для каждого ключа приходилось проверять наличие и вставлять значение вручную. С ними один вызов возвращает значение или создает его на лету. Полезно в группировке данных, счетчиках и кэшах, где ошибки из-за null или undefined приводили к багам.</p>
<h2>Как работает Map.getOrInsert()</h2>
<p dir="auto">Метод <strong>getOrInsert(key, defaultValue)</strong> ищет ключ в Map. Если находит - возвращает значение. Если нет - вставляет пару key/defaultValue и возвращает defaultValue. Это атомарная операция: никаких промежуточных проверок.</p>
<p dir="auto">Пример: группировка элементов по ключу. Раньше писали if (map.has(key)) { map.get(key).push(value); } else { map.set(key, [value]); }. Теперь достаточно map.getOrInsert(key, []).push(value). Код короче в три раза, и работает без ошибок даже с null-значениями.</p>
<p dir="auto">Логика простая, как в спецификации: метод канонизирует ключ, ищет совпадение по SameValue, вставляет если нужно. Поддерживает любые типы ключей - объекты сравниваются по ссылке.</p>
<ul>
<li><strong>Преимущества в производительности</strong>: Одна операция вместо has + get + set. Движки JS легко оптимизируют такой паттерн.</li>
<li><strong>Безопасность с null/undefined</strong>: В отличие от map.get(key) ?? defaultValue, getOrInsert всегда вставляет именно defaultValue.</li>
<li><strong>Применение в циклах</strong>: Идеально для for…of по данным, где строят словари на лету.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Традиционный подход</th>
<th>С getOrInsert</th>
</tr>
</thead>
<tbody>
<tr>
<td>if (!map.has(key)) map.set(key, []); map.get(key).push(value);</td>
<td>map.getOrInsert(key, []).push(value);</td>
</tr>
<tr>
<td>3 вызова Map</td>
<td>1 вызов</td>
</tr>
<tr>
<td>Риск race condition в async</td>
<td>Атомарно</td>
</tr>
</tbody>
</table>
<h2>Map.getOrInsertComputed() для ленивых вычислений</h2>
<p dir="auto">Этот метод похож, но defaultValue вычисляется функцией: <strong>getOrInsertComputed(key, callback)</strong>. Callback(key) вызывается только если ключа нет. Экономит ресурсы на дорогих операциях.</p>
<p dir="auto">Представьте создание объектов или запросы к API по умолчанию. С getOrInsert defaultValue создается всегда, даже зря. Computed вернет существующее значение без вызова callback. Пример: map.getOrInsertComputed(key, () =&gt; new ExpensiveObject(key)).</p>
<p dir="auto">В спецификации: проверка IsCallable(callback), вызов только при отсутствии ключа, обновление если Map изменился во время callback. Плюс проверка после - на случай мутаций.</p>
<ul>
<li><strong>Экономия</strong>: Callback не вызывается, если ключ есть. Логгируйте внутри - увидите разницу.</li>
<li><strong>Гибкость</strong>: Callback получает key, может зависеть от него (default for ${key}).</li>
<li><strong>TypeError</strong>: Кидает, если callback не функция - защита от ошибок.</li>
</ul>
<pre><code class="language-javascript">const defaultCreator = (key) =&gt; `default for ${key}`;
map.getOrInsertComputed('baz', defaultCreator); // Создает только раз
</code></pre>
<h2>Примеры в реальных сценариях</h2>
<p dir="auto">Счетчики - классика. Раньше: 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). Читаемо и оптимизируемо.</p>
<p dir="auto">Группировка данных из массива: for (let [key, value] of data) { grouped.getOrInsert(key, []).push(value); }. Работает для строк, объектов, массивов. Для WeakMap то же самое - gc-friendly.</p>
<p dir="auto">Подсчет символов: const map = new Map(); for (const char of string) { const obj = map.getOrInsert(char, {char, count: 0}); obj.count++; }. С computed - объект создается лениво.</p>
<ul>
<li><strong>Кэш с вычислением</strong>: map.getOrInsertComputed(key, () =&gt; computeExpensive(key));</li>
<li><strong>Словари в реакте/Vue</strong>: Хранить компоненты по id без проверок.</li>
<li><strong>WeakMap для приватных данных</strong>: getOrInsert в классах для метаданных.</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Сценарий</th>
<th>До ECMAScript 2026</th>
<th>После</th>
</tr>
</thead>
<tbody>
<tr>
<td>Счетчик</td>
<td>if/else + get/set</td>
<td>getOrInsert(key, 0) + 1</td>
</tr>
<tr>
<td>Группировка</td>
<td>has/get/set</td>
<td>getOrInsert(key, [])</td>
</tr>
<tr>
<td>Объект по умолчанию</td>
<td>?? оператор (риски)</td>
<td>getOrInsertComputed</td>
</tr>
</tbody>
</table>
<h2>Что дает ECMAScript 2026 Map</h2>
<p dir="auto">Методы упрощают код на 50-70% в типичных случаях с Map. Поддержка в Firefox 144+, Chrome 145+, Safari 26.2 - уже можно тестировать. WeakMap версии идентичны.</p>
<p dir="auto">Осталось место для оптимизаций в многопоточности, но для single-thread JS это шаг вперед. Думайте о миграции шаблонов - has/get/set уйдут в прошлое.</p>
]]></description><link>https://forum.exlends.ru/topic/1679/map.getorinsert-v-ecmascript-2026-atomarnye-operacii-dlya-map</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 03:39:23 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/1679.rss" rel="self" type="application/rss+xml"/><pubDate>Tue, 17 Mar 2026 05:43:14 GMT</pubDate><ttl>60</ttl></channel></rss>