--- title: Оператор розпакування slug: Web/JavaScript/Reference/Operators/Оператор_розпакування tags: - Iterator - JavaScript - Operator - Ітератор - Оператор translation_of: Web/JavaScript/Reference/Operators/Spread_syntax translation_of_original: Web/JavaScript/Reference/Operators/Spread_operator ---
Оператор розпакування дозволяє розкласти колекцію в місця, де потрібні нуль чи декілька аргументів (як от виклики функцій), або декілька елементів (масиви), чи декілька змінних (деструктуризаційне присвоєння). Також можна розкласти об’єкт у місця де потрібні нуль чи більше пар ключ-значення (для оголошення об’єктів).
Для виклику функцій:
myFunction(...iterableObj);
Для масивів:
[...iterableObj, 4, 5, 6];
Для об’єктів (нове в ECMAScript; чернетка в 3-ій стадії):
let objClone = { ...obj };
Приклад: {{jsxref( "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]);
Викликаючи конструктор з 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 залишається незміненим
Зауваження: оператор розпакування при копіюванні масиву йде лише на один рівень вглиб. Таким чином він не придатний для копіювання багатовимірних масивів, що видно з наступного прикладу (те саме з {{jsxref("Object.assign()")}} та розпакуванням об’єктів).
var a = [[1], [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // Тепер масив a також змінено: [[], [2], [3]]
{{jsxref("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];
{{jsxref("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.
Однорівневе клонування (без прототипу) чи злиття об’єктів тепер можливе використовуючи коротший запис ніж {{jsxref("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 }
Зауваж, що {{jsxref("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()
щоб дізнатись більше.
Оператор решти виглядає точно так само як і оператор розпакування. До певної міри, він протилежний оператору розпакування - оператор розпакування розкладає колекцію на елементи, а оператор решти, натомість, складає кілька елементів у колекцію. Дивись решта параметрів.
Специфікація | Стан | Коментар |
---|---|---|
{{SpecName('ES2015', '#sec-array-initializer')}} | {{Spec2('ES2015')}} | Визначено в деяких секціях специфікацій: Array Initializer, Argument Lists |
{{SpecName('ESDraft', '#sec-array-initializer')}} | {{Spec2('ESDraft')}} | Без змін. |
Rest/Spread Properties for ECMAScript | Чернетка | Чернетка в 3 стадії |
{{CompatibilityTable}}
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari (WebKit) |
---|---|---|---|---|---|
Spread operation in array literals | {{CompatChrome("46")}} | {{ CompatGeckoDesktop("16") }} | {{CompatIE("Edge/10240")}} | {{CompatNo}} | 7.1 |
Spread operation in function calls | {{CompatChrome("46")}} | {{ CompatGeckoDesktop("27") }} | {{CompatIE("Edge/10240")}} | {{CompatNo}} | 7.1 |
Spread operation in destructuring | {{CompatChrome("49")}} | {{ CompatGeckoDesktop("34") }} | {{CompatNo}} | {{CompatUnknown}} | {{CompatUnknown}} |
Feature | Android | Android Webview | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile | Chrome for Android |
---|---|---|---|---|---|---|---|
Spread operation in array literals | {{CompatNo}} | {{CompatChrome("46")}} | {{ CompatGeckoMobile("16") }} | {{CompatNo}} | {{CompatNo}} | 8 | {{CompatChrome("46")}} |
Spread operation in function calls | {{CompatNo}} | {{CompatChrome("46")}} | {{ CompatGeckoMobile("27") }} | {{CompatNo}} | {{CompatNo}} | 8 | {{CompatChrome("46")}} |
Spread operation in destructuring | {{CompatNo}} | {{CompatNo}} | {{ CompatGeckoDesktop("34") }} | {{CompatUnknown}} | {{CompatUnknown}} | {{CompatUnknown}} | {{CompatNo}} |