Что используешь для хранения коллекций в JavaScript?

Ответ

В JavaScript (и, соответственно, в Node.js) для хранения коллекций данных доступны несколько структур. Выбор зависит от конкретной задачи:

  1. Массивы (Array) — для упорядоченных списков.

    const tasks = ['Рефакторинг', 'Написать тесты'];
    tasks.push('Деплой');
  2. Объекты (Object) — для коллекций пар ключ-значение, где ключ — строка или символ. Идеально для структурированных данных.

    const config = {
      port: 3000,
      host: 'localhost',
      logging: true
    };
  3. Map — для коллекций, где ключом может быть любой тип (объект, функция). Сохраняет порядок вставки.

    const userMetadata = new Map();
    const user = { id: 123 };
    userMetadata.set(user, { lastLogin: new Date() });
  4. Set — для хранения уникальных значений любого типа.

    const uniqueTags = new Set();
    uniqueTags.add('nodejs');
    uniqueTags.add('javascript');
    uniqueTags.add('nodejs'); // Не добавится, дубликат
  5. WeakMap и WeakSet — аналоги Map и Set, но с "слабыми" ссылками на ключи (объекты). Это позволяет сборщику мусора удалять объекты-ключи, если на них нет других ссылок. Полезны для приватного хранения метаданных или кэширования без утечек памяти.

    const privateData = new WeakMap();
    class User {
      constructor(name) {
        privateData.set(this, { secretToken: crypto.randomBytes(16) });
      }
      getToken() {
        return privateData.get(this).secretToken;
      }
    }

В Node.js для работы с большими данными также часто используют буферы (Buffer) или TypedArray, но это уже не коллекции в классическом понимании.

Ответ 18+ 🔞

А, ну вот, опять про коллекции в JS спрашивают. Давай разберём, как мужик, без этих ваших заумных книжек. Сидишь ты, значит, пишешь код, и тут бац — надо данные куда-то сложить. И тут начинается: «О, у меня же есть объект! А может, массив? А, нет, Map!». Ёпта, волнение ебать, глаза разбегаются.

Так вот, смотри. Всё просто, как три копейки.

Первое — это обычный массив (Array). Ну, классика жанра. Как список дел перед смертью. Всё по порядку, пронумеровано. Хочешь добавить — push, хочешь убрать — pop. Удобно, предсказуемо, все знают.

const tasks = ['Рефакторинг', 'Написать тесты'];
tasks.push('Деплой'); // Всё, добавил, иди работай

Второе — объект (Object). Это уже серьёзнее. Тут не просто список, а как паспорт: у каждой фигни есть своё имя (ключ). Порт, хост, включено ли логирование — всё по полочкам. Для конфигов — самое то. Но ключ только строка или символ, запомни это, а то потом будешь голову ломать.

const config = {
  port: 3000,
  host: 'localhost',
  logging: true // Включи, не бзди
};

Третье — Map. Вот это, бля, уже интереснее. Это как объект, но на стероидах. Ключом может быть что угодно — хоть целый объект, хоть функцию передавай. Порядок добавления помнит, что тоже иногда овердохуища как полезно. Представь: у тебя есть пользователь (объект), и ты к нему привязываешь какие-то мета-данные. В обычном объекте так не сделаешь, а в Map — запросто.

const userMetadata = new Map();
const user = { id: 123 };
userMetadata.set(user, { lastLogin: new Date() }); // Привязал и не парься

Четвёртое — Set. Задача у него одна — хранить только уникальное. Подкидывай ему значения, а он сам разберётся, было уже такое или нет. Очень удобно, когда нужно убрать дубликаты из какого-нибудь говнолиста. Добавил 'nodejs' два раза? Он тебе второй раз просто проигнорит, хитрая жопа.

const uniqueTags = new Set();
uniqueTags.add('nodejs');
uniqueTags.add('javascript');
uniqueTags.add('nodejs'); // Не добавится, дубликат, я же сказал!

И наконец, пятое — WeakMap и WeakSet. Это для продвинутых, кто про утечки памяти думает. Выглядят как их старшие братья (Map и Set), но с одной важной фишкой: они не мешают сборщику мусора. Если объект-ключ больше нигде не используется, его можно спокойно выкинуть из памяти. Идеально для какого-нибудь кэша или приватных данных внутри класса, чтобы не оставлять за собой хвостов.

const privateData = new WeakMap();
class User {
  constructor(name) {
    // Приватные штуки кладём в WeakMap, ключ — это сам экземпляр (this)
    privateData.set(this, { secretToken: crypto.randomBytes(16) });
  }
  getToken() {
    return privateData.get(this).secretToken; // Достаём только отсюда
  }
}
// Когда объект user умрёт, запись в WeakMap автоматом очистится — красота!

А, да, ещё в Node.js есть свои штуки вроде Buffer или TypedArray для бинарных данных, но это уже совсем другая история, про байты и побайтовые сдвиги. Для обычных коллекций хватит и этого списка. Главное — понимай, для чего каждая вещь, а не тыкай наугад, как мартышлюшка. Выбор инструмента — половина успеха.