MDN wants to learn about developers like you: https://qsurvey.mozilla.com/s3/MDN-dev-survey

Оператор розпакування дозволяє розкласти колекцію в місця, де потрібні нуль чи декілька аргументів (як от виклики функцій), або декілька елементів (масиви), чи декілька змінних (деструктуризаційне пирсвоєння). Також можна розкласти об’єкт у місця де потрібні нуль чи більше пар ключ-значення (для оголошення об’єктів).

Синтаксис

Для виклику функцій:

myFunction(...iterableObj);

Для масивів:

[...iterableObj, 4, 5, 6];

Для об’єктів (нове в ECMAScript; чернетка в 3-ій стадії):

let objClone = { ...obj };

Приклади

Розпакування у викликах функції

Заміна apply

Приклад: Function.prototype.apply прийнято використовувати у випадках, коли потрібно застосувати елементи масиву як аргументи функції.

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);

З розпакуванням тепер отак:

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

Оператор розпакування може бути застосований до будь-якого аргументу та може бути застосований кілька разів.

function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

Apply для new

Викдикаючи конструктор з new, неможливо напряму використовувати на ньому apply (apply робить [[Call]], а не [[Construct]]). Проте з оператором розпакування можна легко розкладати масив у аргументи конструктора:

var dateFields = [1970, 0, 1]; // 1 Січ 1970
// var d = new Date.apply(dateFields) не спрацює. Викине TypeError
var d = new Date(...dateFields); // вуаля

Розпакування в масивах

Ліпше оголошення масивів

Без розпакування, коли потрібно створити новий масив так, щоб якийсь існуючий був його частиною, старого синтаксису оголошення масиву не достатньо та необхідно використовувати комбінацію методів push, splice, concat, тощо. З оператором розпакування це стає значно лаконічніше:

var parts = ['shoulders', 'knees'];
var lyrics = ['head', ...parts, 'and', 'toes'];
// ["head", "shoulders", "knees", "and", "toes"]

Як і з розпакуванням списку аргументів, ... можна використовувати будь-де в оголошенні масиву та будь-яку кількість разів.

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

var arr = [1, 2, 3];
var arr2 = [...arr]; // так само як arr.slice()
arr2.push(4); 

// arr2 стає [1, 2, 3, 4]
// arr залишається незміненим

Зауваження: оператор розпакування при копіюванні масиву йде лише на один рівень вглиб. Таким чином він не придатний для копіювання багатовимірних масивів, що видно з наступного прикладу (те саме з Object.assign() та розпакуванням об’єктів).

var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Тепер масив a також змінено: [[], [2], [3]]

Ліпше злиття масивів

Array.concat часто використовується, щоб додати один масив у кінець іншого. Без розпакування це робиться так:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Доддати всі елементи з arr2 в arr1
arr1 = arr1.concat(arr2);

З розпакуванням це стає:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

Array.unshift часто використовується для того, щоб вставити значення з один масиву в початок іншого. Без розпакування це робиться так:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Вставити всі елементи з arr2 в початок arr1
Array.prototype.unshift.apply(arr1, arr2) // arr1 тепер [3, 4, 5, 0, 1, 2]

З розпакуванням це стає:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 тепер [3, 4, 5, 0, 1, 2]

Розпакування об’єктів

Пропозиція Rest/Spread Properties for ECMAScript (стадія 3) додає розпакування до об’єктів. It copies own enumerable properties from a provided object onto a new object.

Однорівневе клонування (без прототипу) чи злиття об’єктів тепер можливе використовуючи коротший запис ніж Object.assign().

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

Зауваж, що Object.assign() викликає сетери, а оператор розпакування - ні.

Лише для ітерованих

Розпакування може бути застосоване лише для ітерованик об’єктів:

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

Зауваження: наразі (липень 2017) можна говорити про появу розпакування об’єктів у специфікації (дивись попередній підзаголовок). Але ще не до кінця зрозуміло як працюватиме вищенаведений приклад, адже ще немає конкретного рішення щодо цього у спецефікації. Тобто тепер ти можеш розпакувати об’єкт в об’єкт, але не зрозуміло, що станеться, якщо об’єкт розпаковувати у масив і навпаки, масив у об’єкт. Наприклад транспілятор babel вертає наступні результати:

var obj = {'key1': 'value1'}; 
var array = [...obj]; // запише в array пустий масив []

var arr = [1,1,1];
var obj1 = {...arr}; // запише в obj1 {'0': 1, '1': 1, '2': 1}

Розпакування великих колекцій

Використовуючи розпакування зважай на можливість досягнення ліміту аргументів, встановленого у JavaScript рушії, адже оператор розпакування витягує всі елементи колекції в стек, скільки б їх не було. Дивись apply() щоб дізнатись більше.

Оператор решти

Оператор решти виглядає точно так само як і оператор розпакування. До певної міри, він протилежний оператору розпакування - оператор розпакування розкладає колекцію на елементи, а оператор решти, натомість, складає кілька елементів у колекцію. Дивись решта параметрів.

Специфікація

Специфікація Стан Коментар
ECMAScript 2015 (6th Edition, ECMA-262) Standard Визначено в деяких секціях специфікацій: Array Initializer, Argument Lists
ECMAScript Latest Draft (ECMA-262) Living Standard Без змін.
Rest/Spread Properties for ECMAScript Чернетка Чернетка в 3 стадії

Сумісність з браузерами

Feature Chrome Firefox (Gecko) Internet Explorer Opera Safari (WebKit)
Spread operation in array literals 46 16 (16) Edge/10240 No support 7.1
Spread operation in function calls 46 27 (27) Edge/10240 No support 7.1
Spread operation in destructuring 49 34 (34) No support ? ?
Feature Android Android Webview Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile Chrome for Android
Spread operation in array literals No support 46 16.0 (16) No support No support 8 46
Spread operation in function calls No support 46 27.0 (27) No support No support 8 46
Spread operation in destructuring No support No support 34 (34) ? ? ? No support

See also

Мітки документа й учасники

 Зробили внесок у цю сторінку: trofima, KadirTopal
 Востаннє оновлена: trofima,