Пишем код чище, используя паттерны деструктурирования



Вы, наверное, уже знакомы с деструктурированием в JavaScript. Оно пришло к нам в 2015 году в спецификации ES6, но если вам нужно освежить знания, то на сайте Mozilla можно почитать большую подробную статью, как это всё работает.


Но знать как работает совсем не то же, что знать как использовать. Вот три паттерна, которые помогут вам сделать код чище, надёжнее и читаемее!


1. Именованные аргументы функции


Именованные аргументы это альтернативный позиционным аргументам путь обработки параметров функции. Вместо того, чтобы указывать аргументы в строго определённом порядке, просто указывайте их имя. В Питоне, например, это выглядит так:


def sum(a=1,b=2,c=3):
  return a+b+c

sum(b=5,a=10)

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


  1. Можно опустить один или несколько параметров при вызове функции
  2. Порядок при передаче аргументов теперь не важен
  3. Код стал читаемее 

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


function sum({a = 1, b = 2, c = 3}) {
  return a + b + c
}

sum({b: 10, a: 5}) // 5 + 10 + 3 = 18

Все цели достигнуты: можно не указывать c, порядок теперь не важен, и аргументы сопровождаются своими именами. Всё это возможно именно благодаря деструктурированию.


2. Более чистый парсинг ответа сервера


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


function mockServerCall () {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({
        'status': 200,
        'content-type': 'application/json',
        'data' : {
          dataOfInterest: 42
        }
      })
    }, 250)
  })
}

mockServerCall()
  .then(({data: { dataOfInterest = 100 }}) => {
    console.log(dataOfInterest) // 42 (но по дефолту будет 100)
  })

Этот паттерн позволяет выдёргивать интересующие нас данные по мере парсинга аргументов. А возможность настроить дефолтные значения вы получаете бонусом. Что плавно подводит нас к следующему паттерну...


Установка дефолтных значений во время присвоения


Если переменной не существует в пространстве имён, нам часто нужно установить ей значение по-умолчанию.


До прихода деструктурирования вы могли делать что-то типа этого:


// старый способ установки дефолтных значений
var nightMode = userSettings.nightMode || false

Но такой подход потребует по строчке кода на каждое присвоение. Деструктурирование же позволит сделать всё одним махом:


const userSettings = {nightMode: true, fontSize: 'large'}

const {
  nightMode = false,
  language = 'en',
  fontSize = 'normal'
} = userSettings

console.log(nightMode) // true
console.log(language) // 'en'
console.log(fontSize) // 'large'

Этот паттерн можно применять для установки состояния компонентов React!




Надеюсь, эти паттерны вам пригодятся! Чтобы почитать больше о деструктурировании переходите по ссылкам ниже (информация на английском — прим. перев.):


ES6 In Depth: Destructuring


Learn the basics of destructuring props in React

Комментарии (4)


  1. ilnuribat
    20.06.2019 16:56
    +3

    особенно удобно делать так:

    const {
      NODE_ENV = 'development',
      LOG_LEVEL = 'info',
      // ...
    } = process.env;
    


  1. timon_aeg
    20.06.2019 17:11
    +1

    {data: { dataOfInterest = 100 }}

    Осторожно, если data внезапно null или undefined, то возникнет ошибка времени исполнения.


  1. vladbarcelo
    20.06.2019 18:57
    +1

    А ещё так можно выбросить ненужные свойства объекта:


    const data = { usefulProp1: 1, usefulProp2: 2, uselessProp1: 3, usefulProp3: 4 }
    const { uselessProp1, ...usefulData } = data // хоба!
    console.log(usefulData) // дальше работаем с этой переменной


  1. Dron007
    20.06.2019 19:07
    +1

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

    const { language:lang = 'en' } = userSettings
    console.log(lang) // 'en'