От автора: назначение деструктурирования — звучит, как что-то очень сложное. Это напоминает мне объектно-ориентированные термины, такие как инкапсуляция и полиморфизм. Я убежден, что они были выбраны специально для того, чтобы простые концепции казались запредельно сложными!
По сути, назначение деструктурирования ECMAScript 6 (ES2015) позволяет извлекать отдельные элементы из массивов или объектов и помещать их в переменные с использованием сокращенного синтаксиса. Те, кто пришел из PHP, возможно, сталкивались с функцией list(), которая извлекает массивы в переменные за одну операцию. В ES6 объекты и массивы могут отдавать элементы иным способом.
Предположим, у нас есть массив:
1 |
var myArray = ['a', 'b', 'c']; |
В ES5 мы можем извлечь эти значения по индексу:
1 2 3 4 5 6 |
var one = myArray[0], two = myArray[1], three = myArray[2]; // один = 'a', два = 'b', три = 'c' |
Деструктурирование ES6 позволяет использовать более простую и менее подверженную ошибкам альтернативу:
1 2 3 |
const [one, two, three] = myArray; // один = 'a', два = 'b', три = 'c' |
Вы можете игнорировать определенные значения, например.
1 2 3 |
const [one, , three] = myArray; // один = 'a', три = 'c' |
или использовать оператор (…) для извлечения оставшихся элементов:
1 2 3 |
const [one, ...two] = myArray; // один = 'a', два = ['b, 'c'] |
Деструктурирование также работает с объектами, например.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var myObject = { one: 'a', two: 'b', three: 'c' }; // Пример ES5 var one = myObject.one, two = myObject.two, three = myObject.three; // один = 'a', два = 'b', три = 'c' // Пример деструктурирования ES6 const {one, two, three} = myObject; // один = 'a', два = 'b', три = 'c' |
В этом примере имена переменных one, two и three соответствуют именам свойств объектов. Мы также можем назначать свойства переменным с любым именем, например.
1 2 3 4 5 6 7 8 9 10 |
const myObject = { one: 'a', two: 'b', three: 'c' }; // Пример деструктурирования ES6 const {one: first, two: second, three: third} = myObject; // первая = 'a', вторая = 'b', третья = 'c' |
Более сложными вложенными объектами также могут быть ссылки, например.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
const meta = { title: 'Destructuring Assignment', authors: [ { firstname: 'Craig', lastname: 'Buckler' } ], publisher: { name: 'SitePoint', url: '//www.sitepoint.com/' } }; const { title: doc, authors: [{ firstname: name }], publisher: { url: web } } = meta; /* doc = 'Destructuring Assignment' name = 'Craig' web = '//www.sitepoint.com/' */ |
Это кажется сложным, но помните, что во всех назначениях деструктурирования:
левая часть назначения это цель деструктурирования — шаблон, который определяет назначаемые переменные
правая часть назначения это источник деструктурирования — массив или объект, который содержит извлеченные данные.
Существует ряд других предостережений. Во-первых, вы не можете запустить инструкцию с фигурной скобкой, потому что она выглядит как блок кода, например.
1 2 |
// не работает { a, b, c } = myObject; |
Вы должны либо объявить переменные, например:
1 2 |
// это работает const { a, b, c } = myObject; |
либо использовать круглые скобки, если переменные уже объявлены, например.
1 2 |
// это работает ({ a, b, c } = myObject); |
Вы также должны быть осторожными при смешивании объявленных и необъявленных переменных, например.
1 2 3 4 5 6 7 |
// не работает let a; let { a, b, c } = myObject; // работает let a, b, c; ({ a, b, c } = myObject); |
Это основные принципы деструктурирования. Так когда это может нам пригодиться? Я рад, что вы спросили …
Простое объявление
Переменные могут быть объявлены без явного определения каждого значения, например.
1 2 3 4 5 |
// ES5 var a = 'one', b = 'two', c = 'three'; // ES6 const [a, b, c] = ['one', 'two', 'three']; |
Правда, версия деструктурирования длиннее. Но она проще читается, хотя это может быть не так при наличии большого количества элементов.
Обмен значений переменных
Для обмена значений переменных в ES5 требуется временная третья переменная, но с деструктурированием это делается намного проще:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var a = 1, b = 2; // Обмен в ES5 var temp = a; a = b; b = temp; // a = 2, b = 1 // Обратный обмен в ES6 [a, b] = [b, a]; // a = 1, b = 2 |
Вы не ограничены двумя переменными; может быть перегруппировано любое количество элементов, например.
1 2 |
// ротация влево [b, c, d, e, a] = [a, b, c, d, e]; |
Параметры функции по умолчанию
Предположим, что у нас была функция для вывода объекта meta:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var meta = { title: 'Destructuring Assignment', authors: [ { firstname: 'Craig', lastname: 'Buckler' } ], publisher: { name: 'SitePoint', url: '//www.sitepoint.com/' } }; prettyPrint(meta); |
В ES5 необходимо парсировать этот объект, чтобы обеспечить соответствующие значения по умолчанию, например.
1 2 3 4 5 6 7 8 9 |
// Значения по умолчанию ES5 function prettyPrint(param) { param = param || {}; var pubTitle = param.title || 'No title', pubName = (param.publisher && param.publisher.name) || 'No publisher'; return pubTitle + ', ' + pubName; } |
В ES6 мы можем присвоить значение по умолчанию любому параметру, например.
1 2 |
// Значения по умолчанию ES6 function prettyPrint(param = {}) { |
но затем мы можем использовать деструктурирование для извлечения значений и при необходимости назначать значения по умолчанию:
1 2 3 4 5 6 7 8 9 |
// Деструктурированное значение по умолчанию ES6 function prettyPrint( { title: pubTitle = 'No title', publisher: { name: pubName = 'No publisher' } } = {} ) { return pubTitle + ', ' + pubName; } |
Я не уверен, что это легче читать, но это значительно короче.
Возврат из функции нескольких значений
Функции могут возвращать только одно значение, но это может быть сложный объект или многомерный массив. Назначение деструктурирования делает это более практичным, например.
1 2 3 4 5 6 7 |
function f() { return [1, 2, 3]; } const [a, b, c] = f(); // a = 1, b = 2, c = 3 |
Итерация for-of
Рассмотрим массив информации о книге:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const books = [ { title: 'Full Stack JavaScript', author: 'Colin Ihrig and Adam Bretz', url: '//www.sitepoint.com/store/full-stack-javascript-development-mean/' }, { title: 'JavaScript: Novice to Ninja', author: 'Darren Jones', url: '//www.sitepoint.com/store/leaern-javascript-novice-to-ninja/' }, { title: 'Jump Start CSS', author: 'Louis Lazaris', url: '//www.sitepoint.com/store/jump-start-css/' }, ]; |
for-of ES6 похож на for-in, за исключением того, что он извлекает каждое значение, а не индекс / ключ. Например.
1 2 3 |
for (const b of books) { console.log(b.title + ' by ' + b.author + ': ' + b.url); } |
Назначение деструктурирования обеспечивает дополнительные улучшения, например.
1 2 3 |
for (const {title, author, url} of books) { console.log(title + ' by ' + author + ': ' + url); } |
Обработка регулярных выражений
Функции регулярных выражений, такие как match, возвращают массив совпадающих элементов, которые могут стать источником назначения деструктурирования:
1 2 3 |
const [a, b, c, d] = 'one two three'.match(/\w+/g); // a = 'one', b = 'two', c = 'three', d = undefined |
Поддержка назначения деструктурирования
Назначение деструктурирования может не решить все вопросы, но это поможет вам сэкономить немало усилий! В настоящее время поддержка назначения деструктурирования довольно хороша. Оно доступно в Node и во всех основных браузерах, за исключением Internet Explorer. Если вам необходимо поддерживать старые браузеры, рекомендуется использовать компилятор, такой как Babel или Traceur, который переводит назначение деструктурирования ES6 в эквивалент ES5.
Автор: Craig Buckler
Источник: //www.sitepoint.com/
Редакция: Команда webformyself.