Кратко
Секция статьи "Кратко"Спред-синтаксис (spread)
позволяет передавать итерируемые коллекции (например, массивы или строки) как список аргументов функции или добавлять содержащиеся в них элементы в новый массив.
Спред применятся и для объектов, чтобы копировать пары ключ-значение из одного объекта в другой.
Пример
Секция статьи "Пример"При вызове функции использовать значения из массива как аргументы:
function multiplyThreeNumbers(a, b, c) { return a * b * c}const nums = [1, 2, 3]console.log(multiplyThreeNumbers(...nums))// 6
function multiplyThreeNumbers(a, b, c) { return a * b * c } const nums = [1, 2, 3] console.log(multiplyThreeNumbers(...nums)) // 6
В массиве скопировать элементы из другого массива в новый:
const donor = ['это', 'старые', 'значения']const newArray = [...donor, 1, true, 'мама']console.log(newArray)// ['это', 'старые', 'значения', 1, true, 'мама']
const donor = ['это', 'старые', 'значения'] const newArray = [...donor, 1, true, 'мама'] console.log(newArray) // ['это', 'старые', 'значения', 1, true, 'мама']
У объекта скопировать свойства из другого объекта в новый:
const persona = { name: 'Иван', lastName: 'Объектов'}const userData = { ...persona, username: 'killer3000' }console.log(userData)// {// name: "Иван",// lastName: "Объектов",// username: "killer3000"// }
const persona = { name: 'Иван', lastName: 'Объектов'} const userData = { ...persona, username: 'killer3000' } console.log(userData) // { // name: "Иван", // lastName: "Объектов", // username: "killer3000" // }
Как понять
Секция статьи "Как понять"Спред-синтаксис легче всего изучать на примерах. Есть три контекста, в которых он применяется.
При вызове функции
Секция статьи "При вызове функции"Часто встречается ситуация, когда мы хотим использовать данные из итерируемой коллекции в качестве аргументов функции. Чаще всего такая коллекция — массив. Если функция не умеет принимать массив аргументом, то придётся доставать элементы вручную:
function multiplyThreeNumbers(a, b, c) { return a * b * c}const nums = [1, 2, 3]console.log(multiplyThreeNumbers(nums[0], nums[1], nums[2]))// 6
function multiplyThreeNumbers(a, b, c) { return a * b * c } const nums = [1, 2, 3] console.log(multiplyThreeNumbers(nums[0], nums[1], nums[2])) // 6
Если элементов становится больше, доставать значения вручную становится неудобно. Чтобы решить эту проблему, в старых версиях языка использовали метод apply
. Этот метод принимает первым аргументом значение this
, а вторым — список аргументов для вызова функции:
function multiplyThreeNumbers(a, b, c) { return a * b * c}const nums = [1, 2, 3]console.log(multiplyThreeNumbers.apply(null, nums))// 6
function multiplyThreeNumbers(a, b, c) { return a * b * c } const nums = [1, 2, 3] console.log(multiplyThreeNumbers.apply(null, nums)) // 6
Такой синтаксис сложно читается, его нельзя использовать при создании объектов с помощью конструктора new
. Его упростили до спред-синтаксиса. В этом случае элементы как бы выкладываются из списка в нужном порядке:
function multiplyThreeNumbers(a, b, c) { return a * b * c}const nums = [1, 2, 3]console.log(multiplyThreeNumbers(...nums))// 6
function multiplyThreeNumbers(a, b, c) { return a * b * c } const nums = [1, 2, 3] console.log(multiplyThreeNumbers(...nums)) // 6
Если в массиве будет больше элементов, чем параметров функции, то будут использованы только те элементы, которые идут первыми по порядку:
function multiplyThreeNumbers(a, b, c) { return a * b * c}const nums = [1, 2, 3, 5, 6]console.log(multiplyThreeNumbers(...nums))// 6
function multiplyThreeNumbers(a, b, c) { return a * b * c } const nums = [1, 2, 3, 5, 6] console.log(multiplyThreeNumbers(...nums)) // 6
При создании массивов с помощью литерала []
Секция статьи "При создании массивов с помощью литерала []" Спред-синтаксис решает задачу создания нового массива с использованием данных из другого массива. Без него неудобно создавать массив, который содержит элементы другого. Приходится использовать методы массива, например, concat
:
const watchedMovies = ['Rocky', 'Terminator 2', 'The Matrix']const watchedVideos = ['Rick&Morty', 'lofi hip hop radio'].concat(watchedMovies)console.log(watchedVideos)// ['Rick&Morty', 'lofi hip hop radio', 'Rocky', 'Terminator 2', 'The Matrix']
const watchedMovies = ['Rocky', 'Terminator 2', 'The Matrix'] const watchedVideos = ['Rick&Morty', 'lofi hip hop radio'].concat(watchedMovies) console.log(watchedVideos) // ['Rick&Morty', 'lofi hip hop radio', 'Rocky', 'Terminator 2', 'The Matrix']
Спред решает эту проблему лучше:
const watchedMovies = ['Rocky', 'Terminator 2', 'The Matrix']const watchedVideos = ['Rick&Morty', 'lofi hip hop radio', ...watchedMovies]console.log(watchedVideos)// ['Rick&Morty', 'lofi hip hop radio', 'Rocky', 'Terminator 2', 'The Matrix']
const watchedMovies = ['Rocky', 'Terminator 2', 'The Matrix'] const watchedVideos = ['Rick&Morty', 'lofi hip hop radio', ...watchedMovies] console.log(watchedVideos) // ['Rick&Morty', 'lofi hip hop radio', 'Rocky', 'Terminator 2', 'The Matrix']
Таким образом можно создать копию существующего массива:
const watchedMovies = ['Rocky', 'Terminator 2', 'The Matrix']const myWatchedMovies = [...watchedMovies]
const watchedMovies = ['Rocky', 'Terminator 2', 'The Matrix'] const myWatchedMovies = [...watchedMovies]
Или склеить несколько массивов в один:
const movies = ['Rocky', 'Terminator 2', 'The Matrix']const series = ['Prison Break', 'Rick&Morty', 'Lost']const watched = [...movies, ...series]// [// "Rocky",// "Terminator 2",// "The Matrix",// "Prison Break",// "Rick&Morty",// "Lost"// ]
const movies = ['Rocky', 'Terminator 2', 'The Matrix'] const series = ['Prison Break', 'Rick&Morty', 'Lost'] const watched = [...movies, ...series] // [ // "Rocky", // "Terminator 2", // "The Matrix", // "Prison Break", // "Rick&Morty", // "Lost" // ]
Пример поведения с уровнем вложенности больше одного:
const users = [{ name: 'Иван', lastName: 'Объектов' }]const copyUsers = [...users]copyUsers[0].name = 'Николай'console.log(users[0])// { name: 'Николай', lastName: 'Объектов' }
const users = [{ name: 'Иван', lastName: 'Объектов' }] const copyUsers = [...users] copyUsers[0].name = 'Николай' console.log(users[0]) // { name: 'Николай', lastName: 'Объектов' }
При создании объекта с помощью литерала {}
Секция статьи "При создании объекта с помощью литерала {}" По аналогии с массивами, спред-синтаксис решает проблему копирования свойств в новый объект. В версии языка без спреда для копирования использовался метод Object
, который принимал два объекта — куда копировать свойства и откуда:
const person = { name: 'Иван', lastName: 'Объектов' }const userData = Object.assign({ username: 'killer3000' }, person)console.log(userData)// {// name: "Иван",// lastName: "Объектов",// username: "killer3000"// }
const person = { name: 'Иван', lastName: 'Объектов' } const userData = Object.assign({ username: 'killer3000' }, person) console.log(userData) // { // name: "Иван", // lastName: "Объектов", // username: "killer3000" // }
Спред упрощает код и делает его читабельнее:
const person = { name: 'Иван', lastName: 'Объектов' }const userData = { username: 'killer3000', ...person }console.log(userData)// {// name: "Иван",// lastName: "Объектов",// username: "killer3000"// }
const person = { name: 'Иван', lastName: 'Объектов' } const userData = { username: 'killer3000', ...person } console.log(userData) // { // name: "Иван", // lastName: "Объектов", // username: "killer3000" // }
Если свойства в новом и старом объекте совпадают, то будет использоваться то значение свойства, которое шло последним:
const person = { name: 'Иван', lastName: 'Объектов' }const userData = { name: 'Николай', ...person }console.log(userData)// { name: "Иван", lastName: "Объектов" }
const person = { name: 'Иван', lastName: 'Объектов' } const userData = { name: 'Николай', ...person } console.log(userData) // { name: "Иван", lastName: "Объектов" }
Если поставить спред в начало, то будет использоваться новое имя:
const person = { name: 'Иван', lastName: 'Объектов' }const userData = { ...person, name: 'Николай' }console.log(userData)// { name: "Николай", lastName: "Объектов" }
const person = { name: 'Иван', lastName: 'Объектов' } const userData = { ...person, name: 'Николай' } console.log(userData) // { name: "Николай", lastName: "Объектов" }
На практике
Секция статьи "На практике"🛠 Спред на объектах используют в библиотеке React. Программист может передать в функцию объект с произвольными свойствами, но мы хотим запретить устанавливать некоторые из них. В этом случае создаётся новый объект, в который сначала копируются присланные значения, а потом значения «запрещённых» свойств. В этом случае даже если запрещённое свойство было передано, оно будет перезаписано:
function Headline(props) { const filteredProps = {...props, ariaHidden: false} return createElement('h1', filteredProps, 'Текст заголовка')}
function Headline(props) { const filteredProps = {...props, ariaHidden: false} return createElement('h1', filteredProps, 'Текст заголовка') }