Урок · JavaScript
Объекты: собираем связанные данные вместе
Объект в JavaScript — набор пар «ключ — значение» в фигурных скобках, описывающий одну сущность: пользователя, товар, урок. Значение читают через точку lesson.title или квадратные скобки lesson['title']. Значением может быть что угодно, включая функцию — тогда это метод.
{ title: 'Flexbox', minutes: 20 }— объект из двух свойств.- Точка — для известного ключа, скобки — когда ключ в переменной.
- Несуществующее свойство даёт
undefined, а не ошибку. const copy = objне копирует объект — нужен{ ...obj }.Object.entries(obj)превращает объект в массив пар для перебора.
Зачем этот урок сейчас
У урока есть название, длительность, уровень и автор. Можно завести четыре переменные, но для десяти уроков их станет сорок. Объект собирает данные одной вещи вместе, а массив объектов — каталог целиком. Ответы сервера в JSON, настройки, состояние интерфейса — всё это объекты.
Создание и чтение
const lesson = {
title: 'Flexbox',
minutes: 20,
isPublished: true,
tags: ['css', 'layout'],
};
console.log(lesson.title); // 'Flexbox'
console.log(lesson['minutes']); // 20
const field = 'isPublished';
console.log(lesson[field]); // true — ключ из переменной
console.log(lesson.author); // undefined — такого свойства нетКлючи — строки, даже если записаны без кавычек. Кавычки обязательны, если в ключе пробел или дефис: { 'data-id': 5 }, и читать его тогда можно только через скобки.
Изменение, добавление и удаление
lesson.minutes = 25; // изменить
lesson.level = 'начальный'; // добавить новое свойство
delete lesson.isPublished; // удалить
'level' in lesson; // true
Object.hasOwn(lesson, 'author'); // falseОбъект, объявленный через const, можно менять изнутри: const запрещает только присвоить переменной другой объект. Проверить наличие ключа надёжнее через in или Object.hasOwn: сравнение с undefined не отличит отсутствующий ключ от ключа со значением undefined.
Короткая запись свойств
const title = 'Grid';
const minutes = 30;
const lesson = { title, minutes }; // то же, что { title: title, minutes: minutes }
const key = 'level';
const extra = { [key]: 'средний' }; // вычисляемый ключ: { level: 'средний' }Методы и this
const cart = {
items: [],
add(product) {
this.items.push(product);
},
total() {
return this.items.reduce((sum, p) => sum + p.price, 0);
},
};
cart.add({ title: 'Курс CSS', price: 1500 });
cart.total(); // 1500Функция внутри объекта — метод. this в методе указывает на объект перед точкой при вызове: cart.add() — значит, this это cart. Методы пишут в короткой форме add() {}, а не стрелкой: у стрелочной функции нет своего this, и this.items внутри неё не сработает.
Деструктуризация
const { title, minutes, level = 'старт' } = lesson;
function showLesson({ title, minutes }) {
return `${title}: ${minutes} минут`;
}
showLesson(lesson);Деструктуризация достаёт несколько свойств в переменные одной строкой. Имена должны совпадать с ключами, а значение по умолчанию сработает, если свойства нет. Особенно удобно в параметрах функции: сразу видно, какие поля ей нужны.
Ссылка и копия
const a = { title: 'HTML', tags: ['base'] };
const b = a; // вторая ссылка на тот же объект
b.title = 'CSS';
console.log(a.title); // 'CSS' — изменился и a
const copy = { ...a, title: 'JS' }; // поверхностная копия с заменой поля
copy.tags.push('new'); // но массив внутри общий!
const deep = structuredClone(a); // глубокая копияПеременная хранит не сам объект, а ссылку на него. Присваивание копирует ссылку. Spread создаёт новый объект, но вложенные массивы и объекты остаются общими. Когда нужно менять вложенные данные независимо, используй structuredClone.
Перебор объекта
const prices = { html: 0, css: 1500, js: 2500 };
Object.keys(prices); // ['html', 'css', 'js']
Object.values(prices); // [0, 1500, 2500]
Object.entries(prices); // [['html', 0], ['css', 1500], ['js', 2500]]
for (const [course, price] of Object.entries(prices)) {
console.log(`${course}: ${price} ₽`);
}Object.keys, values и entries превращают объект в массив, а массив уже можно перебрать, отфильтровать и отсортировать. Подробнее — на странице Object.keys, values и entries.
Безопасное чтение: ?. и ??
const user = { name: 'Анна' };
user.address.city; // TypeError: нельзя читать city у undefined
user.address?.city; // undefined — без ошибки
user.address?.city ?? 'Город не указан'; // запасное значениеЧитать несуществующее свойство безопасно, а вот свойство у undefined — ошибка. Опциональная цепочка ?. останавливается на пустом звене. Оператор ?? подставляет запасное значение только для null и undefined, в отличие от ||, который заменит и 0, и пустую строку.
Массив объектов
const lessons = [
{ id: 1, title: 'HTML', done: true },
{ id: 2, title: 'CSS', done: false },
];
const current = lessons.find((l) => l.id === 2);
const done = lessons.filter((l) => l.done);
const titles = lessons.map((l) => l.title);Однотипные данные хранят массивом объектов: так устроены каталоги, списки задач и почти все ответы сервера. Ищут нужный объект через find, отбирают через filter, преобразуют через map.
Объект или массив
Разные свойства одной сущности с именами: название, цена, автор урока. Доступ по ключу.
Список однотипных элементов по порядку: уроки, задачи, комментарии. Доступ по индексу, перебор и сортировка.
Частые ошибки
- Читают свойство у undefined:
user.address.cityбез проверки — используй?.. - Считают
const copy = objкопией и случайно меняют общий объект. - Пишут метод стрелочной функцией и удивляются, что this не работает.
- Путают точку и скобки:
obj.keyищет ключ «key», а не значение переменной key. - Перебирают объект через for без Object.entries и получают ошибку «не итерируемый».
Доступность
Объекты — внутренняя структура программы, но часто из них строится интерфейс: карточки, списки, таблицы. Выводи данные объектов через textContent и правильные теги (список, таблица), а не склеивай HTML-строкой — так текст не сломает разметку и останется понятным скринридеру.
Поддержка браузерами
Объекты и базовые операции работают везде. Короткая запись свойств, деструктуризация и spread поддерживаются всеми актуальными браузерами. ?., ??, Object.hasOwn и structuredClone — более новые, но тоже доступны в актуальных версиях Chrome, Safari и Firefox.
Практика
Создай объект товара с названием, ценой и количеством. Добавь метод total(), возвращающий стоимость. Затем сделай копию товара с другим количеством, не меняя исходный объект, и выведи все свойства копии в консоль строками «ключ: значение».
Показать решение
const product = {
title: 'Курс HTML',
price: 1200,
count: 1,
total() {
return this.price * this.count;
},
};
const bigOrder = { ...product, count: 3 };
console.log(bigOrder.total()); // 3600
console.log(product.count); // 1 — исходный не изменился
for (const [key, value] of Object.entries(bigOrder)) {
if (typeof value !== 'function') console.log(`${key}: ${value}`);
}Частые вопросы
Чем точка отличается от квадратных скобок?
Точка читает свойство с фиксированным именем: obj.title. Скобки принимают строку или переменную: obj[key], и нужны для ключей с пробелами и дефисами.
Почему изменился исходный объект?
Переменные хранят ссылку на объект. const b = a не копирует его — обе переменные смотрят на один объект. Копию даёт { ...a } или structuredClone(a).
Как проверить, есть ли свойство в объекте?
'key' in obj или Object.hasOwn(obj, 'key'). Сравнение с undefined не отличит отсутствующий ключ от ключа со значением undefined.
Как перебрать объект?
Через Object.entries(obj) и for...of: for (const [key, value] of Object.entries(obj)).
Почему this в методе равен undefined?
Метод записан стрелочной функцией или вызван отдельно от объекта (например, передан в обработчик). Пиши методы в форме name() {} и вызывай через объект.