Объекты в JavaScript: создание и работа
Содержание
О проверке кода. Примеры не запускались — в отличие от материалов по Node.js с фактическим выводом. Говорим прямо, а не ставим бейдж «проверено».
Объект — главная структура данных JavaScript: почти всё в языке им является. Разберём создание, доступ и типовые операции без ловушек.
Создание объекта
// литерал — основной способ
const user = {
name: 'Аня',
age: 30,
greet() { return `Привет, ${this.name}`; }, // метод
};
// пустой и потом заполнить
const empty = {};
empty.x = 1;
Литерал {} — то, чем создают объекты в 99% случаев. Ключи — строки (кавычки можно опускать для валидных имён), значения — что угодно, включая функции (методы) и вложенные объекты.
Доступ: точка против скобок
user.name; // "Аня" — точка, когда имя известно
user['name']; // то же самое
const key = 'age';
user[key]; // 30 — динамический доступ ТОЛЬКО через скобки
user['user-id']; // скобки, если имя с дефисом или спецсимволом
Точка — когда имя свойства известно заранее и является валидным идентификатором. Квадратные скобки — обязательны в двух случаях: имя лежит в переменной (динамический доступ) или содержит символы, недопустимые в идентификаторе (user-id, пробелы).
Это ровно причина, по которой data-атрибуты в DOM и ключи с дефисами читают через скобки.
Вычисляемые ключи и сокращения
Современный синтаксис убирает повторы:
const name = 'Аня';
const age = 30;
// сокращённая запись: имя переменной = имя свойства
const user = { name, age }; // вместо { name: name, age: age }
// вычисляемый ключ — имя из выражения
const field = 'email';
const obj = { [field]: 'a@b.ru' }; // ключ будет "email"
// метод короче
const api = {
get() {}, // вместо get: function() {}
};
Сокращённая запись { name, age } — то, что вы постоянно видите при возврате объектов из функций. Вычисляемый ключ [field] позволяет задать имя свойства динамически прямо в литерале.
Перебор объекта
const user = { name: 'Аня', age: 30, city: 'Москва' };
Object.keys(user); // ['name', 'age', 'city']
Object.values(user); // ['Аня', 30, 'Москва']
Object.entries(user); // [['name','Аня'], ['age',30], ['city','Москва']]
for (const [key, value] of Object.entries(user)) {
console.log(key, value);
}
Object.keys / values / entries
Современный способ
- Возвращают массив — можно
map,filter - Только собственные свойства
entries+for...ofдля пар- Предсказуемо
for…in
Наследие, осторожно
- Обходит и унаследованные свойства
- Нужна проверка
hasOwnвнутри - Для массивов вообще не стоит
- Заменён
Object.keys
Берите Object.keys/values/entries — они возвращают массив (значит, доступны map, filter) и обходят только собственные свойства. Старый for...in обходит ещё и унаследованные из прототипа, что почти всегда не то, что нужно.
Копирование: поверхностное и глубокое
const original = { name: 'Аня', address: { city: 'Москва' } };
// поверхностная копия
const shallow = { ...original };
shallow.name = 'Борис'; // ✅ не тронет оригинал
shallow.address.city = 'Казань'; // ❌ address ОБЩИЙ — изменит оригинал!
// глубокая копия
const deep = structuredClone(original);
deep.address.city = 'Пермь'; // ✅ оригинал цел
{ ...obj } и Object.assign копируют только верхний уровень. Вложенные объекты остаются общими — меняете во «копии», меняется в оригинале. Это та же природа ссылок, что у массивов.
Для настоящей независимости — structuredClone(obj): он копирует всю структуру, включая Date, Map, Set. В отличие от старого трюка JSON.parse(JSON.stringify(obj)), который эти типы ломает. structuredClone — метод платформы, работает и в Node.
Проверка свойства
const user = { name: 'Аня', role: undefined };
'name' in user; // true — есть в цепочке (и унаследованное)
Object.hasOwn(user, 'name'); // true — только собственное
user.role !== undefined; // false — но role ЕСТЬ, просто undefined!
Не проверяйте существование через сравнение с undefined — оно врёт, если значение и есть undefined. Надёжно: Object.hasOwn(obj, key) (собственное свойство) или оператор in (с учётом прототипа). Object.hasOwn — современная замена hasOwnProperty.
Защита объекта
const config = Object.freeze({ port: 3000 });
config.port = 8080; // молча не сработает (в строгом режиме — ошибка)
Object.keys(config); // читать можно
Object.freeze делает объект неизменяемым — ни изменить, ни добавить, ни удалить свойства. Полезно для констант-конфигов. Помните: const защищает переменную, а freeze — содержимое объекта; это разные вещи. И freeze тоже поверхностный — вложенные объекты нужно замораживать отдельно.
Смежные темы: примитивы и ссылки — почему копия общая; методы Object — подробнее; классы — когда объекта мало. Полный список — в уроках JavaScript.