Недавно я написал небольшую интеграцию со Slack для своей игровой группы. Я хотел обрабатывать броски костей для настольных игр, поэтому мне нужно было сопоставить такие шаблоны, как 1d8
, d20+2
или 2d6-4
. Я написал простое регулярное выражение для его обработки, которое, вероятно, можно было бы значительно улучшить, но оно работает для моего варианта использования: /(\d+)?d(\d+)([\+\-]\d+)?/i
(вы можете поиграть с ним на RegExr).
С ES5 я, вероятно, сделал бы что-то подобное с результатами сопоставления регулярных выражений:
var matches = rollString.match(rollRegex); var count = matches[1] || 1; var die = matches[2]; var modifier = matches[3] || 0;
С синтаксисом деструктурирования ES6 он становится намного чище (и на самом деле, на самом деле есть раздел, который делает именно такие вещи в документах):
let matches = rollString.match(rollRegex); let [, count=1, die, modifier=0] = matches;
Две линии на четверых! Как только вы привыкнете к этому, деструктурирование будет довольно интуитивно понятным, но ради объяснения давайте рассмотрим, что только что произошло: мы использовали по существу тот же синтаксис, который мы используем для создания массива, но на левую часть выражения, чтобы разделить нашу цель (или «деструктурировать» ее) и извлечь отдельные элементы в именованные переменные для дальнейшего использования. Мы начали с массива matches
, который выглядел (при условии, что у нас была входная строка d20+2
) примерно так: ['d20+2', undefined, '20', '+2']
, и «достигнул внутрь», чтобы извлечь интересующие нас значения (count
, die
и modifier
), игнорируя тот, о котором мы не заботились (вся входная строка, d20+2
).
Кроме того, поскольку count
и modifier
имеют разумные значения по умолчанию (если вы не указываете количество кубиков, мы предполагаем, что вы бросаете один кубик, а если вы не указываете модификатор, мы предполагаем, что это 0), мы могли указать их в выражении деструктурирования, если их было undefined
в массиве. В приведенном выше случае count
было неопределенным, поэтому по умолчанию было установлено значение 1, а modifier
было +2
, поэтому оно не получило своего значения по умолчанию.
Точно так же, как вы можете деструктурировать массивы, вы можете деструктурировать и объекты. Например, Slack отправляет полезную нагрузку на мою конечную точку HTTP (на которой работает небольшой экспресс-сервер), которая выглядит примерно так (некоторые поля для краткости опущены):
{ “channel_name”: “roller-test”, “user_name”: “Problematic”, “command”: “/roll”, “text”: “d20+2” }
Предполагая, что меня интересуют поля user_name
и text
, я мог бы получить их со следующим назначением деструктурирования:
let {user_name, text} = req.body;
Если бы я хотел присвоить эти свойства переменным с именами username
и roll
вместо их значений по умолчанию, синтаксис был бы немного другим, но все равно простым:
let {user_name: username, text: roll} = req.body;
В качестве последнего примера вы также можете деструктурировать вложенные данные. Следующий фрагмент назначит «Что такое 42?» на question
и "Ответ на жизнь, вселенную и все остальное" на correctAnswer
:
let data = { question: ‘What is 42?’, answers: [‘6 times 7’, ‘The answer to life, the universe, and everything’, ‘How many engineers it takes to change a lightbulb’] }; let {question, answers: [,correctAnswer,]} = data;
Это основы деструктуризации в ES6! Если вы хотите узнать больше, я рекомендую вам ознакомиться с MDN или, если вам нравится более глубокое погружение, со Спецификацией ES6 по этому вопросу.