Кратко
СкопированоСпред-синтаксис (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, 'Текст заголовка') }
На собеседовании
Скопировано отвечает
СкопированоRest
- и spread
-операторы являются частью синтаксиса JavaScript. Они выполняют разные функции, хотя могут быть похожи в некоторых случаях. Давайте рассмотрим их отличия.
Оператор rest
(...
)
СкопированоRest
-оператор используется для сбора оставшихся аргументов функции в массив.
function sum(...args) { return args.reduce((total, num) => total + num, 0)}console.log(sum(1, 2, 3, 4))// 10
function sum(...args) { return args.reduce((total, num) => total + num, 0) } console.log(sum(1, 2, 3, 4)) // 10
Таким образом можно обрабатывать неизвестное количество аргументов, переданных в функцию.
Оператор spread
(...
)
СкопированоSpread
-оператор используется для распространения элементов массива или свойств объекта.
const arr1 = [1, 2, 3]const arr2 = [4, 5, 6]const combinedArray = [...arr1, ...arr2]console.log(combinedArray)// [1, 2, 3, 4, 5, 6]
const arr1 = [1, 2, 3] const arr2 = [4, 5, 6] const combinedArray = [...arr1, ...arr2] console.log(combinedArray) // [1, 2, 3, 4, 5, 6]
Оператор spread
также используется для создания поверхностных копий массивов или объектов.
const originalArray = [1, 2, 3]const copiedArray = [...originalArray]console.log(copiedArray)// [1, 2, 3]
const originalArray = [1, 2, 3] const copiedArray = [...originalArray] console.log(copiedArray) // [1, 2, 3]
Таким образом, основное отличие между rest
- и spread
-операторами заключается в их применении. Rest
используется для сбора аргументов в функции, тогда как spread
— для распространения элементов массивов или объектов.
отвечает
СкопированоОператоры spread
и rest
выглядят одинаково, как три точки — .
, но выполняют противоположные действия.
Что делает оператор rest
?
СкопированоСобирает оставшиеся аргументы функции в массив. Этот синтаксис используется при объявлении функции.
function doSomething(first, second, ...array) { console.log(first, second, array)}doSomething(1, 2, 3, 4, 5)// 1 2 [3, 4, 5]
function doSomething(first, second, ...array) { console.log(first, second, array) } doSomething(1, 2, 3, 4, 5) // 1 2 [3, 4, 5]
Собирает оставшиеся элементы массива в новый массив. Используется при деструктуризации массива.
const [first, second, ...array] = [1, 2, 3, 4, 5]console.log(first, second, array)// 1 2 [3, 4, 5]
const [first, second, ...array] = [1, 2, 3, 4, 5] console.log(first, second, array) // 1 2 [3, 4, 5]
Собирает оставшиеся свойства объекта в новый объект. Используется при деструктуризации объекта.
const { c, ...object } = { a: 1, b: 2, c: 3 }console.log(c, object)// 3 {a: 1, b: 2}
const { c, ...object } = { a: 1, b: 2, c: 3 } console.log(c, object) // 3 {a: 1, b: 2}
⛔ Оператор rest
собирает все оставшиеся элементы, свойства или аргументы функции, если написать что-то после них, это вызовет ошибку:
const [first, second, ...array, five] = [1, 2, 3, 4, 5]// five после ...array// Ошибка!
const [first, second, ...array, five] = [1, 2, 3, 4, 5] // five после ...array // Ошибка!
Что делает оператор spread
?
СкопированоРаскладывает массив на отдельные аргументы при вызове функции.
function doSomething(first, second, third) { console.log(first, second, third)}const array = [1, 2, 3]doSomething(...array)// 1 2 3
function doSomething(first, second, third) { console.log(first, second, third) } const array = [1, 2, 3] doSomething(...array) // 1 2 3
Раскладывает массив на отдельные элементы. Этот синтаксис используется при создании массива с помощью литерала [
.
const array = [3, 4]const newArray = [1, 2, ...array, 5]console.log(newArray)// [1, 2, 3, 4, 5]
const array = [3, 4] const newArray = [1, 2, ...array, 5] console.log(newArray) // [1, 2, 3, 4, 5]
Раскладывает объект на отдельные свойства. Этот синтаксис используется при создании объекта с помощью литерала {}
.
const object = { b: 2, c: 3 }const newObject = { a: 1, ...object }console.log(newObject)// { a: 1, b: 2, c: 3}
const object = { b: 2, c: 3 } const newObject = { a: 1, ...object } console.log(newObject) // { a: 1, b: 2, c: 3}
Оператор spread
может стоять где угодно и использоваться любое количество раз в рамках одного вызова функции или создания массива, объекта.
Так тоже можно:
const firstArray = [3, 4]const secondArray = [15, 16]const newArray = [1, 2, ...firstArray, 5, ...secondArray]console.log(newArray)// [1, 2, 3, 4, 5, 15, 16]
const firstArray = [3, 4] const secondArray = [15, 16] const newArray = [1, 2, ...firstArray, 5, ...secondArray] console.log(newArray) // [1, 2, 3, 4, 5, 15, 16]