Что такое Map в JavaScript?

«Что такое Map в JavaScript?» — вопрос из категории JavaScript, который задают на 26% собеседований Node.js Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Map — это встроенная в JavaScript коллекция для хранения пар ключ-значение, где ключом может быть значение любого типа (объект, функция, примитив), в отличие от обычных объектов, где ключи автоматически преобразуются в строки.

Зачем использовать Map в Node.js?

  • Ключи любого типа: Идеально для сопоставления объектов метаданных или DOM-элементов (в SSR) со значениями.
  • Сохранение порядка вставки: При итерации элементы возвращаются в порядке их добавления.
  • Удобный API: Имеет методы get, set, has, delete и свойство size.
  • Производительность: В сценариях частого добавления/удаления пар Map может быть быстрее объекта.

Базовый пример:

// Создание и использование Map
const userSessions = new Map();

// Ключом может быть объект (например, WebSocket соединение)
const socket = { id: 'ws-123' };
const user = { id: 'user-456', name: 'Alice' };

userSessions.set(socket, user); // Ключ - объект
userSessions.set(user.id, socket); // Ключ - строка

console.log(userSessions.get(socket)); // { id: 'user-456', name: 'Alice' }
console.log(userSessions.has(user.id)); // true
console.log(userSessions.size); // 2

// Итерация (порядок сохранён)
for (const [key, value] of userSessions) {
  console.log(key, '->', value);
}
// Вывод:
// { id: 'ws-123' } -> { id: 'user-456', name: 'Alice' }
// 'user-456' -> { id: 'ws-123' }

// Удаление
userSessions.delete(user.id);

Практический пример в Node.js: простой in-memory кэш с TTL (Time To Live):

class SimpleCache {
  constructor() {
    this.cache = new Map(); // Хранит данные: ключ -> { value, expiry }
  }

  set(key, value, ttlMs = 5000) {
    const expiry = Date.now() + ttlMs;
    this.cache.set(key, { value, expiry });
    // Автоочистка просроченных записей (можно вынести в отдельный интервал)
    setTimeout(() => {
      if (this.cache.get(key)?.expiry < Date.now()) {
        this.cache.delete(key);
      }
    }, ttlMs);
  }

  get(key) {
    const item = this.cache.get(key);
    if (!item) return null;
    if (item.expiry < Date.now()) {
      this.cache.delete(key);
      return null;
    }
    return item.value;
  }
}

// Использование
const cache = new SimpleCache();
cache.set('api_response_123', { data: 'someData' }, 10000);
console.log(cache.get('api_response_123')); // { data: 'someData' }
setTimeout(() => {
  console.log(cache.get('api_response_123')); // null (после истечения TTL)
}, 11000);
Map vs Object: Критерий Map Object
Ключи Любого типа Только String или Symbol
Порядок Сохраняет порядок вставки Не гарантирован (хотя в современных JS есть порядок для строковых ключей)
Размер map.size Object.keys(obj).length
Итерация Прямо итерируем (for...of) Требуется Object.keys, for...in
Прототип Не имеет унаследованных ключей Может иметь ключи из цепочки прототипов
Производительность Лучше при частых добавлениях/удалениях Лучше в сценариях статической структуры