Объекты

Объект — коллекция именованных свойств (пар ключ-значение), основной способ структурирования данных в JavaScript.

Зачем нужно

Объекты — фундаментальная структура данных JS. Почти всё в JS — объект: массивы, функции, Date, RegExp. Понимание объектов необходимо для работы с любым API и фреймворком.

Где используется

  • Хранение структурированных данных
  • Конфигурации и настройки
  • Ответы API (JSON)
  • DOM-элементы
  • Модули и пространства имён

Предпосылки

Типы данных, Переменные

Создание объектов

// 1. Литерал объекта (основной способ)
const user = {
  name: 'Алиса',
  age: 25,
  isActive: true
};

// 2. new Object (не рекомендуется)
const obj = new Object();
obj.name = 'Боб';

// 3. Object.create
const proto = { greet { return `Привет, ${this.name}`; } };
const person = Object.create(proto);
person.name = 'Чарли';
console.log(person.greet); // "Привет, Чарли"

// 4. Конструктор / Класс
class User {
  constructor(name) {
    this.name = name;
  }
}
const u = new User('Дана');

Свойства: чтение, запись, удаление

const user = { name: 'Алиса', age: 25 };

// Чтение
console.log(user.name);       // 'Алиса' (точечная нотация)
console.log(user['age']);     // 25 (скобочная нотация)

// Запись
user.email = 'alice@mail.com'; // добавление
user.age = 26;                  // изменение

// Динамический ключ — только через 
const key = 'name';
console.log(user[key]); // 'Алиса'

// Удаление
delete user.email;
console.log(user.email); // undefined

// Проверка существования свойства
console.log('name' in user);              // true
console.log(user.hasOwnProperty('name')); // true
console.log(Object.hasOwn(user, 'name')); // true (ES2022)

Вычисляемые свойства

const field = 'color';
const value = 'red';

const config = {
  [field]: value,                    // { color: 'red' }
  [`${field}Dark`]: 'darkred',      // { colorDark: 'darkred' }
  ['get' + 'Name'] { return 'Алиса'; } // метод getName
};

console.log(config.color);      // 'red'
console.log(config.colorDark);  // 'darkred'
console.log(config.getName);  // 'Алиса'

Сокращённая запись

const name = 'Алиса';
const age = 25;

// Shorthand properties
const user = { name, age };
// Эквивалент: { name: name, age: age }

// Shorthand methods
const calculator = {
  add(a, b) { return a + b; },       // вместо add: function(a, b) {...}
  subtract(a, b) { return a - b; }
};

Перебор объектов

const user = { name: 'Алиса', age: 25, city: 'Москва' };

// for...in (включая унаследованные свойства)
for (const key in user) {
  if (user.hasOwnProperty(key)) {
    console.log(`${key}: ${user[key]}`);
  }
}

// Object.keys() — массив ключей
Object.keys(user);   // ['name', 'age', 'city']

// Object.values() — массив значений
Object.values(user);  // ['Алиса', 25, 'Москва']

// Object.entries() — массив пар [ключ, значение]
Object.entries(user);
// [['name', 'Алиса'], ['age', 25], ['city', 'Москва']]

// Удобный перебор
for (const [key, value] of Object.entries(user)) {
  console.log(`${key}: ${value}`);
}

// Object.fromEntries — обратное преобразование
const entries = [['a', 1], ['b', 2]];
Object.fromEntries(entries); // { a: 1, b: 2 }

Деструктуризация

const user = { name: 'Алиса', age: 25, city: 'Москва' };

// Базовая
const { name, age } = user;
console.log(name); // 'Алиса'

// С переименованием
const { name: userName, age: userAge } = user;
console.log(userName); // 'Алиса'

// Со значением по умолчанию
const { name, country = 'Россия' } = user;
console.log(country); // 'Россия'

// Вложенная деструктуризация
const response = {
  data: {
    users: [{ id: 1, name: 'Алиса' }]
  }
};
const { data: { users: [firstUser] } } = response;
console.log(firstUser.name); // 'Алиса'

// Rest-свойства
const { name, ...rest } = user;
console.log(rest); // { age: 25, city: 'Москва' }

Spread оператор

const defaults = { theme: 'light', lang: 'ru', fontSize: 14 };
const userPrefs = { theme: 'dark', fontSize: 16 };

// Слияние (последний побеждает)
const config = { ...defaults, ...userPrefs };
// { theme: 'dark', lang: 'ru', fontSize: 16 }

// Поверхностная копия
const copy = { ...user };
copy.name = 'Боб';
console.log(user.name); // 'Алиса' — оригинал не изменился

// Добавление свойств
const enhanced = { ...user, role: 'admin', updatedAt: Date.now() };

Полезные методы Object

// Object.assign — копирование свойств
const target = { a: 1 };
Object.assign(target, { b: 2 }, { c: 3 });
console.log(target); // { a: 1, b: 2, c: 3 }

// Object.freeze — полная заморозка
const frozen = Object.freeze({ x: 1, y: 2 });
frozen.x = 10;          // игнорируется (strict mode — ошибка)
frozen.z = 3;            // игнорируется
console.log(frozen.x);  // 1

// Object.keys()/values/entries
Object.keys({ a: 1, b: 2 });    // ['a', 'b']
Object.values({ a: 1, b: 2 });  // [1, 2]
Object.entries({ a: 1, b: 2 }); // [['a', 1], ['b', 2]]

// Object.hasOwn (ES2022) — замена hasOwnProperty
Object.hasOwn({ a: 1 }, 'a'); // true
Object.hasOwn({ a: 1 }, 'b'); // false

// Object.groupBy (ES2024)
const people = [
  { name: 'Алиса', age: 25 },
  { name: 'Боб', age: 30 },
  { name: 'Чарли', age: 25 }
];
const grouped = Object.groupBy(people, p => p.age);
// { 25: [{name:'Алиса',...}, {name:'Чарли',...}], 30: [{name:'Боб',...}] }

Optional chaining с объектами

const user = {
  name: 'Алиса',
  address: {
    city: 'Москва'
  }
};

// Без optional chaining
const zip = user.address && user.address.zip; // undefined

// С optional chaining
const zip2 = user.address?.zip;       // undefined
const street = user.location?.street; // undefined (нет ошибки)

// Вызов метода
const result = user.getName?.; // undefined если метода нет

Частые ошибки

1. Мутация через ссылку

const original = { a: 1, nested: { b: 2 } };
const copy = { ...original };
copy.nested.b = 999;
console.log(original.nested.b); // 999 — spread делает ПОВЕРХНОСТНУЮ копию!

// Решение: structuredClone для глубокой копии
const deepCopy = structuredClone(original);

2. for...in перебирает унаследованные свойства

// Используй Object.keys() или проверку hasOwnProperty
for (const key of Object.keys(obj)) {
  // Только собственные свойства
}

3. Порядок ключей

// Числовые ключи сортируются первыми
const obj = { b: 2, 1: 'one', a: 1, 2: 'two' };
Object.keys(obj); // ['1', '2', 'b', 'a']

Практика

  1. Создай объект student со свойствами и методом introduce
  2. Напиши функцию merge(obj1, obj2) без использования spread
  3. Напиши функцию pick(obj, keys) — возвращает объект только с указанными ключами
  4. Глубоко скопируй объект с вложенными массивами и объектами

Связанные темы

Ресурсы