Коллекции в JavaScript

Коллекция - это структура для хранения нескольких значений. В JavaScript к коллекциям можно отнести массивы, объекты, Set, Map и слабые коллекции WeakSet и WeakMap.

У каждой коллекции своя задача. Одна удобна для списка, другая - для описания объекта, третья - для уникальных значений, четвертая - для пар ключ - значение.

Массив как коллекция

Массив хранит элементы по порядку. У каждого элемента есть индекс, начиная с нуля.

let languages = ['HTML', 'CSS', 'JavaScript']

languages[0] // 'HTML'
languages.length // 3

Массив удобно перебирать, фильтровать, преобразовывать и сортировать.

let upperLanguages = languages.map(language => {
  return language.toUpperCase()
})

Массив выбирают, когда порядок элементов важен и с данными нужно работать как со списком.

Объект как коллекция свойств

Объект хранит данные в свойствах. У каждого свойства есть имя и значение.

let user = {
  name: 'Alex',
  age: 25,
  city: 'Moscow',
}

Объект удобно использовать, когда нужно описать одну сущность: пользователя, товар, настройки, форму.

Для перебора объекта часто используют методы Object.keys(), Object.values() и Object.entries().

Object.keys(user) // ['name', 'age', 'city']
Object.values(user) // ['Alex', 25, 'Moscow']
Object.entries(user) // [['name', 'Alex'], ['age', 25], ['city', 'Moscow']]

Set как коллекция уникальных значений

Set хранит только уникальные значения. Если добавить одно и то же значение несколько раз, в коллекции оно останется один раз.

let tags = new Set()

tags.add('javascript')
tags.add('html')
tags.add('javascript')

tags.size // 2

Set удобен, когда важно знать, есть ли значение в наборе, и не нужны повторения.

tags.has('javascript') // true
tags.has('css') // false

Map как коллекция ключей и значений

Map хранит пары ключ - значение. Она похожа на объект, но лучше подходит для коллекций, которые часто изменяются и перебираются.

let roles = new Map()

roles.set('admin', 'full access')
roles.set('editor', 'can edit')

roles.get('admin') // 'full access'

В Map можно быстро проверить наличие ключа и узнать размер коллекции.

roles.has('editor') // true
roles.size // 2

Слабые коллекции

WeakSet и WeakMap тоже являются коллекциями, но используются для более специальных задач. Они работают только с объектами и не удерживают эти объекты в памяти.

let userData = new WeakMap()
let user = { name: 'Alex' }

userData.set(user, 'online')

userData.get(user) // 'online'

Такие коллекции нельзя перебрать, у них нет свойства size. Для обычной работы со списками, наборами и справочниками чаще используют массив, объект, Set или Map.

Перебор коллекций

Массивы, Set и Map можно перебирать циклом for…of.

let tags = new Set(['javascript', 'html', 'css'])

for (let tag of tags) {
  console.log(tag)
}

С Map при переборе удобно сразу получать ключ и значение.

let roles = new Map([
  ['admin', 'full access'],
  ['editor', 'can edit'],
])

for (let [role, access] of roles) {
  console.log(role, access)
}

Обычный объект напрямую через for…of не перебирается. Сначала его обычно превращают в массив ключей, значений или пар.

let user = {
  name: 'Alex',
  age: 25,
}

for (let [key, value] of Object.entries(user)) {
  console.log(key, value)
}

Преобразование коллекций

Иногда одну коллекцию удобно преобразовать в другую. Например, Set можно превратить в массив, чтобы использовать методы массивов.

let tags = new Set(['javascript', 'html', 'css'])

let tagsArray = Array.from(tags)

Объект можно превратить в массив пар с помощью Object.entries(), а потом вернуть обратно через Object.fromEntries().

let user = {
  name: 'Alex',
  age: 25,
}

let entries = Object.entries(user)

Object.fromEntries(entries) // { name: 'Alex', age: 25 }

Итого

Коллекции помогают хранить и обрабатывать группы данных. Массив удобен для списков, объект - для описания сущностей, Set - для уникальных значений, Map - для пар ключ - значение. Если понимать назначение каждой коллекции, код становится проще и предсказуемее.