Автор выбрал COVID-19 Relief Fund для получения пожертвования в рамках программы Write for DOnations.
Многие функции для работы с массивами и объектами были добавлены в язык JavaScript после выпуска спецификации ECMAScript версии 2015. В этой статье мы расскажем о деструктурировании, параметрах rest и синтаксисе spread. Они открывают возможность более прямого доступа к элементам массива или объекта и делают работу с этими структурами данных более быстрой и лаконичной.
Во многих других языках отсутствует аналогичный синтаксис для деструктурирования, параметров rest и spread, и поэтому данные функции будет полезно изучить как начинающим разработчикам JavaScript, так и тем, кто переходит на JavaScript с другого языка. В этой статье мы расскажем о деструктурировании объектов и массивов, использовании оператора spread для распаковки объектов и массивов и использовании параметров rest при вызове функций.
Синтаксис деструктурирования позволяет задавать свойства объектов и элементы массива как переменные. Это значительно сокращает количество строк кода, необходимых для манипулирования данными в этих структурах. Существует два типа деструктурирования: деструктурирование объектов и деструктурирование массивов.
Деструктурирование объектов позволяет создавать новые переменные, используя свойство объекта как значение.
Рассмотрим пример объекта, представляющего собой заметку со свойствами id
, title
и date
:
const note = {
id: 1,
title: 'My first note',
date: '01/01/1970',
}
Обычно при создании новой переменной для каждого свойства нужно задавать каждую переменную отдельно, используя много повторов:
// Create variables from the Object properties
const id = note.id
const title = note.title
const date = note.date
С деструктурированием объектов можно уложиться в одну строку. При заключении каждой переменной в фигурные скобки {}
JavaScript создаст новые переменные из каждого свойства с тем же именем:
// Destructure properties into variables
const { id, title, date } = note
Запустите console.log()
для новых переменных:
console.log(id)
console.log(title)
console.log(date)
На экран будут выведены начальные значения свойств:
Output1
My first note
01/01/1970
Примечание. Деструктурирование объекта не изменяет первоначальный объект. Вы все равно можете вызвать первоначальный объект note
со всеми исходными записями.
При деструктурировании объектов создаются новые переменные с теми же именами, что и у свойств объекта. Если вы не хотите, чтобы имя новой переменной совпадало с именем свойства, вы можете переименовать новую переменную, используя двоеточие (:
) для ввода нового имени, как показано в следующем примере с noteId
:
// Assign a custom name to a destructured value
const { id: noteId, title, date } = note
Зарегистрируйте новую переменную noteId
в консоли:
console.log(noteId)
Результат будет выглядеть следующим образом:
Output1
Также вы можете деструктурировать значения вложенных объектов. Например, обновите объект note
так, чтобы у него был вложенный объект author
:
const note = {
id: 1,
title: 'My first note',
date: '01/01/1970',
author: {
firstName: 'Sherlock',
lastName: 'Holmes',
},
}
Теперь вы можете деструктурировать объект note
, а затем провести деструктурирование еще раз, чтобы создать переменные из свойств объекта author
:
// Destructure nested properties
const {
id,
title,
date,
author: { firstName, lastName },
} = note
Затем зарегистрируйте новые переменные firstName
и lastName
, используя литерали шаблонов:
console.log(`${firstName} ${lastName}`)
Результат будет выглядеть следующим образом:
OutputSherlock Holmes
В этом примере у вас есть доступ к содержимому объекта author
, но сам объект author
остается недоступным. Для доступа к объекту и его вложенным значениям их следует декларировать отдельно:
// Access object and nested values
const {
author,
author: { firstName, lastName },
} = note
console.log(author)
Этот код выводит объект author
:
Output{firstName: "Sherlock", lastName: "Holmes"}
Деструктурирование объекта полезно не только для сокращения объема кода, но также позволяет организовать целевой доступ к важным свойствам.
Кроме того, деструктурирование можно использовать для доступа к свойствам объектов значений примитивов. Например, String — это глобальный объект для строк, и он имеет свойство length
:
const { length } = 'A string'
Эта команда находит изначальное свойство длины строки и задает для него переменную length
. Зарегистрируйте length
, чтобы проверить, сработало ли это:
console.log(length)
Результат будет выглядеть следующим образом:
Output8
Строка A string
была косвенно конвертирована в объект для получения свойства length
.
Деструктурирование массивов позволяет создавтаь новые переменные, используя элементы массива в качестве значения. В качестве примера рассмотрим массив с разными компонентами даты:
const date = ['1970', '12', '01']
Массивы в JavaScript гарантированно сохраняют порядок, и поэтому первым индексом всегда будет год, вторым — месяц и т. д. Зная это, вы можете создавать переменные из элементов массива:
// Create variables from the Array items
const year = date[0]
const month = date[1]
const day = date[2]
Если делать это вручную, вам потребуется большой объем кода. Деструктурирование массивов позволяет распаковать значения массива по порядку и присвоить им собственные переменные, как показано здесь:
// Destructure Array values into variables
const [year, month, day] = date
Зарегистрируйте новые переменные в журнале:
console.log(year)
console.log(month)
console.log(day)
Результат будет выглядеть следующим образом:
Output1970
12
01
Значения можно пропускать,оставляя пустой синтаксис деструктурирования между запятыми:
// Skip the second item in the array
const [year, , day] = date
console.log(year)
console.log(day)
При запуске этого кода будут указаны значения year
и day
:
Output1970
01
Вложенные массивы также можно деструктурировать. Вначале создайте вложенный массив:
// Create a nested array
const nestedArray = [1, 2, [3, 4], 5]
Затем деструктурируйте массив и зарегистрируйте новые переменные:
// Destructure nested items
const [one, two, [three, four], five] = nestedArray
console.log(one, two, three, four, five)
Результат будет выглядеть следующим образом:
Output1 2 3 4 5
Синтаксис деструктурирования можно применять для деструктурирования параметров функции. Для тестирования вам нужно будет деструктурировать ключи
и значения
из Object.entries()
.
Вначале декларируйте объект note
:
const note = {
id: 1,
title: 'My first note',
date: '01/01/1970',
}
Для этого объекта вы можете указать пары ключ-значение, деструктурируя аргументы по мере их передачи в метод forEach()
:
// Using forEach
Object.entries(note).forEach(([key, value]) => {
console.log(`${key}: ${value}`)
})
Также вы можете использовать для этой цели цикл for
:
// Using a for loop
for (let [key, value] of Object.entries(note)) {
console.log(`${key}: ${value}`)
}
В каждом случае вы получите следующий результат:
Outputid: 1
title: My first note
date: 01/01/1970
Деструктурирование объектов и деструктурирование массивов можно комбинировать в одном выражении деструктурирования. При деструктурировании также можно использовать параметры по умолчанию, как видно из этого примера, где задается дата по умолчанию new Date()
.
Вначале декларируйте объект note
:
const note = {
title: 'My first note',
author: {
firstName: 'Sherlock',
lastName: 'Holmes',
},
tags: ['personal', 'writing', 'investigations'],
}
Затем деструктурируйте объект и задайте новую переменную new со
значением по умолчанию new Date()
:
const {
title,
date = new Date(),
author: { firstName },
tags: [personalTag, writingTag],
} = note
console.log(date)
Команда console.log(date)
выведет на экран примерно следующее:
OutputFri May 08 2020 23:53:49 GMT-0500 (Central Daylight Time)
Как показано в этом разделе, синтаксис деструктурирования добавляет в JavaScript гибкость и позволяет создавать более лаконичный код. В следующем разделе мы покажем, как использовать синтаксис spread для раскрытия структур данных с выводом составляющих их записей данных.
Синтаксис Spread (...
) — это еще одно полезное дополнение JavaScript для работы с массивами, объектами и вызовами функций. Spread позволяет распаковывать или раскрывать объекты и элементы итерации (например, массивы) и использовать их для создания копий структур данных с целью упрощения манипуляций с данными.
Spread упрощает выполнение распространенных задач с массивами. Допустим, у нас есть два массива и мы хотим их комбинировать:
// Create an Array
const tools = ['hammer', 'screwdriver']
const otherTools = ['wrench', 'saw']
Раньше нам нужно было бы использовать concat()
для сокращения двух массивов:
// Concatenate tools and otherTools together
const allTools = tools.concat(otherTools)
Теперь мы также можем использовать spread для распаковки массивов в новый массив:
// Unpack the tools Array into the allTools Array
const allTools = [...tools, ...otherTools]
console.log(allTools)
Результат выполнения будет выглядеть так:
Output["hammer", "screwdriver", "wrench", "saw"]
Это особенно полезно в случае неизменяемых объектов. Например, вы можете работать с приложением, которое сохранило объект users
в массиве объектов:
// Array of users
const users = [
{ id: 1, name: 'Ben' },
{ id: 2, name: 'Leslie' },
]
Вы можете использовать push
для изменения массива и добавления нового пользователя, если это изменяемый объект:
// A new user to be added
const newUser = { id: 3, name: 'Ron' }
users.push(newUser)
Однако при этом изменяется массив user
, что может быть для нас нежелательно.
Spread позволяет создать новый массив из существующего и добавить в его конец новый элемент:
const updatedUsers = [...users, newUser]
console.log(users)
console.log(updatedUsers)
Теперь в новый массив updatedUsers
добавлен новый пользователь, а первоначальный массив users
остался без изменений:
Output[{id: 1, name: "Ben"}
{id: 2, name: "Leslie"}]
[{id: 1, name: "Ben"}
{id: 2, name: "Leslie"}
{id: 3, name: "Ron"}]
Создание копий данных вместо изменения имеющихся данных помогает предотвратить неожиданные изменения. При создании в JavaScript объекта или массива и присвоения его другой переменной вы на самом деле не создаете новый объект, а передаете ссылку.
Рассмотрим этот пример, где мы создаем массив и назначаем его другой переменной:
// Create an Array
const originalArray = ['one', 'two', 'three']
// Assign Array to another variable
const secondArray = originalArray
При удалении последнего элемента второго массива изменится первый:
// Remove the last item of the second Array
secondArray.pop()
console.log(originalArray)
Результат будет выглядеть следующим образом:
Output["one", "two"]
Spread позволяет делать простую копию массива или объекта, где будут клонированы все свойства верхнего уровня, а вложенные объекты будут передаваться посредством ссылки. Такой простой копии может быть достаточно для простых массивов или объектов.
Если вы напишете тот же код, но при этом скопируете массив с помощью spread, первоначальный массив больше не будет меняться:
// Create an Array
const originalArray = ['one', 'two', 'three']
// Use spread to make a shallow copy
const secondArray = [...originalArray]
// Remove the last item of the second Array
secondArray.pop()
console.log(originalArray)
На консоли будет зарегистрировано следующее:
Output["one", "two", "three"]
Spread также можно использовать для конвертации набора или другого элемента с итерацией в массив.
Создайте новый набор и добавьте в него записи:
// Create a set
const set = new Set()
set.add('octopus')
set.add('starfish')
set.add('whale')
Используйте оператор spread с set
и зарегистрируйте результаты:
// Convert Set to Array
const seaCreatures = [...set]
console.log(seaCreatures)
В результате вы получите следующий вывод:
Output["octopus", "starfish", "whale"]
Это также может быть полезно при создании массива из строки:
const string = 'hello'
const stringArray = [...string]
console.log(stringArray)
Это даст нам массив, где каждый символ будет элементом массива:
Output["h", "e", "l", "l", "o"]
При работе с объектами spread можно использовать для их копирования и обновления.
Изначально для копирования объектов использовался Object.assign()
:
// Create an Object and a copied Object with Object.assign()
const originalObject = { enabled: true, darkMode: false }
const secondObject = Object.assign({}, originalObject)
Теперь secondObject
будет клоном originalObject
.
Синтаксис spread все упрощает, позволяя создать простую копию объекта посредством его передачи в новый объект:
// Create an object and a copied object with spread
const originalObject = { enabled: true, darkMode: false }
const secondObject = { ...originalObject }
console.log(secondObject)
Результат будет выглядеть следующим образом:
Output{enabled: true, darkMode: false}
Как и в случае с массивами при этом создается простая копия, где вложенные объекты будут передаваться посредством ссылки.
Spread упрощает добавление и изменение свойств существующего неизменяемого объекта. В этом примере мы добавляем свойство isLoggedIn
в объект user
:
const user = {
id: 3,
name: 'Ron',
}
const updatedUser = { ...user, isLoggedIn: true }
console.log(updatedUser)
В результате вы получите следующий вывод:
Output{id: 3, name: "Ron", isLoggedIn: true}
При обновлении объектов с помощью spread важно учитывать, что каждый вложенный объект также потребуется передать. Рассмотрим пример, когда в объекте user
содержится вложенный объект organization
:
const user = {
id: 3,
name: 'Ron',
organization: {
name: 'Parks & Recreation',
city: 'Pawnee',
},
}
Если мы попробуем добавить новый элемент в объект organization
, существующие поля будут перезаписаны:
const updatedUser = { ...user, organization: { position: 'Director' } }
console.log(updatedUser)
Результат будет выглядеть следующим образом:
Outputid: 3
name: "Ron"
organization: {position: "Director"}
Если изменяемость неважна, поле можно обновить напрямую:
user.organization.position = 'Director'
Однако нам нужно изменяемое решение, и мы используем spread для копирования внутреннего объекта для сохранения имеющихся свойств:
const updatedUser = {
...user,
organization: {
...user.organization,
position: 'Director',
},
}
console.log(updatedUser)
В результате вы получите следующий вывод:
Outputid: 3
name: "Ron"
organization: {name: "Parks & Recreation", city: "Pawnee", position: "Director"}
Spread также можно использовать с аргументами в вызовах функций.
Например, у нас имеется функция multiply
, которая берет три параметра и умножает их:
// Create a function to multiply three items
function multiply(a, b, c) {
return a * b * c
}
Обычно мы передаем три переменных по отдельности как аргументы вызова функции, примерно так:
multiply(1, 2, 3)
Результат будет выглядеть следующим образом:
Output6
Однако если все значения, которые вы хотите передать функции, уже существуют в массиве, синтаксис syntax позволит использовать каждый элемент массива в качестве аргумента:
const numbers = [1, 2, 3]
multiply(...numbers)
Это даст тот же результат:
Output6
Примечание. Без spread этого можно добиться с помощью apply()
:
multiply.apply(null, [1, 2, 3])
Это даст нам следующее:
Output6
Теперь вы увидели, как можно использовать spread для сокращения кода и можете рассмотреть другой вариант использовать параметров ...
синтаксиса: rest.
В последнюю очередь в этой статье мы расскажем о синтаксисе параметра rest. Синтаксис аналогичен синтаксису spread (...
), но имеет противоположный эффект. Вместо распаковки массива или объекта на отдельные значения синтаксис rest создаст массив с неограниченным количеством аргументов.
Например, если в функции restTest
мы захотим использовать массив args
, состоящий из неограниченного количества аргументов, мы получим следующее:
function restTest(...args) {
console.log(args)
}
restTest(1, 2, 3, 4, 5, 6)
Все аргументы, переданные в функцию restTest
, теперь доступны в массиве args
:
Output[1, 2, 3, 4, 5, 6]
Синтаксис Rest можно использовать как единственный параметр или как последний параметр в списке. Если его использовать как единственный паарметр, он соберет все аргументы, но в конце списка он соберет все остающиеся аргументы, как показано в этом примере:
function restTest(one, two, ...args) {
console.log(one)
console.log(two)
console.log(args)
}
restTest(1, 2, 3, 4, 5, 6)
При этом будут отдельно приниматься два аргумента, а остальные будут сгруппированы в массив:
Output1
2
[3, 4, 5, 6]
В более старом коде переменную arguments
можно было бы использовать для сбора всех аргументов, передаваемых в функцию:
function testArguments() {
console.log(arguments)
}
testArguments('how', 'many', 'arguments')
Результат выглядел бы так:
[secondary_label Output]1
Arguments(3) ["how", "many", "arguments"]
Однако такой подход имеет ряд недостатков. Во первых, переменную arguments
нельзя использовать со стрелочными функциями.
const testArguments = () => {
console.log(arguments)
}
testArguments('how', 'many', 'arguments')
При этом будет возникать ошибка:
OutputUncaught ReferenceError: arguments is not defined
Кроме того, arguments
не является истинным массивом и не может использовать такие методы как map
и filter
без предварительной конвертации в массив. Он будет собирать все передаваемые аргументы, а не только остальные аргументы, как показано в примере restTest(one, two, ...args)
.
Rest можно использовать и при деструктурировании массивов:
const [firstTool, ...rest] = ['hammer', 'screwdriver', 'wrench']
console.log(firstTool)
console.log(rest)
Это даст нам следующее:
Outputhammer
["screwdriver", "wrench"]
Также Rest можно использовать при деструктурировании объектов:
const { isLoggedIn, ...rest } = { id: 1, name: 'Ben', isLoggedIn: true }
console.log(isLoggedIn)
console.log(rest)
Результат будет выглядеть так:
Outputtrue
{id: 1, name: "Ben"}
Таким образом, синтаксис rest дает эффективные методы для сбора неопределенного количества элементов.
В этой статье мы рассказали о деструктурировании, синтаксисе spread и параметрах rest. Краткое содержание:
Деструктурирование, параметры rest и синтаксис spread — полезные функции JavaScript, позволяющие сохранять код лаконичным и чистым.
Если вы хотите увидеть деструктурирование в действии, пройдите обучающий модуль «Настройка компонентов React с помощью Props», где этот синтаксис используется для деструктурирования данных и их передачи компонентам клиентской части. Если вы хотите узнать больше о JavaScript, вернитесь на страницу серии статей по программированию на JavaScript.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.