В предыдущей статье рассматривались типы данных и различия между примитивами и объектами. Теперь имеет смысл остановиться на объектах подробнее, потому что именно они используются для хранения состояния, конфигураций, моделей данных и практически всего «сущностного» в приложениях.

Важно не просто уметь создавать объект, а понимать, как он ведёт себя при чтении, изменении и передаче.

Самый простой объект

const user = {
  name: 'Alex',
  age: 30
};

Здесь объект:

  • хранит набор свойств
  • каждое свойство — пара «ключ–значение»
  • значения могут быть любыми типами данных

Доступ к свойствам возможен двумя способами.

Доступ к свойствам

Через точку:

console.log(user.name);

Через квадратные скобки:

console.log(user['age']);

Оба способа работают, но используются в разных ситуациях.

Когда нужны квадратные скобки

Если имя свойства известно заранее и является корректным идентификатором, используется точка.

Если имя свойства:

  • хранится в переменной
  • содержит пробелы или спецсимволы

нужны квадратные скобки.

const field = 'name';
console.log(user[field]);

const data = {
  'first name': 'Alex'
};

console.log(data['first name']);

Добавление и изменение свойств

Объект в JavaScript — изменяемая структура.

const product = {
  title: 'Book'
};

product.price = 500;
product.title = 'Notebook';

Здесь:

  • свойство price добавлено
  • свойство title изменено

Это называется мутация объекта.

Удаление свойств

delete product.price;

После этого свойства больше нет.

Важно понимать, что удаление свойства:

  • влияет на все ссылки на объект
  • может ломать ожидаемую структуру данных

Поэтому delete используется редко и осознанно.

Проверка существования свойства

console.log('title' in product); // true
console.log('price' in product); // false

Оператор in проверяет:

  • есть ли такое свойство в объекте
  • включая свойства прототипа (о нём позже)

Значение undefined и отсутствие свойства — не одно и то же

const item = {
  count: undefined
};

console.log(item.count);      // undefined
console.log('count' in item); // true

И другой случай:

const item = {};

console.log(item.count);      // undefined
console.log('count' in item); // false

Это важное различие при проверках и валидации данных.

Перебор свойств объекта

Самый простой способ — for...in.

for (const key in user) {
  console.log(key, user[key]);
}

Этот цикл:

  • перебирает все перечисляемые свойства
  • включая унаследованные (позже это станет важно)

Современные методы объекта

Для явной работы со своими свойствами используются методы Object.

Object.keys(user);   // ['name', 'age']
Object.values(user); // ['Alex', 30]
Object.entries(user); // [['name', 'Alex'], ['age', 30]]

Пример использования:

Object.entries(user).forEach(([key, value]) => {
  console.log(key, value);
});

Объект как структура данных, а не просто «мешок»

Частая ошибка — использовать объект без чёткой формы.

const settings = {};
settings.theme = 'dark';
settings.language = 'en';

На небольшом участке кода это допустимо, но по мере роста проекта:

  • сложно понять, какие свойства ожидаются
  • легко допустить ошибку в имени

Поэтому важно придерживаться предсказуемой структуры.

Ограничение изменения объекта

Иногда требуется защитить объект от изменений.

const config = {
  mode: 'production'
};

Object.freeze(config);

После этого:

  • нельзя добавить новые свойства
  • нельзя изменить существующие
  • нельзя удалить свойства
config.mode = 'development'; // не сработает

Object.freeze — не глубокая защита

const config = {
  options: {
    debug: false
  }
};

Object.freeze(config);
config.options.debug = true; // работает

Защищается только верхний уровень.

Практический вывод

На этом этапе важно зафиксировать:

  1. Объекты — изменяемые структуры данных
  2. Все ссылки указывают на один и тот же объект
  3. Добавление, изменение и удаление свойств — мутации
  4. Проверка свойства и undefined — разные вещи
  5. Структура объекта должна быть предсказуемой

В следующей статье логично перейти к теме копирования объектов и массивов, потому что именно там чаще всего допускаются ошибки, приводящие к неожиданным мутациям и трудноотлавливаемым багам.