Деструктуризация
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/destructuring-assignment.
Деструктуризация (destructuring assignment) – это особый синтаксис присваивания, при котором можно присвоить массив или объект сразу нескольким переменным, разбив его на части.
Массив
Пример деструктуризации массива:
'use strict'; let [firstName, lastName] = ["Илья", "Кантор"]; alert(firstName); // Илья alert(lastName); // Кантор
При таком присвоении первое значение массива пойдёт в переменную firstName , второе – в lastName , а последующие (если есть) – будут отброшены.
Ненужные элементы массива также можно отбросить, поставив лишнюю запятую:
'use strict'; // первый и второй элементы не нужны let [, , title] = "Юлий Цезарь Император Рима".split(" "); alert(title); // Император
В коде выше первый и второй элементы массива никуда не записались, они были отброшены. Как, впрочем, и все элементы после третьего.
Оператор «spread»
Если мы хотим получить и последующие значения массива, но не уверены в их числе – можно добавить ещё один параметр, который получит «всё остальное», при помощи оператора «. » («spread», троеточие):
'use strict'; let [firstName, lastName, . rest] = "Юлий Цезарь Император Рима".split(" "); alert(firstName); // Юлий alert(lastName); // Цезарь alert(rest); // Император,Рима (массив из 2х элементов)
Значением rest будет массив из оставшихся элементов массива. Вместо rest можно использовать и другое имя переменной, оператор здесь – троеточие. Оно должно стоять только последним элементом в списке слева.
Значения по умолчанию
Если значений в массиве меньше, чем переменных – ошибки не будет, просто присвоится undefined :
'use strict'; let [firstName, lastName] = []; alert(firstName); // undefined
Впрочем, как правило, в таких случаях задают значение по умолчанию. Для этого нужно после переменной использовать символ = со значением, например:
'use strict'; // значения по умолчанию let [firstName="Гость", lastName="Анонимный"] = []; alert(firstName); // Гость alert(lastName); // Анонимный
В качестве значений по умолчанию можно использовать не только примитивы, но и выражения, даже включающие в себя вызовы функций:
'use strict'; function defaultLastName() < return Date.now() + '-visitor'; >// lastName получит значение, соответствующее текущей дате: let [firstName, lastName=defaultLastName()] = ["Вася"]; alert(firstName); // Вася alert(lastName); // 1436. -visitor
Заметим, что вызов функции defaultLastName() для генерации значения по умолчанию будет осуществлён только при необходимости, то есть если значения нет в массиве.
Деструктуризация объекта
Деструктуризацию можно использовать и с объектами. При этом мы указываем, какие свойства в какие переменные должны «идти».
Объект справа – уже существующий, который мы хотим разбить на переменные. А слева – список переменных, в которые нужно соответствующие свойства записать.
'use strict'; let options = < title: "Меню", width: 100, height: 200 >; let = options; alert(title); // Меню alert(width); // 100 alert(height); // 200
Как видно, свойства options.title , options.width и options.height автоматически присвоились соответствующим переменным.
Если хочется присвоить свойство объекта в переменную с другим именем, например, чтобы свойство options.width пошло в переменную w , то можно указать соответствие через двоеточие, вот так:
'use strict'; let options = < title: "Меню", width: 100, height: 200 >; let = options; alert(title); // Меню alert(w); // 100 alert(h); // 200
В примере выше свойство width отправилось в переменную w , свойство height – в переменную h , а title – в переменную с тем же названием.
Если каких-то свойств в объекте нет, можно указать значение по умолчанию через знак равенства = , вот так;
'use strict'; let options = < title: "Меню" >; let = options; alert(title); // Меню alert(width); // 100 alert(height); // 200
Можно и сочетать одновременно двоеточие и равенство:
'use strict'; let options = < title: "Меню" >; let = options; alert(title); // Меню alert(w); // 100 alert(h); // 200
А что, если в объекте больше значений, чем переменных? Можно ли куда-то присвоить «остаток», аналогично массивам?
Такой возможности в текущем стандарте нет. Она планируется в будущем стандарте, и выглядеть она будет примерно так:
'use strict'; let options = < title: "Меню", width: 100, height: 200 >; let = options; // title = "Меню" // size = < width: 100, height: 200>(остаток)
Этот код будет работать, например, при использовании Babel со включёнными экспериментальными возможностями, но ещё раз заметим, что в текущий стандарт такая возможность не вошла.
Деструктуризация без объявления
В примерах выше переменные объявлялись прямо перед присваиванием: let = . Конечно, можно и без let , использовать уже существующие переменные.
Однако, здесь есть небольшой «подвох». В JavaScript, если в основном потоке кода (не внутри другого выражения) встречается <. >, то это воспринимается как блок.
Например, можно использовать такой блок для ограничения видимости переменных:
'use strict'; < // вспомогательные переменные, локальные для блока let a = 5; // поработали с ними alert(a); // 5 // больше эти переменные не нужны >alert(a); // ошибка нет такой переменной
Конечно, это бывает удобно, но в данном случае это создаст проблему при деструктуризации:
let a, b; = ; // будет ошибка, оно посчитает, что - блок
Чтобы избежать интерпретации как блока, нужно обернуть всё присваивание в скобки:
let a, b; ( = ); // внутри выражения это уже не блок
Вложенные деструктуризации
Если объект или массив содержат другие объекты или массивы, и их тоже хочется разбить на переменные – не проблема.
Деструктуризации можно как угодно сочетать и вкладывать друг в друга.
В коде ниже options содержит подобъект и подмассив. В деструктуризации ниже сохраняется та же структура:
'use strict'; let options = < size: < width: 100, height: 200 >, items: ["Пончик", "Пирожное"] > let < title="Меню", size: , items: [item1, item2] > = options; // Меню 100 200 Пончик Пирожное alert(title); // Меню alert(width); // 100 alert(height); // 200 alert(item1); // Пончик alert(item2); // Пирожное
Как видно, весь объект options корректно разбит на переменные.
Итого
- Деструктуризация позволяет разбивать объект или массив на переменные при присвоении.
- Синтаксис:
let = object
Здесь двоеточие : задаёт отображение свойства prop в переменную varName , а равенство =default задаёт выражение, которое будет использовано, если значение отсутствует (не указано или undefined ). Для массивов имеет значение порядок, поэтому нельзя использовать : , но значение по умолчанию – можно:
let [var1 = default, var2, . rest] = array
Как мы увидим далее, деструктуризации особенно удобны при чтении объектных параметров функций.
ES6: Реструктуризующее присваивание
Скорее всего, вы уже видели несколько примеров использования реструктуризующего присваивания, или destructuring. Данная синтаксическая конструкция используется для извлечения данных из массивов и объектов.
Чтобы вас не смущало такое хитрое название, можно представить процесс, не как разложение объекта или массива на его составляющие, а как простое структурированное присваивание. Проще всего понять новую синтаксическю конструкцию можно, рассмотрев пример из прошлого:
// Структурированное присваивание для массивов var arr = ['this', 'is', 'array']; var first = arr[0], second = arr[1], third = arr[2]; console.log(first, second, third); // this is array // Структурированное присваивание для объектов var obj = a: 'this', b: 'is', c: 'object' >; var a = obj.a, b = obj.b, c = obj.c; console.log(a, b, c); // this is object
Проще говоря, раньше приходилось записывать каждую переменную по отдельности вручную. А если приходилось иметь дело с динамическими данными, то могла понадобиться и ещё одна дополнительная переменная:
var f = function() return ['this', 'is', 'array']; >; var tmp = f(), first = tmp[0], second = tmp[1], third = tmp[2]; console.log(first, second, third); // this is array
С релизом ES6 всё стало в разы проще:
var f = function() return ['this', 'is', 'array']; >; // ES6 destructuring для массивов var [ first, second, third ] = f(); console.log(first, second, third); // this is array
Destructuring с объектами
Создание нескольких переменных одновременно из объекта настолько же простое, как и из массива. Если вы хотите создать переменную с тем же именем, что и свойство объекта, то можно использовать сокращенную конструкцию:
var obj = a: 'this', b: 'is', c: 'object' >; var a, b, c > = obj; console.log(a, b, c); // this is object
В другом случае, когда имя переменной отличается от свойства, используется полный вариант:
var obj = a: 'this', b: 'is', c: 'object' >; var a: x, b: y, c: z > = obj; // Данные записаны в переменные x, y и z console.log(x, y, z); // this is object // Переменных a, b, c не существует console.log(a, b, c); // ReferenceError
Важно понимать отличие реструктуризующего присваивания от создания объекта с помощью литерала:
// Создание объекта var a = 10, b = 20; var obj = x: a, y: b >; console.log(obj.x, obj.y); // 10 20
Создавая объект с помощью литерала, вы следуете правилу: справа находится свойство, слева − значение < свойство: значение >. Подобное присваивание свойств интуитивно понятно, так как можно представить его, как обычное присваивание значение переменной переменная = значение .
Однако, когда вы используете реструктуризующее присваивание, названное выше правило действует в точности наоборот < значение: свойство >.
var a = 10, b = 20; var obj = x: a, y: b >; var x: A, y: B > = obj; console.log(A, B); // 10 20
В случае var obj = < x: a, y: b >x и y представляют свойства объекта. В случае var < x: A, y: B >= obj; x и y тоже представляют свойства.
Присваивание при отсутствии свойства
Если переданного вами свойства нет в объекте, то вы получите переменную, содержащую undefined :
var obj = a: 1 >; // у объекта нет свойства b var x: a, y: b > = obj; // переменной y будет присвоено undefined console.log(x, y); // 1 undefined
Вложенность
Реструктуризующее присваивание можно использовать с любым уровнем вложенности:
var o = zero: [ one: 1, two: 2 >, three: 3, four: 4 > ], five: 5 >; var zero: [ one: first >], five: fifth > = o; console.log(first, fifth); // 1 5
Обращение к свойствам примитивов
Примитивные значения не являются объектами, но обладают свойствами и методами, которые можно получить с помощью реструктуризующего присваивания:
var length: l, trim: t > = 'this is string'; console.log(l); // 14 console.log(t); // String.prototype.trim
Destructuring с массивами
Выше я уже рассматривал пример применения destructuring с массивами. В целом, применение достаточно схоже с объектами, за исключением двух ключевых особенностей:
Работает с любыми коллекциями
// Строки var [a, b, c] = 'xyz'; console.log(a, b, b); // x y z // Коллекции DOM элементов // Первые две ссылки со страницы var [link1, link2] = document.links; console.log(link1.tagName); // A console.log(link2.textContent); // текстовое содержание ссылки
Можно использовать оператор spread при присваивании
var [a, b, . c] = [1, 2, 3, 4, 5]; console.log(a, b, c); // 1 2 [3, 4, 5]
В данном случае переменные a и b получат соответственно значения 1 и 2 , а переменная c все оставшиеся значения в виде массива [3, 4, 5] .
Параметры по умолчанию
При использовании реструктуризующего присваивания можно задать параметры по умолчанию, на случай, если массив или объект не содержат присваиваемого свойства:
// Без параметра по умолчанию var [x, y, z] = [1, 2]; console.log(x, y, z); // 1 2 undefined // С использованием параметра по умолчанию var [x, y, z = 3] = [1, 2]; console.log(x, y, z); // 1 2 3
Также, как и в случае с функциями, в качестве параметра по умолчанию можно передать выполнение какой-либо функции:
var calc = function(num) return Math.pow(num, 2); >; var prop: x, pow: y = calc(x)> = prop: 4 >; console.log(x, y); // 4 16 var prop: x, pow: y = calc(x)> = prop: 4, pow: 10 >; console.log(x, y); // 4 10
Деструктурирующее присваивание
Синтаксис деструктурирующего присваивания в выражениях JavaScript позволяет извлекать данные из массивов или объектов при помощи синтаксиса, подобного объявлению массива или литералов в объекте.
Синтаксис
var a, b, rest; [a, b] = [1, 2]; console.log(a); // 1 console.log(b); // 2 [a, b, . rest] = [1, 2, 3, 4, 5]; console.log(a); // 1 console.log(b); // 2 console.log(rest); // [3, 4, 5] ( a, b > = a: 1, b: 2 >); console.log(a); // 1 console.log(b); // 2 ( a, b, . rest > = a: 1, b: 2, c: 3, d: 4 >); console.log(a); // 1 console.log(b); // 2 console.log(rest); //
Описание
Выражения объявления объектов или массивов предоставляют простой способ создания пакета однородных данных. При создании такого пакета вы получаете возможность использовать его любым доступным образом. Также вы можете возвращать его в функциях.
Одной из ключевых возможностей использования деструктурирующего присваивания является чтение структуры данных одним оператором, хотя помимо этого вы можете найти множество других применений в приведённых ниже примерах.
Данная возможность подобна таковой, присутствующей в языках Perl и Python.
Разбор массивов
Простой пример
var foo = ["one", "two", "three"]; // без деструктурирования var one = foo[0]; var two = foo[1]; var three = foo[2]; // с деструктурированием var [one, two, three] = foo;
Обмен значений переменных
После выполнения фрагмента кода, значение b будет 1, a будет 3. Без деструктурирующего присваивания, для обмена значений требуется дополнительная временная переменная (или что-то наподобие XOR-обмена).
var a = 1; var b = 3; [a, b] = [b, a];
Возврат нескольких значений
Благодаря деструктурирующему присваиванию, функции могут возвращать несколько значений. Хотя всегда можно было возвращать массивы в функциях, оно предоставляет гибкость:
function f() return [1, 2]; >
Как вы видите, возвращаемые результаты имеют вид массива, значения которого заключены в квадратные скобки. Вы можете возвращать неограниченное количество результатов таким образом. В следующем примере, f() возвращает [1, 2] как результат:
var a, b; [a, b] = f(); console.log("A is " + a + " B is " + b);
Оператор [a, b] = f() присваивает результаты функции переменным в квадратных скобках: a будет присвоено 1, b будет присвоено 2.
Вы также можете использовать результат функции в виде массива:
var a = f(); console.log("A is " + a);
В данном случае a будет массивом с элементами 1 и 2.
Игнорирование некоторых значений
Вы также можете проигнорировать не нужные значения:
function f() return [1, 2, 3]; > var [a, , b] = f(); console.log("A is " + a + " B is " + b);
После выполнения кода, a будет 1, b будет 3. Значение 2 игнорируется. Таким же образом вы можете игнорировать любые (или все) значения. Например:
Получение значений из результата регулярного выражения
Когда метод exec() регулярного выражения находит совпадение, он возвращает массив, содержащий первый совпадающий фрагмент строки и далее группы, определённые в регулярном выражении. Деструктурирующее присваивание упрощает получение данных из этих групп, игнорируя первый фрагмент:
var url = "https://developer.mozilla.org/en-US/Web/JavaScript"; var parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(url); var [, protocol, fullhost, fullpath] = parsedURL; console.log(protocol); // выведет "https"
Разбор объектов
Простой пример
var o = p: 42, q: true >; var p, q > = o; console.log(p); // 42 console.log(q); // true // Объявление новых переменных var p: foo, q: bar > = o; console.log(foo); // 42 console.log(bar); // true
Загрузка модулей
Деструктурирующее присваивание помогает загружать специфичные наборы модулей, как в Add-on SDK:
const Loader, main > = require("toolkit/loader");
Вложенный объект и разбор массива
var metadata = title: "Scratchpad", translations: [ locale: "de", localization_tags: [], last_edit: "2014-04-14T08:43:37", url: "/de/docs/Tools/Scratchpad", title: "JavaScript-Umgebung", >, ], url: "/ru/docs/Tools/Scratchpad", >; var title: englishTitle, translations: [ title: localeTitle >], > = metadata; console.log(englishTitle); // "Scratchpad" console.log(localeTitle); // "JavaScript-Umgebung"
Деструктурирование во время обхода
var people = [ name: "Mike Smith", family: mother: "Jane Smith", father: "Harry Smith", sister: "Samantha Smith", >, age: 35, >, name: "Tom Jones", family: mother: "Norah Jones", father: "Richard Jones", brother: "Howard Jones", >, age: 25, >, ]; for (var name: n, family: father: f >, > of people) console.log("Name: " + n + ", Father: " + f); > // "Name: Mike Smith, Father: Harry Smith" // "Name: Tom Jones, Father: Richard Jones"
Получение полей объекта-параметра функции
function userId( id >) return id; > function whois( displayName, fullName: firstName: name > >) console.log(displayName + " is " + name); > var user = id: 42, displayName: "jdoe", fullName: firstName: "John", lastName: "Doe", >, >; console.log("userId: " + userId(user)); // "userId: 42" whois(user); // "jdoe is John"
В приведённом примере извлекаются поля id , displayName и firstName из объекта пользователь.
Деструктурирование вычисляемых имён свойств
Вычисляемые имена свойств, например, литералы объектов, могут использоваться при деструктурирующем присваивании:
let key = "z"; let [key]: foo > = z: "bar" >; console.log(foo); // "bar"
Спецификации
Specification |
---|
ECMAScript Language Specification # sec-destructuring-assignment |
ECMAScript Language Specification # sec-destructuring-binding-patterns |
Совместимость с браузерами
BCD tables only load in the browser
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 7 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
MDN
Support
- Product help
- Report an issue
Our communities
Developers
- Web Technologies
- Learn Web Development
- MDN Plus
- Hacks Blog
- Website Privacy Notice
- Cookies
- Legal
- Community Participation Guidelines
Visit Mozilla Corporation’s not-for-profit parent, the Mozilla Foundation.
Portions of this content are ©1998– 2023 by individual mozilla.org contributors. Content available under a Creative Commons license.
Деструктуризация в JavaScript
Доброго времени суток, друзья. В данной статье мы разберем на примерах понятие деструктурирующего присваивания (destructuring assignment). Посмотрим, где его можно использовать, а также его преимущества по сравнению со старым синтаксисом выполнения аналогичных задач.
Что такое деструктуризация?
Само понятие деструктуризация (деструктурирующее присваивание) обозначает способ получения данных из массива или объекта путем использования специального синтаксиса. В чем его главная идея? Облегчить труд рядового разработчика и повысить скорость самой разработки путем написания меньшего кода. Давайте посмотрим сперва на саму проблему, решим ее стандартным способом, а затем воспользуемся деструктуризацией.
Деструктуризация массивов
Предположим что у нас есть массив простых строк.
const array = ["one", "two", "three"]
Для получения нужного элемента воспользуемся базовым способом, укажем индекс элемента в квадратных скобках.
console.log(array[0]) // ‘one’
Теперь воспользуемся деструктуризацией для решения этой же задачи. Для этого достаточно указать в квадратных скобках (по количеству элементов массива) переменные которые будут автоматически производить нам действие обращения по индексу
const array = ["one", "two", "three"] const [one, two, three] = array console.log(one) // ‘one’
Необязательно указывать каждый элемент в деструктуризации, можно просто отделить его запятыми. Например, для получения третьего элемента напишем следующий код.
const array = ["one", "two", "three"] const [, , three] = array console.log(three) // «three»
Деструктуризация позволяет нам присваивать значения по умолчанию, что часто бывает очень полезно. В момент реструктуризации для нужного элемента достаточно указать равно и написать его значение по умолчанию.
const array = [«one», «two», «three»] const [one, two, three, four] = array console.log(four) // undefined const [one, two, three, four = ‘four'] = array console.log(four) // ‘four’
Деструктуризация объектов
Помимо массивов очень удобно использовать деструктуризацию для получения нужных значений из объекта. Для этого нужно использовать фигурные строки по аналогии с массивами. Представим, что у нас есть следующий объект хранящий персональные данные.
const person = < name: «Vova», age: 24, hobbies: < sport: [‘boxing’, ‘swimming] >>
Для получения возраста достаточно воспользоваться точечной нотацией.
const age = person.age; console.log(age) // 24
Теперь используем деструктуризацию.
const < age >= person console.log(age) // 24
Помимо синтаксиса деструктуризация имеет ряд преимуществ:
1. Быстрое присваивание переменными других названий — достаточно указать новое название переменной после двоеточия.
const < name: firstName >= person console.log(firstName) // «Vova»
2. Присваивание значений по умолчанию, по аналогии с массивом — просто добавив после знака равно нужное значение.
const < street = "123" >= person // Такого поля нет в объекте console.log(street) // "123"
3. Деструктуризация вложенных элементов (объектов, массивов)
const < name, age, hobbies: < sport >> = person; console.log(sport[0]) // ‘boxing’
Заключение
Сегодня мы рассмотрели на практике использование деструктурирующего присваивания и погрузились в нюансы работы и «фишки», которые вы можете использовать на практике. Надеюсь, что данный материал был вам полезен. Учитесь, думайте, пишите код. Удачного кодинга, друзья!
Подписывайтесь на наш канал в Telegram и на YouTube для получения самой последней и актуальной информации.