<?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">В ECMAScript 2026 появился метод <strong>Map.getOrInsert</strong>. Он возвращает значение по ключу или вставляет дефолтное, если ключа нет. Это упрощает работу с коллекциями и избавляет от boilerplate-кода с проверками has и set.</p>
<p dir="auto">Зачем это нужно? В реальных проектах часто приходится группировать данные или инициализировать структуры. Без getOrInsert приходится писать if-else, что увеличивает ошибки и усложняет код. Новый метод делает всё атомарно - одной строкой. Плюс есть версия getOrInsertComputed для ленивых вычислений.</p>
<h2>Как работает Map.getOrInsert</h2>
<p dir="auto">Метод map.getOrInsert(key, defaultValue) ищет ключ в Map. Если находит - возвращает значение. Нет ключа - вставляет пару [key, defaultValue] и возвращает defaultValue. Всё происходит за один проход, без лишних вызовов has или get.</p>
<p dir="auto">Это эквивалентно коду:</p>
<pre><code class="language-javascript">if (map.has(key)) {
  return map.get(key);
}
map.set(key, defaultValue);
return defaultValue;
</code></pre>
<p dir="auto">Но короче и надёжнее, особенно если значения могут быть null или undefined. Пример: группировка данных по ключам. Проходим массив, для каждого ключа получаем массив или создаём новый - и пушим значения.</p>
<p dir="auto">Вот базовый синтаксис и поведение:</p>
<ul>
<li><strong>key</strong>: любой объект, сравнивается по ссылке.</li>
<li><strong>defaultValue</strong>: вставляется только при отсутствии ключа.</li>
<li>Возвращает всегда значение по ключу после операции.</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 (!map.has(k)) map.set(k, []); map.get(k).push(v);</td>
<td>map.getOrInsert(k, []).push(v);</td>
</tr>
<tr>
<td>С объектом по умолчанию</td>
<td>if (!map.has(k)) map.set(k, {});</td>
<td>map.getOrInsert(k, {});</td>
</tr>
<tr>
<td>С null/undefined</td>
<td>map.set(k, map.get(k) ?? def);</td>
<td>map.getOrInsert(k, def);</td>
</tr>
</tbody>
</table>
<h2>Отличия getOrInsert и getOrInsertComputed</h2>
<p dir="auto">getOrInsert подходит, когда дефолт прост - число, строка, пустой массив. defaultValue вычисляется всегда при вызове, даже если ключ есть. Но если создание дефолта дорогое - объект с вычислениями или запрос - лучше getOrInsertComputed.</p>
<p dir="auto">Этот метод принимает колбэк: map.getOrInsertComputed(key, () =&gt; expensiveValue). Колбэк вызывается <em>только</em> если ключа нет. После вставки возвращает значение. Идеально для счётчиков или сложных структур, где не хочешь тратить ресурсы зря. В спецификации учтено, что Map может измениться во время колбэка - метод перепроверяет.</p>
<p dir="auto">Преимущества в списке:</p>
<ul>
<li><em>Ленивое вычисление</em>: колбэк не вызывается при наличии ключа.</li>
<li><em>Атомарность</em>: вставка без гонок в однопотоке.</li>
<li>Поддержка в WeakMap для тех же сценариев.</li>
</ul>
<p dir="auto">Пример подсчёта символов:</p>
<pre><code class="language-javascript">const map = new Map();
for (const char of "hello") {
  const counter = map.getOrInsertComputed(char, () =&gt; ({char, count: 0}));
  counter.count++;
}
</code></pre>
<h2>Реальные примеры использования</h2>
<p dir="auto">Представь группировку логов по пользователям. Для каждого ID пользователя нужен массив событий. Без getOrInsert: проверка has, get, push или set. С методом - чистая строка. Ещё кейс: кэш вычислений, где дефолт - результат функции.</p>
<p dir="auto">В многопоточных окружениях (Web Workers) атомарность помогает избежать дублей. Хотя JS однопоточный, в асинхронных сценариях это спасает от race conditions при параллельных вставках. Плюс WeakMap.getOrInsert для объектов без утечек памяти.</p>
<p dir="auto">Популярные паттерны:</p>
<ul>
<li>Группировка: map.getOrInsert(key, []).push(value);</li>
<li>Счётчики: map.getOrInsert(key, 0) + 1;</li>
<li>Объекты: map.getOrInsertComputed(key, () =&gt; computeObject(key));</li>
</ul>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Паттерн</th>
<th>До ECMAScript 2026</th>
<th>С 2026</th>
</tr>
</thead>
<tbody>
<tr>
<td>Группировка массивов</td>
<td>if (!m.has(k)) m.set(k,[]); m.get(k).push(v);</td>
<td>m.getOrInsert(k,[]).push(v);</td>
</tr>
<tr>
<td>Инициализация счётчика</td>
<td colspan="2">m.set(k, (m.get(k)</td>
<td>0) +1);</td>
<td>m.getOrInsert(k,0) +1;</td>
</tr>
<tr>
<td>Кэш с вычислением</td>
<td>if(!m.has(k)) m.set(k, heavyFn(k));</td>
<td>m.getOrInsertComputed(k, () =&gt; heavyFn(k));</td>
</tr>
</tbody>
</table>
<h2>Что меняется в проектах с ECMAScript 2026</h2>
<p dir="auto">Теперь код чище, меньше ошибок от забытых проверок. Браузеры и Node.js поддержат это нативно - забудь полифилы из core-js. Для TypeScript типы уже готовы. <em>Нюанс</em>: ключи сравниваются SameValue, как в Map - по ссылке для объектов.</p>
<p dir="auto">Методы усиливают Map как основной инструмент для словарей. Раньше полагались на lodash или самописные хелперы. Теперь стандарт. Стоит обновить гайдлайны: предпочитай getOrInsert простым случаям, Computed - дорогим.</p>
<p dir="auto">Останутся вопросы по WeakMap-версиям или интеграции с Proxy. Там похожая логика, но для слабых ссылок - тема для разборов.</p>
]]></description><link>https://forum.exlends.ru/topic/1399/map.getorinsert-v-ecmascript-2026-atomarnye-operacii-dlya-map</link><generator>RSS for Node</generator><lastBuildDate>Sat, 17 Oct 2026 03:39:40 GMT</lastBuildDate><atom:link href="https://forum.exlends.ru/topic/1399.rss" rel="self" type="application/rss+xml"/><pubDate>Sun, 08 Mar 2026 12:48:06 GMT</pubDate><ttl>60</ttl></channel></rss>