Понимание синтаксиса деструктуризации в JavaScript

Сайт webdevblog.ru опубликовал перевод статьи  «Understanding the JavaScript Destructuring Syntax«. Представляем его вашему вниманию.

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

В JavaScript (и других языках программирования) мы часто работаем с группами данных, такими как массив и объект. Доступ к этим данным обычно осуществляется с помощью индекса для массивов и свойства для объектов, но приходилось ли вам когда-нибудь обращаться к одному и тому же определенному фрагменту данных снова и снова в коде до точки, из-за чего код становилось все труднее и труднее понимать?

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

//--- Base example
if (users[0].capabilities[0].type === 'edit' && users[0].active)

//--- By hand
const user = users[0]
const active = user.active
const canEdit = user.capabilities[0].type
if (canEdit === 'edit' && active)

//--- With destructuring
const [{ active, capabilities: [{ type: canEdit }] }] = users
if (canEdit === 'edit' && active)

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

Disclaimer: эта статья предназначена для людей, которые впервые изучают синтаксис деструктурированого присваивания и испытывают трудности с его пониманием. Я расскажу только о возможностях, которые дает нам эта функция. Для получения более подробных примеров и информации я рекомендую прочитать примеры на страницы MDN Destructuring.

Начнем с массивов

const people = ['Karen', 'Bob']`

sendItem(people[0], 'chocs')`
sendItem(people[1], 'coal')`

На первый взгляд, приведенный выше код довольно ясен. По какой-то причине тот, кто находится в индексе 0, кажется, получает хороший предмет chocs, в то время как человек с индексом 1 получает только кусок угля coal.

Может быть, мы могли бы переписать код, чтобы он был немного понятнее.

const people = ['Karen', 'Bob']

const bestFriend = people[0]
const archEnemy = people[1]

sendItem(bestFriend, 'chocs')
sendItem(archEnemy, 'coal')

Теперь, когда мы объявили некоторые переменные, которые более точно описывают, что означают индексы 0 и 1, код становится легче читать и понимать. Однако вы можете заметить некоторую многословность в том месте, где мы объявляем обе константы.

Сейчас это не имеет большого значения, поскольку нам нужно извлечь из массива только двух человек. Но что, если их было бы 5 или 10? Из-за этой необходимости синтаксис деструктуризации сделал нашу жизнь лучше в ES6.

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

const people = ['Karen', 'Bob']

const [bestFriend, archEnemy] = people

sendItem(bestFriend, 'chocs')
sendItem(archEnemy, 'coal')  

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

Вы уже знаете, как объявлять массив, поэтому, если я вам скажу:

const people = [bestFriend, archEnemy]

В этом есть смысл, правда? Переменной слева присваивается содержимое справа.

Если мы инвертируем предыдущий оператор, мы получим:

[bestFriend, archEnemy] = const people

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

Таким образом, мы перемещаем ключевое слово const в начало, и получаем следующее:

const [bestFriend, archEnemy] = people

Это означает: я хочу создать две переменные, bestFriend и archEnemy, из массива people. Первая переменная, bestFriend, будет фиксировать значение в индексе 0 массива people; а вторая переменная, archEnemy, будет фиксировать значение внутри индекса 1.

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

// index 0 index 1
const [bestFriend, archEnemy] = people

Работа с объектами

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

Давайте создадим объект «человек», над которым мы можем работать в качестве нашего примера.

const bestFriend = {
  name: 'Karen',
  age: 35,
  species: 'Reptilian',
  alignment: 'Chaotic neutral',
  favorites: [
    { type: 'food', value: 'ice cream' },
    { type: 'animal', value: 'otter' }
  ]
}

const archEnemy = {
  age: 40,
  name: 'Unavailable'
}

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

const { age, favorites, name } = bestFriend
console.log(age) // 35
console.log(favorites[0].value) // ice cream
console.log(name) // Karen

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

const { age: howOld, name: howToCall } = bestFriend
console.log(howOld) // 35
console.log(howToCall) // Karen

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

sendItem(bestFriend, bestFriend.favorites[0].value, bestFriend.age)
sendItem(archEnemy, 'coal', archEnemy.age)

На первый взгляд, не зная внутреннего API функции sendItem, это не очень понятно. Мы могли бы использовать простые переменные, чтобы прояснить наши намерения. Мы хотим послать нашему другу столько подарков, сколько его возраст (age), и столько врагу сколько его возраст.

const perfectGift = bestFriend.favorites[0].value
const amountOfGiftsForFriend = bestFriend.age
const amountOfCoalForEnemy = archEnemy.age

sendItem(bestFriend, perfectGift, amountOfGiftsForFriend)
sendItem(archEnemy, 'coal', amountOfCoalForEnemy)

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

const {age: amountOfGiftsForFriend, favorites: [{ value: perfectGift }]} = bestFriend
const {age: amountOfCoalForEnemy} = archEnemy

sendItem(bestFriend, perfectGift, amountOfGiftsForFriend)
sendItem(archEnemy, 'coal', amountOfCoalForEnemy)

Давайте деструктурируем (ха!) этот пример, чтобы лучше понять, что происходит.

В первой строке мы деструктурируем несколько свойств из объекта bestFriend. Нам нужно знать два фрагмента данных: perfectGift, который должен быть значением первого элемента в массиве favorites, и amountOfGiftsForFriend, который должен быть равен age.

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

const { age: amountOfGiftsForFriend } = bestFriend
console.log(amountOfGiftsForFriend) // 35

Затем нам нужно деструктурировать свойство favorites.

const { favorites } = bestFriend
console.log(favorites) 
// [
//  { type: 'food', value: 'ice cream' },
//  { type: 'animal', value: 'otter' }
// ]

А теперь оставайтесь со мной, favorites — это массив, верно? А в первой части этой статьи мы узнали, что можно деструктурировать массивы по их индексу. Помните?

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

const { favorites: [firstFavorite] }
console.log(firstFavorite) // { type: 'food', value: 'ice cream' }

Теперь нам просто нужно указать синтаксису деструктуризации, какое свойство этого первого объекта нам нужно и как мы хотим его переименовать.

const { favorites: [{ value: perfectGift }] }
console.log(perfectGift) // ice cream

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

Заключение

Как я упоминал в начале статьи, это небольшое объяснение предназначено только для того, чтобы вы миновали тот момент OMG WHAT IS DIS, когда вы впервые сталкиваетесь с синтаксисом где-то в «дикой» природе.

Я лично считаю, что деструктуризация может внести большую ясность в код, и это фантастический инструмент, который стоит иметь за плечами разработчика. Тем не менее, я рекомендую вам хотя бы быстро прочитать примеры, предоставленные MDN, чтобы глубже понять возможности, которые может дать вам этот синтаксис.

[customscript]techrocks_custom_after_post_html[/customscript]

[customscript]techrocks_custom_script[/customscript]

Оставьте комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Прокрутить вверх