--- title: Оператор розкладу slug: Web/JavaScript/Reference/Operators/Spread_syntax tags: - ECMAScript 2015 - JavaScript - Довідка translation_of: Web/JavaScript/Reference/Operators/Spread_syntax ---
Оператор розкладу дозволяє розкласти ітерабельний об'єкт, такий як масив чи рядок, там, де очікується нуль чи більше аргументів (для викликів функцій) чи елементів (для масивних літералів), або розкласти об'єкт там, де очікується нуль або більше пар ключ-значення (для об'єктних літералів).
Для викликів функцій:
myFunction(...iterableObj);
Для масивних літералів або рядків:
[...iterableObj, "4", "п'ять", 6];
Для об'єктних літералів (нове у ECMAScript 2018):
let objClone = { ...obj };
Залишковий синтаксис виглядає так само, як синтаксис розкладання, але використовується для деструктуризації масивів та об'єктів.
В певному сенсі, залишковий синтаксис є протилежністю синтаксису розкладу. Розклад "розпаковує" масив на його окремі елементи, в той час, як залишковий синтаксис збирає множину елементів та "стискає" їх у єдиний елемент. Дивіться {{jsxref("Functions/решта_параметрів", "залишкові параметри", "", 1)}}.
apply()
Зазвичай, {{jsxref("Function.prototype.apply()")}} використовується, коли ви бажаєте використати елементи масиву як аргументи у функції.
function myFunction(x, y, z) { } const args = [0, 1, 2]; myFunction.apply(null, args);
З оператором розкладу наведене можна записати так:
function myFunction(x, y, z) { } const args = [0, 1, 2]; myFunction(...args);
Будь-який аргумент у списку може використати синтаксис розкладу, і він може використовуватись неодноразово.
function myFunction(v, w, x, y, z) { } const args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);
new
Викликаючи конструктор з {{jsxref("Operators/new", "new")}}, неможливо прямо використовувати масив та apply
(apply
виконує [[Call]]
, а не [[Construct]]
). Однак, масив можна легко використовувати з new
завдяки синтаксису розкладу:
const dateFields = [1970, 0, 1]; // 1 Січня 1970 const d = new Date(...dateFields);
Щоб використати new з масивом параметрів без розкладу, вам довелося б зробити це опосередковано, частковим застосуванням:
function applyAndNew(constructor, args) { function partial () { return constructor.apply(this, args); }; if (typeof constructor.prototype === "object") { partial.prototype = Object.create(constructor.prototype); } return partial; } function myConstructor () { console.log("arguments.length: " + arguments.length); console.log(arguments); this.prop1="знач1"; this.prop2="знач2"; }; var myArguments = ["вітаю", "як", "ся", "маєте", "п.", null]; var myConstructorWithArguments = applyAndNew(myConstructor, myArguments); console.log(new myConstructorWithArguments); // (internal log of myConstructor): arguments.length: 6 // (internal log of myConstructor): ["вітаю", "як", "ся", "маєте", "п.", null] // (log of "new myConstructorWithArguments"): {prop1: "знач1", prop2: "знач2"}
Без оператора розкладу, щоб створити новий масив, частиною якого є існуючий масив, літерального синтаксису масивів недостатньо, доводиться використовувати імперативний код з використанням комбінації з {{jsxref("Array.prototype.push", "push()")}}, {{jsxref("Array.prototype.splice", "splice()")}}, {{jsxref("Array.prototype.concat", "concat()")}}, і т. д. З синтаксисом розкладу все стає набагато лаконічнішим:
var parts = ['плечі', 'коліна']; var lyrics = ['голова', ...parts, 'та', 'пальці']; // ["голова", "плечі", "коліна", "та", "пальці"]
Як і розклад аргументів, ...
може використовуватись будь-де у масивному літералі, і може використовуватись неодноразово.
const arr = [1, 2, 3]; const arr2 = [...arr]; // як arr.slice() arr2.push(4); // arr2 стає [1, 2, 3, 4] // arr залишається незміненим
Заувага: Оператор розкладу ефективно йде на один рівень вглиб при копіюванні масиву. Тому він може бути непридатний для копіювання багатовимірних масивів, як показано у наступному прикладі (те саме з {{jsxref("Object.assign()")}} та розкладом).
const a = [[1], [2], [3]]; const b = [...a]; b.shift().shift(); // 1 // О, ні! Тепер масив 'a' також змінився: a // [[], [2], [3]]
Метод {{jsxref("Array.prototype.concat()")}} часто використовується для приєднання масиву в кінець існуючого масиву. Без оператора розкладу це робиться так:
const arr1 = [0, 1, 2]; const arr2 = [3, 4, 5]; // Додати всі елементи з arr2 у arr1 arr1 = arr1.concat(arr2);
З оператором розкладу отримуємо:
let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; arr1 = [...arr1, ...arr2]; // arr1 тепер [0, 1, 2, 3, 4, 5] // Заувага: Не використовуйте const, це спричинить TypeError (недозволене присвоєння)
Метод {{jsxref("Array.prototype.unshift()")}} часто використовується для додавання масиву значень у початок існуючого масиву. Без оператора розкладу це робиться так:
const arr1 = [0, 1, 2]; const arr2 = [3, 4, 5]; // Подати усі елементи з arr2 до arr1 Array.prototype.unshift.apply(arr1, arr2) // arr1 тепер [3, 4, 5, 0, 1, 2]
З оператором розкладу отримуємо:
let arr1 = [0, 1, 2]; let arr2 = [3, 4, 5]; arr1 = [...arr2, ...arr1]; // arr1 тепер [3, 4, 5, 0, 1, 2]
Заувага: На відміну від unshift()
, цей код створює новий arr1
, а не змінює початковий масив arr1
.
Пропозиція Rest/Spread Properties for ECMAScript (стадія 4) додала розкладені властивості до {{jsxref("Operators/Ініціалізація_об’єктів", "об'єктних літералів", 1)}}. Цей синтаксис копіює особисті, перелічувані властивості наданого об'єкта у новий об'єкт.
Дрібне клонування (без прототипу) чи злиття об'єктів тепер можливе за допомогою синтаксису, коротшого, ніж {{jsxref("Object.assign()")}}.
const obj1 = { foo: 'bar', x: 42 }; const obj2 = { foo: 'baz', y: 13 }; const clonedObj = { ...obj1 }; // Object { foo: "bar", x: 42 } const mergedObj = { ...obj1, ...obj2 }; // Object { foo: "baz", x: 42, y: 13 }
Зауважте, що {{jsxref("Object.assign()")}} запускає {{jsxref("Functions/set", "сетери")}}, а оператор розкладу ні.
Зауважте, що ви не можете ані замінити, ані імітувати функцію {{jsxref("Object.assign()")}}:
let obj1 = { foo: 'bar', x: 42 }; let obj2 = { foo: 'baz', y: 13 }; const merge = ( ...objects ) => ( { ...objects } ); let mergedObj = merge ( obj1, obj2); // Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } } let mergedObj = merge ( {}, obj1, obj2); // Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
У наведеному прикладі оператор розкладу працює не так, як можна було очікувати: він розкладає масив аргументів у об'єктний літерал, через наявність залишкового параметра.
Самі по собі об'єкти не є ітерабельними, але вони стають ітерабельними, коли використовуються у масиві, або з функціями перебору, такими як map()
, reduce()
та assign()
. При з'єднанні 2-х об'єктів за допомогою оператору розкладу, вважається, що застосовується функція перебору, коли відбувається з'єднання.
Оператор розкладу (окрім випадку розкладених властивостей) може застосовуватись тільки до ітерабельних об'єктів:
const obj = {'key1': 'value1'}; const array = [...obj]; // TypeError: obj is not iterable
При використанні оператора розкладу для викликів функцій пам'ятайте про можливість перевищити ліміт кількості аргументів рушія JavaScript. Більше інформації дивіться у статті {{jsxref("Function.prototype.apply", "apply()")}}.
Специфікація |
---|
{{SpecName('ESDraft', '#sec-array-initializer', 'Array initializer')}} |
{{SpecName('ESDraft', '#sec-object-initializer', 'Object initializer')}} |
{{Compat("javascript.operators.spread")}}
...
’)...
’)