Пишем чистый код при помощи деструктуризации объектов в JavaScript

от автора

Сравниваем традиционный способ извлечения значений и деструктуризацию (ES6) в JavaScript

В этой статье мы рассмотрим традиционное присваивание значений из объектов в переменные и новый синтаксис деструктуризации в ES6. Материал адаптирован на русский язык совместно с тимлидом группы frontend-разработки в Skillbox Иваном Казанцевым.

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

Что нам это дает? Возможность писать более чистый и понятный код, экономя время и количество строк.

Деструктуризация объектов

Сначала рассмотрим деструктуризацию объектов. И для примера возьмем объект — клиент (customer).

const customer = {   name: 'Sherlock',   email: 's.h.@gmail.com',   age: 34,   address: {     streetNo: '221b Baker Street',     city: 'London',     country: 'UK'   } }

Базовое присвоение переменной

Если бы нам нужно было достать из него name и email, привычным способом мы бы сделали так:

const name = customer.name; const email = customer['email']; // или так  console.log(name); // Sherlock console.log(email); // s.h@gmaill.com

С помощью деструктуризации мы можем делать так:

const { name, email } = customer;  console.log(name); // Sherlock console.log(email); // s.h@gmaill.com

Как минимум, мы уже не пишем два раза customer и чувствуем себя чуть-чуть лучше, так как можем добавить в резюме что-то про DRY.

Но если мы хотим записать customer.name в переменную с другим именем, выходит, снова нужен традиционный способ? Нет, это мы тоже можем сделать:

const { name: customerName, email } = customer;  // обратите внимание, имя свойства из объекта customer находится слева console.log(customerName); // Sherlock

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

Если мы хотим присвоить значения уже существующим переменным, делаем почти тоже самое, но добавляем ().

let name, email;  ({ name, email } = customer);  console.log(name); console.log(email);

Почему мы добавляем ()?

{ в левой части считается блоком, а не литералом объекта. Если опустите (), вы получите сообщение об ошибке:

{ name, email } = customer;               ^SyntaxError: Unexpected token '='

Вложенные объекты

Итак, мы поняли, что это удобно, можем усложнять. Если хотим получить доступ к свойствам city и country, в традиционном способе нам нужно использовать цепочку обращений:

const name = customer.name; const streetNo = customer.address.streetNo; const city = customer['address']['city']; // или так  console.log(name); // Sherlock console.log(streetNo); // 221b Baker Street console.log(city); // London

Мы можем сделать то же самое, но короче, используя деструктуризацию:

const { name, address: { streetNo, city } } = customer;  console.log(name); // Sherlock console.log(streetNo); // 221b Baker Street console.log(city); // UK

Возможно, выглядит сложнее, но это дело привычки. И да, мы все еще можем записать свойства streetNo и city в переменные с другим названием.

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

Идем дальше. Теперь перед нами стоит задача: добавить married (женат/замужем) нашему объекту customer. Возможные варианты ответа: “да” (yes) или “нет” (no). В случае, если не указан, присвоить значение “нет ответа” (N/A).

Без деструктуризации мы бы сделали так:

let married = customer.married;  console.log(married); // undefined  if (!married) { married = 'N/A'; } console.log(married); // N/A

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

const { name, married = 'N/A' } = customer;  console.log(name); // Sherlock console.log(married); // N/A

Остаточные параметры объекта

Представим, что нам нужно достать только name ( например, чтобы присвоить ему значение по умолчанию), а все остальное записать “как есть” в другую переменную.

const { name = 'Спрятался в коробке', ...rest } = customer;  console.log(name); // Sherlock console.log(rest); // { //  email: 's.h@gmaill.com', //  age: null, //  address: { streetNo: '221b Baker Street', city: 'London', country: 'UK' } // }

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

Деструктуризация null

Стоит иметь ввиду, чтоnull деструктурировать нельзя, мы получим ошибку:

function getCustomer() { return null; }  let { name, email } = getCustomer(); // TypeError: Cannot destructure property name of 'undefined' or 'null'.

Поэтому мы должны обрабатывать такие случаи, например, так:

let { name = 'Спрятался в коробке', email = null } = getCustomer() || {};  console.log(name, email); // Спрятался в коробке null

Деструктуризация аргументов функции

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

Как бы мы сделали ранее:

let display = (customer) => console.log(`${customer.name} ${customer.address.city}`);  display(customer); // Sherlock London

Как мы сделаем теперь:

let display = ( { name, address: { city } } ) => console.log(`${name} ${city}`);    display(customer); // Sherlock London

Деструктуризация массивов

Да, это работает и с массивами. Для примера нам понадобится пакет с фруктами.

const fruits = ['Banana', 'Orange', 'Apple', 'Mango'];

Базовая деструктуризация массива

Если бы нам нужно было достать банан и апельсин, ранее мы бы сделали следующее:

let firstFruit = fruits[0]; let secondFruit = fruits[1];  console.log(firstFruit); // Banana console.log(secondFruit); // Orange

Но не сегодня, сегодня мы познакомились с деструктуризацией!

let [firstFruit, secondFruit, thirdFruit] = fruits;  console.log(firstFruit); // Banana console.log(secondFruit); // Orange console.log(secondFruit); // Apple (да, мы можем позволить себе и третий фрукт, потому что мы молодцы)

Пропуск пунктов

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

let [firstFruit, , thirdFruit] = fruits;

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

Остаточные параметры массива

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

let [yourFav, , ...friendsFav] = fruits;  console.log(yourFav); // Banana console.log(friendsFav); // [ 'Apple', 'Mango' ]

Замена значений

И в конце — фокус. Сейчас мы поменяем местами первый и второй фрукт, не объявляя для этого новую переменную.

let [firstFruit, secondFruit] = fruits;  console.log(firstFruit); // Banana console.log(secondFruit); // Orange  [firstFruit, secondFruit] = [secondFruit, firstFruit]  console.log(firstFruit); // Orange console.log(secondFruit); // Banana

Ловкость деструктуризации и никакого мошенничества.

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


ссылка на оригинал статьи https://habr.com/ru/company/skillbox/blog/658007/


Комментарии

Добавить комментарий

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