Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Вложенные объекты JS: Объекты

Значением свойства объекта может быть всё, что угодно, включая другой объект или массив:

const user = { name: 'Vasya', married: true, age: 25 };

// Добавим свойство friends со списком друзей
user.friends = ['Kolya', 'Petya'];

// Добавим свойство children со списком детей,
// каждый ребёнок представлен отдельным объектом
user.children = [
  { name: 'Mila', age: 1 },
  { name: 'Petr', age: 10 },
];

// Добавим вложенный объект
user.company = { name: 'Hexlet' };

console.log(user); // =>
// {
//   name: 'Vasya',
//   married: true,
//   age: 25,
//   friends: [ 'Kolya', 'Petya' ],
//   children: [ { name: 'Mila', age: 1 }, { name: 'Petr', age: 10 }],
//   company: { name: 'Hexlet' } 
// }

Все то же самое можно определить сразу при создании объекта:

const user = {
  name: 'Vasya',
  married: true,
  age: 25,
  friends: ['Kolya', 'Petya'],
  children: [
    { name: 'Mila', age: 1 },
    { name: 'Petr', age: 10 },
  ],
  company: {
    name: 'Hexlet'
  },
};

В этом случае обращение к вложенным элементам происходит по цепочке:

user.friends[1];       // 'Petya'
user.children[0].name; // 'Mila'
user.company.name; // 'Hexlet'

// Или через квадратные скобки
user['children'][0]['name']; // 'Mila'

Печать на экран

В console.log() встроено одно ограничение. Если в объекте есть другие объекты на глубине больше второго уровня вложенности, то при выводе такого объекта на экран вместо объектов отобразится строка [Object], а вместо массива — [Array].

const obj = { a: { b: { c: { key: 'value' }, e: [1, 2] } } };
console.log(obj);
// { a: { b: { c: [Object], e: [Array] } } }

Для вывода таких объектов можно воспользоваться функцией преобразования в JSON:

console.log(JSON.stringify(obj));
// {"a":{"b":{"c":{"key":"value"},"e":[1,2]}}}

// Или форматированный вывод
console.log(JSON.stringify(obj, null, '  '));
// {
//   "a": {
//     "b": {
//       "c": {
//         "key": "value"
//       },
//       "e": [
//         1,
//         2
//       ]
//     }
//   }
// }

Проверки в глубину

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

// Добираемся до obj.one.two.three
if (Object.hasOwn(obj, 'one')) {
  if (Object.hasOwn(obj.one, 'two')) {
    if (Object.hasOwn(obj.one.two, 'three')) {
      // ...
    }
  }
}

Так будет выглядеть решение в лоб. Однако, есть более удобный способ, речь о котором ниже.

Оператор опциональной последовательности

Если задача состоит в том, чтобы извлечь данные, а не просто проверить их существование, то можно пойти другим путем. В Javascript встроен оператор опциональной последовательности (optional chaining), который позволяет извлекать вложенные данные без проверок:

const obj = {};
obj?.one?.two?.three // undefined

Этот оператор никогда не приводит к ошибке. Он работает на любых типах данных и всегда возвращает либо undefined, либо значение указанного свойства, если оно существует.

Оператор не меняет общий подход работы с ключами в объектах. Этот же пример с динамическим ключом:

const obj = {};
const key = 'one';
obj?.[key]?.two?.three // undefined

Оператор нулевого слияния

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

const obj = {};
obj?.one?.two?.three ?? 'defaultValue' // 'defaultValue'

Значение по умолчанию возвращается только в том случае, когда слева undefined или null. В этом смысле данный оператор совсем не похож на логическое сравнение ||:

const value = false;

value ?? 'default'; // false
value || 'default'; // 'default'

get (lodash)

Пример выше перегружен символами и выглядит достаточно сложно. Как альтернативу можно использовать функцию get() библиотеки Lodash.

import _ from 'lodash';

const obj = {};

const value = _.get(obj, 'one.two.three', 'defaultValue'); // 'defaultValue'

get() особенно удобен в случае динамических ключей. В таком случае вторым аргументом можно передать массив ключей:

_.get(obj, ['one', 'two', 'three'], 'defaultValue'); // 'defaultValue'

Дополнительные материалы

  1. Функция get из библиотеки Lodash

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
1000
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы
профессия
от 6 300 ₽ в месяц
Разработка фронтенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 21 сентября
профессия
от 6 300 ₽ в месяц
Разработка бэкенд-компонентов для веб-приложений
10 месяцев
с нуля
Старт 21 сентября
профессия
от 10 080 ₽ в месяц
Разработка фронтенд- и бэкенд-компонентов для веб-приложений
16 месяцев
с нуля
Старт 21 сентября
профессия
новый
Автоматизированное тестирование веб-приложений на JavaScript
8 месяцев
c опытом
в разработке
дата определяется

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»