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

В моей предыдущей статье мы рассмотрели, как деструктуризация работает с массивами в JavaScript. Вы можете проверить это здесь:



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

На этот раз мы собираемся обсудить, как выполнять деструктуризацию в JavaScript с помощью объектов.

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

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

Когда дело касается объектов, основная концепция деструктуризации остается неизменной. Как и в случае с массивами, мы деструктурируем объект, чтобы разбить сложную структуру данных (которая в данном конкретном случае была бы объектом) на меньшую и более простую структуру данных, такую ​​как переменная.

Деструктуризация объектов действительно спасает жизнь, когда дело доходит до обработки вызовов API, поскольку позволяет обрабатывать данные, полученные API, с гораздо меньшим количеством кода. Разобравшись с этим, давайте подробно рассмотрим, как деструктуризация объектов работает в JavaScript.

Получение свойств с использованием имени свойства

Допустим, у нас есть следующий объект.

const myInfo = {name: “Soumadri”, job: “Editor”, hobby: “Reading”};

Наша традиционная методика получения свойств будет выглядеть примерно так:

const myName = myInfo.name;
const myJob = myInfo.job;
const myHobby = myInfo.hobby;
console.log(myName, myJob, myHobby);

Это даст нам следующий результат:

Теперь давайте посмотрим, как мы можем сделать то же самое с помощью деструктурирования.

Чтобы деструктурировать объекты, мы используем фигурные скобки {}. Все, что нам нужно сделать, это указать имена переменных, которые точно соответствуют именам свойств, которые мы хотим извлечь из объекта. Давайте посмотрим, как это можно сделать для объекта, который я только что упомянул.

const {name, job, hobby} = myInfo;

Мы помещаем фигурные скобки в левую часть оператора присваивания. Как и в случае с массивами, когда JavaScript видит это, он будет знать, что должен выполнить деструктурирующее присвоение.

А в правой части размещаем название объекта. Обратите внимание, что имена переменных в левой части (имя, работа, хобби) соответствуют точным именам свойств в объекте myInfo. Теперь мы можем проверить результат.

console.log(name, job, hobby);

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

Имейте в виду, что, в отличие от массивов, последовательность элементов (или свойств) в объекте не имеет значения. Таким образом, нам не нужно вручную пропускать элементы. Так, например, мы можем сделать это:

const {name, hobby, job} = myInfo;

И мы получили бы следующие результаты (переменные получают те же соответствующие свойства, что и имена переменных. Таким образом, хотя позиции «хобби» и «работа» в результатах меняются местами, их значения остаются прежними):

А если бы мы хотели пропустить свойство (скажем, например, «работа»), мы бы просто сделали это:

const {name, hobby} = myInfo;
console.log(name, hobby);

И вот оно:

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

Получение свойств при переименовании переменной

В предыдущем сценарии мы получали свойства, используя переменные, имена которых совпадали с именами свойств в объекте. Однако что, если бы мы хотели хранить данные объекта под разными именами переменных? Посмотрим, как это сделать.

Чтобы ссылаться на свойство в объекте, нам все равно придется использовать его исходное имя. Однако мы можем изменить имя переменной, в которой хранятся полученные данные. Это можно сделать, как показано ниже.

const {name: myName, job:myJob, hobby: myHobby} = myInfo;

Мы по-прежнему использовали исходные имена переменных с левой стороны, но мы добавили двоеточие рядом с ними, а затем предоставили имя новой переменной, в которой мы хотели сохранить данные.

Например, на myInfo.name имеется ссылка через «имя», но тогда соответствующее ему значение («Сумадри») сохраняется в переменной myName. То же самое и с двумя другими свойствами и переменными. Давайте проверим вывод:

console.log(myName, myJob, myHobby);

И действительно, получаем тот же результат:

Получение свойств без объявления переменной

Мы также можем извлекать свойства при объявлении переменных, в которых мы сохраняем извлеченные значения отдельно. Посмотрим, как это сделать.

let name, job, hobby;
({ name, job, hobby } = myInfo);
console.log(name, job, hobby);

И действительно, мы получаем следующий вывод:

Поскольку переменные name, job и hobby уже были объявлены до выполнения деструктуризации, мы используем круглые скобки () вокруг оператора присваивания, чтобы гарантировать завершение операции.

Без круглых скобок утверждение было бы недействительным. Например, это будет недопустимый синтаксис:

{ name, job, hobby } = myInfo;

И приведет к ошибке:

Мы увидим, почему именно JavaScript считает этот синтаксис недопустимым, в следующем примере ниже.

Изменение переменных при разрушении объектов

Допустим, у нас есть две переменные со следующими значениями.

let x = 10;
let y = 20;

И у нас есть объект со следующими свойствами.

let obj = {x: 100, y: 200, z: 300};

А теперь мы хотим заменить значения объявленных ранее переменных (x и y) значениями свойств x и y внутри объекта obj.

Мы не можем сделать что-то подобное:

const {x, y} = obj;

Или это:

let {x, y} = obj;

Это потому, что мы уже объявили переменные a и b ранее, и нам не нужны новые переменные с тем же именем; мы хотим заменить значения в этих переменных.

Что, если бы мы сделали что-то подобное? В этом случае мы больше не создаем новые переменные x и y.

{x, y} = obj;

Если мы сохраним это, мы получим синтаксическую ошибку:

Это та же ошибка, которую мы видели в самом конце предыдущего раздела, если вы правильно помните. Почему JavaScript выдает эту ошибку?

Это потому, что, когда мы начинаем строку кода с фигурными скобками, как мы это делали выше (и без объявления переменной), JavaScript ожидает блок кода. А поскольку мы не можем присвоить значение блоку кода, как мы пытались сделать выше, JavaScript выдает ошибку «Неожиданный токен‘ = ’».

Итак, каков обходной путь? Чтобы решить эту проблему, мы вносим следующее изменение.

({x, y} = obj);

Верно, еще раз, как и в разделе прямо перед этим, мы заключаем всю строку кода в круглые скобки.

А теперь, если мы попробуем вывести на консоль значения x и y:

console.log(x,y);

И вот оно. Нам удалось перезаписать значения x и y (изменить их).

Значения по умолчанию

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

const library = {
name: “Soumadri’s Fiction Book Shelf”,
location: ‘1234 Fiction Palace, Calcutta, India’,
genres: [‘Mystery’, ‘Horror’, ‘Fantasy’, ‘Sci-Fi’, ‘Literary Fiction’, ‘Historical Fiction’],
titles: [‘The Inugami Clan’, ‘The Three Coffins’, ‘In Search of Lost Time’, ‘Sandman’, ‘The Left Hand of Darkness’, ‘The Complete Works of H.P. Lovecraft’, ‘Do Androids Dream of Electric Sheep?’, ‘In the Woods’, ‘In a Glass Darkly’, ‘Fingersmith’],
authors: [‘Neil Gaiman’, ‘Ursula Le Guin’, ‘Sheridan Le Fanu’, ‘H.P. Lovecraft’, ‘Marcel Proust’, ‘Tana French’, ‘John Dickson Carr’, ‘Seishi Yokomizo’, ‘Philip K. Dick’, ‘Sarah Waters’],
};

Если вы новичок и этот объект кажется вам устрашающим, позвольте мне кратко рассказать о каждом из свойств.

  • name: Название моей личной книжной полки / библиотеки.
  • адрес: Адрес библиотеки.
  • жанры: массив, в котором хранятся все жанры книг, имеющихся в библиотеке.
  • названия: массив, в котором хранятся все названия книг, имеющихся в библиотеке.
  • авторы: массив, в котором хранятся имена всех авторов, чьи книги есть в библиотеке.

Теперь предположим, что этот объект был данными, которые мы получили в результате вызова API, и мы на самом деле не знаем, каковы существующие свойства объекта (давайте представим себя для этого урока).

Теперь посмотрим, где значения по умолчанию могут пригодиться в реальных приложениях.

Теперь, поскольку я не знаю, какие свойства существуют у объекта, если бы я попытался получить такое свойство, как, скажем, library.openingHours:

console.log(library.openingHours);

В результате я бы получил undefined.

В качестве временного решения можно использовать значения по умолчанию. Если мы не уверены, существует ли свойство для объекта, мы можем присвоить ему значение по умолчанию, которое будет использоваться, если свойство не найдено в объекте. Если свойство существует в объекте, значение по умолчанию заменяется фактическим существующим значением свойства.

Давайте посмотрим на это в действии.

const { openingHours = “Unknown”, titles = [] } = library;

Мы установили OpenHours равным строковому значению по умолчанию “Unknown”. И мы по умолчанию установили заголовки в пустой массив []. Теперь посмотрим, что происходит, когда мы пытаемся распечатать результат.

console.log(openingHours);
console.log(titles);

И действительно, мы получили то, что ожидали. Поскольку свойство openingHours не существует в объекте библиотеки, оно сохраняет значение по умолчанию, которое мы ему присвоили (строка “Unknown”). А поскольку title существует как свойство объекта библиотеки, его значение по умолчанию (пустой массив []) было перезаписано фактическим значением свойства объекта библиотеки.

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

Разрушение вложенных объектов

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

const library = {
name: “Soumadri’s Fiction Book Shelf”,
location: ‘1234 Fiction Palace, Calcutta, India’,
genres: [‘Mystery’, ‘Horror’, ‘Fantasy’, ‘Sci-Fi’, ‘Literary Fiction’, ‘Historical Fiction’],
titles: [‘The Inugami Clan’, ‘The Three Coffins’, ‘In Search of Lost Time’, ‘Sandman’, ‘The Left Hand of Darkness’, ‘The Complete Works of H.P. Lovecraft’, ‘Do Androids Dream of Electric Sheep?’, ‘In the Woods’, ‘In a Glass Darkly’, ‘Fingersmith’],
authors: [‘Neil Gaiman’, ‘Ursula Le Guin’, ‘Sheridan Le Fanu’, ‘H.P. Lovecraft’, ‘Marcel Proust’, ‘Tana French’, ‘John Dickson Carr’, ‘Seishi Yokomizo’, ‘Philip K. Dick’, ‘Sarah Waters’],
timings: {
 mon: {
  open: 10,
  close: 21,
 },
 tue: {
  open: 10,
  close: 21,
 },
 sat: {
  open: 10,
  close: 16,
 },
 },
};

Посмотрим, что мы здесь сделали. К существующему объекту библиотеки я добавил еще одно свойство, называемое «тайминги», значениями которого являются объекты («mon», «tue», «sat»), которые сами по себе являются объектами, содержащими другие пары «ключ-значение» (например, open: 10, close: 21).

Итак, сначала давайте извлечем значения свойства "timeings". Вот как мы это сделаем.

const {timings} = library;

И проверим результат:

console.log(timings);

И вот так.

Хорошо, теперь, когда у нас уже есть "тайминги", давайте попробуем извлечь из него "сат".

const {sat} = timings;

А теперь посмотрим на результат.

console.log(sat);

И действительно, это ожидаемый результат.

Но здесь мы получаем объект, в то время как нам нужны значения двух переменных - одна называется «open», а другая - «close» - в двух отдельных переменных. Конечно, мы могли бы дополнительно деструктурировать "sat", чтобы получить свойства, но это слишком много строк кода. Есть ли более простое, быстрое и короткое решение? Ну да. Это то, что мы можем сделать благодаря деструктуризации.

const {sat: {open, close}} = timings;

Это пример деструктуризации вложенных объектов. Сначала мы деструктурируем тайминги, чтобы получить "sat", а затем, если мы поместим двоеточие (:) рядом с "sat" и снова начнем фигурные скобки ({}), мы сможем получить свойства, присутствующие в "sat".

Посмотрим на результат.

console.log(open, close);

И действительно, у нас есть значения «open» и «close», которые отдельно хранятся и печатаются в консоли.

Получение свойств из объектов, переданных в качестве параметра функции (практическое применение)

Давайте теперь посмотрим на практическое применение деструктуризации. Для начала мы собираемся еще раз изменить наш объект библиотеки.

const library = {
name: “Soumadri’s Fiction Book Shelf”,
location: ‘1234 Fiction Palace, Calcutta, India’,
genres: [‘Mystery’, ‘Horror’, ‘Fantasy’, ‘Sci-Fi’, ‘Literary Fiction’, ‘Historical Fiction’],
titles: [‘The Inugami Clan’, ‘The Three Coffins’, ‘In Search of Lost Time’, ‘Sandman’, ‘The Left Hand of Darkness’, ‘The Complete Works of H.P. Lovecraft’, ‘Do Androids Dream of Electric Sheep?’, ‘In the Woods’, ‘In a Glass Darkly’, ‘Fingersmith’],
authors: [‘Neil Gaiman’, ‘Ursula Le Guin’, ‘Sheridan Le Fanu’, ‘H.P. Lovecraft’, ‘Marcel Proust’, ‘Tana French’, ‘John Dickson Carr’, ‘Seishi Yokomizo’, ‘Philip K. Dick’, ‘Sarah Waters’],
timings: {
mon: {
open: 10,
close: 21,
},
tue: {
open: 10,
close: 21,
},
sat: {
open: 10,
close: 16,
},
},
lendBook: function (obj) {
 console.log(obj);
},
};

Как видите, я добавил функцию lendBook(), которая принимает объект (obj) в качестве аргумента. Пока мы просто выводим на консоль весь объект.

А теперь объяснение этого.

В JavaScript функция может иметь множество параметров, особенно в реальном приложении. И затем, если вы попытаетесь использовать эту функцию, может быть трудно узнать порядок параметров. Следовательно, мы можем отказаться от определения параметров вручную; вместо этого мы просто передаем объект в функцию в качестве аргумента. И тогда функция немедленно деструктурирует этот объект.

Попробуем реализовать это, вызвав функцию.

library.lendBook({
memberName: ‘Soumadri Banerjee’,
authorIndex: 2,
titleIndex: 4,
date: ‘8th July, 2021’,
});

Вот краткое объяснение каждого свойства объекта, который мы передаем в вызов функции.

  • memberName: имя члена библиотеки, который берет книгу.
  • authorIndex: позиция индекса, соответствующая имени автора книги в массиве library.authors.
  • titleIndex: позиция индекса, соответствующая названию книги в массиве library.titles.
  • date: Дата получения книги.

А теперь, если мы проверим наш браузер на результат:

Хотя это нормально, я упоминал ранее, что мы хотим, чтобы функция немедленно деструктурировала объект в качестве аргумента, то есть мы хотим выполнить деструктуризацию (получить значения свойств) прямо в аргументах функции.

Вот как мы можем это сделать.

lendBook: function ({ authorIndex, titleIndex, date, memberName }) {
console.log(
`The book ${this.titles[titleIndex]} by ${this.authors[authorIndex]} was borrowed by ${memberName} on ${date}.`
);
},
};

Мы деструктурируем объект, отправленный при вызове функции, используя точно такие же четыре имени свойства (authorIndex, titleIndex, date, memberName) в аргументах функции в фигурных скобках ({}) - это те же имена свойств, что и в объекте obj, который мы прошли ранее во время вызова функции.

И теперь у нас эти значения хранятся в отдельных переменных.

Для вывода на консоль я просто использовал литерал шаблона (если вы не знакомы с литералами шаблона, можете использовать обычную строку), чтобы напечатать оператор, используя все данные, представленные нам в аргументах. Результат выглядит так:

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

Еще один важный момент, на который следует обратить внимание, заключается в том, что при деструктуризации аргументов функции нам не нужно следовать какому-либо определенному порядку. Например, memberName деструктурируется в самом конце, в отличие от того, в каком порядке следуют свойства в объекте obj, который мы передали в функцию. Нам просто нужно убедиться, что мы используем точно такие же имена, что и имена свойств, для деструктуризации и получения их как переменных.

Мы можем улучшить это еще больше, реализовав то, что мы узнали ранее: значения по умолчанию.

Давайте изменим нашу функцию на следующую:

lendBook: function ({
authorIndex = 0,
titleIndex = 3,
date,
memberName,
returnDate = ‘1 month’,
}) {
console.log(
`The book ${this.titles[titleIndex]} by ${this.authors[authorIndex]} was borrowed by ${memberName} on ${date}. Please return it within ${returnDate}.`
);
}

Что мы здесь сделали, так это то, что в случае, если свойства authorIndex и titleIndex не существуют для объекта, они устанавливаются на 0 и 3 соответственно. А если returnDate не существует как свойство, ему присваивается строка «1 месяц».

Для вызова функции, который мы сделали ранее, мы предоставили значения индекса для authorIndex и titleIndex (4 и 2) соответственно. И не было собственности под названием returnDate. Итак, если мы сейчас вызовем функцию library.lendBook(), можете ли вы угадать, каков будет результат? Попробуйте.

Верно; как я упоминал ранее, значения по умолчанию, которые мы установили для authorIndex и titleIndex (0 и 3), перезаписываются во время вызова функции на 4 («Марсель Пруст») и 2 («В поисках утраченного времени») соответственно. А поскольку такого свойства, как returnDate, не было, для него установлено значение по умолчанию «1 месяц».

Конечно, это довольно рудиментарный пример с довольно большим количеством логических ловушек (очевидным является отсутствие проверки, гарантирующей, что выбранная книга действительно написана автором, которого мы выбираем), но он предназначен для того, чтобы показать вам, как работает деструктуризация. и приведем в некоторой степени реальный пример того, где это может пригодиться.

Не стесняйтесь возиться с этими концепциями, опробуйте все, что мы узнали в этой статье, и, возможно, даже улучшите и доработайте приведенные мной примеры.

Заключение

Вот и все, поздравляем с окончанием этой чрезвычайно длинной статьи. Как и в предыдущей статье, я хотел бы выразить благодарность Йонасу Шмедтманну и его отличному курсу Удеми за то, что они дали мне четкое понимание этих тем.

Я надеюсь, что вам понравилось это читать, и что это оказалось полезным. Если у вас есть какие-либо вопросы или замечания, не стесняйтесь оставлять замечание.

Приятного вам дня, хорошего дня и до скорой встречи.

Больше контента на plainenglish.io