Skip to main content

Оператор spread і rest

Оператор ... це один синтаксис із двома ролями: spread (розпакування) розгортає ітерований об'єкт або властивості об'єкта на окремі елементи, а rest (залишок) збирає решту елементів в один масив чи об'єкт. Роль визначає не сам оператор, а місце, де він стоїть: у літералі та у виклику функції це spread, у параметрах функції та в деструктуризації це rest.

Теорія

TL;DR

  • ... у літералі або виклику розгортає значення: [...arr], {...obj}, sum(...nums).
  • ... у деструктуризації або в списку параметрів збирає залишок: [a, ...rest], function fn(...args).
  • Spread робить поверхневу копію (shallow copy): вкладені об'єкти та масиви копіюються за посиланням.
  • Spread по об'єктах зливає властивості, і пізніший ключ перезаписує раніший.
  • Це сучасна заміна concat, Object.assign і Array.prototype.slice.call(arguments).

Швидкий приклад

javascript
const numbers = [1, 2, 3]; const moreNumbers = [0, ...numbers, 4, 5]; // spread: розпакували масив console.log(moreNumbers); // [0, 1, 2, 3, 4, 5] const [first, ...rest] = moreNumbers; // rest: зібрали залишок console.log(first); // 0 console.log(rest); // [1, 2, 3, 4, 5]

Spread: розпакування масивів

Spread використовується для розпакування (розкриття) масиву чи об'єкта на окремі елементи.

javascript
const numbers = [1, 2, 3]; const moreNumbers = [0, ...numbers, 4, 5]; console.log(moreNumbers); // [0, 1, 2, 3, 4, 5]

Тут ...numbers «розкрив» масив [1, 2, 3] усередину нового масиву.

Копіювання масивів:

javascript
const arr1 = [1, 2, 3]; const arr2 = [...arr1]; console.log(arr2); // [1, 2, 3] console.log(arr1 === arr2); // false (новий масив)

Це поверхнева копія (shallow copy): новим є лише зовнішній масив.

Об'єднання масивів:

javascript
const a = [1, 2]; const b = [3, 4]; const c = [...a, ...b]; console.log(c); // [1, 2, 3, 4]

Spread у викликах функцій

У виклику функції spread перетворює масив на список окремих аргументів.

javascript
function sum(a, b, c) { return a + b + c; } const nums = [1, 2, 3]; console.log(sum(...nums)); // 6

...nums перетворює [1, 2, 3] на sum(1, 2, 3).

Spread з об'єктами

Той самий синтаксис копіює власні перелічувані властивості з одного об'єкта в інший.

javascript
const user = { name: 'Alex', age: 25 }; const newUser = { ...user, city: 'Paris' }; console.log(newUser); // { name: 'Alex', age: 25, city: 'Paris' }

Якщо ключі збігаються, пізніше значення перезаписує раніше:

javascript
const merged = { a: 1, ...{ a: 2, b: 3 } }; console.log(merged); // { a: 2, b: 3 }

Rest: збирання залишку

Rest працює у зворотний бік: він не розпаковує, а збирає елементи, що залишилися, у масив або об'єкт.

У масивах:

javascript
const [first, ...rest] = [1, 2, 3, 4]; console.log(first); // 1 console.log(rest); // [2, 3, 4]

В об'єктах:

javascript
const user = { name: 'Alex', age: 25, city: 'Paris' }; const { name, ...info } = user; console.log(name); // Alex console.log(info); // { age: 25, city: 'Paris' }

У функціях:

javascript
function sum(...numbers) { return numbers.reduce((a, b) => a + b, 0); } console.log(sum(1, 2, 3, 4)); // 10

...numbers збирає всі аргументи функції у справжній масив, на відміну від псевдомасиву arguments.

Spread проти rest і що це замінило

ОсобливістьSpreadRest
Що робитьРозпаковуєЗбирає
Де використовуєтьсяУ виклику функції, при створенні масиву або об'єктаВ оголошенні функції або в деструктуризації
Приклад[...arr], {...obj}, fn(...args)function fn(...args), [a, ...rest]

Приклади «до і після»:

До ES6З ES6
arr1.concat(arr2)[...arr1, ...arr2]
Object.assign({}, obj1, obj2){...obj1, ...obj2}
Array.prototype.slice.call(arguments)(...args) => {}

Підсумкова таблиця поведінки:

КонтекстПоведінка ...Приклад
Spread (розпакування)Розгортає масив або об'єкт[...arr], {...obj}, sum(...nums)
Rest (залишок)Збирає залишок елементів[a, ...rest], function fn(...args)

Типові помилки

  1. Вважати spread глибоким копіюванням. Spread і rest поверхневі: вкладені об'єкти та масиви копіюються за посиланням, тож зміна вкладеного поля в копії видно в оригіналі.

    javascript
    const obj = { nested: { a: 1 } }; const copy = { ...obj }; copy.nested.a = 2; console.log(obj.nested.a); // 2, а не 1

    Для глибокої копії потрібен structuredClone(obj) або ручний обхід структури.

  2. Використовувати ... без контексту деструктуризації. Запис const ...rest = arr; це синтаксична помилка; правильно const [a, ...rest] = arr;.

  3. Ставити rest не останнім. function fn(...args, last) {} не компілюється: rest-параметр може бути лише останнім, бо він забирає все, що лишилося.

  4. Забувати про порядок ключів у spread об'єктів. { ...defaults, ...options } і { ...options, ...defaults } дають різний результат, бо перемагає той об'єкт, що стоїть правіше.

  5. Плутати ...args з arguments. arguments це псевдомасив, якого немає у стрілкових функціях; rest-параметр завжди дає справжній масив із методами map, filter, reduce.

Коротка відповідь

Для співбесіди
Premium

Коротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.