let colors = {
header: "blue",
footer: "gray",
content: {
title: "black",
body: "darkgray",
signature: "light blue"
}
};
Объект внутри объекта определяется так же, как и свойство с использованием скобочного синтаксиса для установки значения свойства для объекта. Если мы хотим добавить свойство во вложенный объект, то можем для этого использовать те же только что полученные знания.
Допустим, мы хотим добавить свойство frame во вложенный объект content. Сделать мы это можем, например, так:
colors.content.frame = "yellow";
Начинаем с объекта colors, переходим к объекту content, а затем определяем свойство и значение, которые нам нужны. Если же для обращения к свойству content вы предпочтете использовать скобочную нотацию, то сделаете так:
colors["content"]["frame"] = "yellow";
Если вы хотите одновременно использовать оба вида нотации, то это тоже возможно:
colors.content["frame"] = "yellow";
В начале я говорил, что существует ряд способов для добавления свойств объекту. Мы рассмотрели один из них. Более сложный способ задействует методы Object.defineProperty и Object.defineProperties. Эти методы также позволяют вам устанавливать свойство и его значение, но при этом дают и другие возможности. Например, возможность указать, может ли свойство быть пронумеровано или может ли оно быть перенастроено и т. д. Это однозначно выходит за рамки того, что мы будем делать 99 % времени в начале обучения, но если вам это нужно, то упомянутые два метода вполне пригодятся. Документация MDN (https://mdn.dev/) приводит хорошие примеры их использования для добавления одного или нескольких свойств объекту.
Удаление свойств
Если добавление свойств могло показаться вам занятным, то их удаление несколько муторно. Но при этом оно проще. Продолжим работать с объектом colors:
let colors = {
header: "blue",
footer: "gray",
content: {
title: "black",
body: "darkgray",
signature: "light blue"
}
};
Требуется удалить свойство footer. Для этого используем один из двух способов в зависимости от того, хотим мы обратиться к свойству посредством скобочной нотации или точечной:
delete colors.footer;
// или
delete colors["footer"];
Главную роль при этом играет ключевое слово delete. Просто используйте его, сопроводив свойством, которое хотите удалить.
Но JavaScript не был бы собой, если бы тут не содержался подвох. В данном случае он связан с производительностью. Если вы будете часто удалять большое количество свойств во множестве объектов, то использование delete окажется намного медленнее, чем определение значений свойств как undefined:
colors.footer = undefined;
// или
colors["footer"] = undefined;
Оборотная же сторона определения свойства как undefined в том, что оно по-прежнему остается в памяти. Вам потребуется взвесить все за и против (скорость или память) для каждой отдельной ситуации, чтобы выбрать оптимальный вариант.
Что же происходит под капотом?
Мы научились создавать объекты и производить с ними некоторые простые модификации. Так как объекты — это сердце всех возможностей JavaScript, то важно как можно лучше разобраться в происходящем. И не ради расширения багажа знаний, хоть это и помогло бы впечатлить друзей или родственников за ужином. Главная часть работы в JavaScript — это создание объектов на основе других объектов и выполнение традиционных, присущих объектному программированию действий. Все эти действия будут для вас гораздо понятнее, когда мы разберемся в том, что же происходит при работе с объектами.
Давайте вернемся к нашему объекту funnyGuy:
let funnyGuy = {};
Итак, что мы можем сделать с пустым объектом, не имеющим свойств? Неужели наш объект funnyGuy совсем одинок и изолирован от всего происходящего? В ответ эхом — нет. Причина скрыта в том, как создаваемые в JS объекты автоматически связываются с более крупным Object и всей присущей ему функциональностью. Лучшим способом понять эту связь будет визуализация. Сосредоточьтесь и внимательно рассмотрите рис. 18.1.
Рис. 18.1. Что на самом деле происходит с простым, казалось бы, объектом funnyGuy
Здесь отображено, что именно происходит за кадром, когда мы создаем пустой объект funnyGuy.
Рассмотрение этого представления начнем с самого объекта. Здесь все по-прежнему, а вот остальное уже отличается. Мы видим, что наш funnyGuy — это просто пустой объект. У него нет свойств, которые мы могли бы ему определить, но есть свойства, которые определяются по умолчанию. Эти свойства связывают объект funnyGuy с лежащим в основе типом Object, не требуя для этого нашего вмешательства. Эта связь позволяет вызывать стандартные свойства Object для funnyGuy: