Зарегистрируйтесь для доступа к 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' ],
//   company: { name: 'Hexlet' },
//   children: [ { name: 'Mila', age: 1 }, { name: 'Petr', age: 10 } ] }

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

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'

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

В 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 (_.has(obj, 'one')) {
  if (_.has(obj.one, 'two')) {
    if (_.has(obj.one.two, 'three')) {
      // ...
    }
  }
}

Так будет выглядеть решение в лоб. Однако, has() гораздо гибче, чем может показаться на первый взгляд. Вторым параметром эта функция принимает не просто название свойства, она работает с понятием "путь". То есть пример выше можно переписать так:

if (_.has(obj, 'one.two.three')) {
  // ...
}

Путь можно представить массивом:

// Может быть удобно, когда имена представлены переменными
if (_.has(obj, ['one', 'two', 'three'])) {
  // ...
}

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

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

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

Этот оператор никогда не приводит к ошибке. Он работает на любых типах данных и всегда возвращает либо 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

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

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

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

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

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

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

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

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

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

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

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

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

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

Иконка программы Фронтенд-разработчик
Профессия
Разработка фронтенд-компонентов веб-приложений
27 октября 8 месяцев
Иконка программы Node.js-разработчик
Профессия
Разработка бэкенд-компонентов веб-приложений
27 октября 8 месяцев

Есть вопрос или хотите участвовать в обсуждении?

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

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг»