--- title: Składnia rozwinięcia slug: Web/JavaScript/Referencje/Operatory/Składnia_rozwinięcia translation_of: Web/JavaScript/Reference/Operators/Spread_syntax ---
Dla wywołań funkcji:
mojaFunkcja(...iterowalnyObiekt);
Dla literałów tablicowych lub łańcuchów znaków:
[...iterowalnyObiekt, '3', 'cztery', 5];
Dla literałów obiektowych (nowe w ECMAScript 2018):
let klonObiektu = { ...obiekt };
apply
Powszechne jest używanie {{jsxref( "Function.prototype.apply")}} w przypadkach, w których chcemy użyć elementów tablicy jako argumentów funkcji.
function mojaFunkcja(x, y, z) { } var argumenty = [0, 1, 2]; mojaFunkcja.apply(null, argumenty);
Przy użyciu operatora rozpakowania można to zapisać jako:
function mojaFunkcja(x, y, z) { } var argumenty = [0, 1, 2]; mojaFunkcja(...argumenty);
Każdy argument na liście argumentów może użyć operatora rozpakowania, można go także używać wielokrotnie.
function mojaFunkcja(v, w, x, y, z) { } var argumenty = [0, 1]; mojaFunkcja(-1, ...argumenty, 2, ...[3]);
When calling a constructor with new
, it's not possible to directly use an array and apply
(apply
does a [[Call]]
and not a [[Construct]]
). However, an array can be easily used with new
thanks to spread syntax:
var dateFields = [1970, 0, 1]; // 1 Jan 1970 var d = new Date(...dateFields);
To use new with an array of parameters without spread syntax, you would have to do it indirectly through partial application:
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="val1"; this.prop2="val2"; }; var myArguments = ["hi", "how", "are", "you", "mr", null]; var myConstructorWithArguments = applyAndNew(myConstructor, myArguments); console.log(new myConstructorWithArguments); // (internal log of myConstructor): arguments.length: 6 // (internal log of myConstructor): ["hi", "how", "are", "you", "mr", null] // (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}
Bez składni rozwinięcia, aby utworzyć nową tablicę, używając tablicy już istniejącej jako jej części, składnia literału tablicowego nie jest już wystarczająca i musimy użyć kodu imperatywnego, używając kombinacji push
, splice
, concat
itd. Z użyciem składni rozwinięcia staje się to o wiele prostsze i bardziej zwięzłe:
var czesci = ['kotek', 'na', 'plotek']; var wierszyk = ['wlazl', ...czesci, 'i', 'mruga']; // ["wlazl", "kotek", "na", "plotek", "i", "mruga"]
Tak jak dla list argumentów w wywołaniach funkcji, operator ...
może być użyty wielokrotnie i w każdym miejscu literału tablicowego.
var tab = [1, 2, 3]; var tab2 = [...tab]; // jak tab.slice() tab2.push(4); // tab2 staje się [1, 2, 3, 4] // tab pozostaje niezmieniona
Uwaga: Składnia rozwinięcia skutecznie sięga tylko na jeden poziom wgłąb przy kopiowaniu tablicy. W związku z tym takie podejście może być nieodpowiednie przy kopiowaniu tablic wielowymiarowych, jak pokazuje poniższy przykład (tak samo jest z {{jsxref("Object.assign()")}} i kładnią rozwinięcia).
var a = [[1], [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // Tablica a została zmodyfikowana: [[], [2], [3]]
{{jsxref("Array.concat")}} jest często używane do dołączania elementów jednej tablicy na koniec drugiej. Bez składni rozwinięcia wygląda to tak:
var tab1 = [0, 1, 2]; var tab2 = [3, 4, 5]; // Dołącz wszystkie elementy tab2 na koniec tab1 tab1 = tab1.concat(tab2);
Przy użyciu składni rozwinięcia wygląda to natomiast tak:
var tab1 = [0, 1, 2]; var tab2 = [3, 4, 5]; tab1 = [...tab1, ...tab2];
{{jsxref("Array.unshift")}} jest często używane do dołączania elementów jednej tablicy na początek drugiej. Bez składni rozwinięcia wygląda to w następujący sposób:
var tab1 = [0, 1, 2]; var tab2 = [3, 4, 5]; // Dodaj wszystkie elementy tab2 na początek tab1 Array.prototype.unshift.apply(tab1, tab2) // tab1 staje się [3, 4, 5, 0, 1, 2]
Przy użyciu składni rozwinięcia otrzymuje to następującą postać [jednak zauważ, że w tym przypadku utworzona zostaje nowa tablica tab1
– w odróżnieniu od {{jsxref("Array.unshift")}}, tab1
nie jest automatycznie modyfikowana):
var tab1 = [0, 1, 2]; var tab2 = [3, 4, 5]; tab1 = [...tab2, ...tab1]; // tab1 staje się [3, 4, 5, 0, 1, 2]
The Rest/Spread Properties for ECMAScript proposal (stage 4) adds spread properties to object literals. It copies own enumerable properties from a provided object onto a new object.
Shallow-cloning (excluding prototype) or merging of objects is now possible using a shorter syntax than {{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 }
Note that {{jsxref("Object.assign()")}} triggers setters whereas spread syntax doesn't.
Note that you cannot replace nor mimic the {{jsxref("Object.assign()")}} function:
var obj1 = { foo: 'bar', x: 42 }; var obj2 = { foo: 'baz', y: 13 }; const merge = ( ...objects ) => ( { ...objects } ); var mergedObj = merge ( obj1, obj2); // Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } } var mergedObj = merge ( {}, obj1, obj2); // Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }
In the above example, the spread syntax does not work as one might expect: it spreads an array of arguments into the object literal, due to the rest parameter.
Składnia rozwinięcia może być użyta jedynie dla obiektów iterowalnych:
var obiekt = {'klucz1': 'wartosc1'}; var tablica = [...obiekt]; // TypeError: obiekt is not iterable
Kiedy używaż składni rozwinięcia do wywołań funkcji, musisz być świadomy możliwości przekroczenia limitu liczby argumentów w silniku JavaScript. Po więcej szczegółów zajrzyj do apply()
.
Składnia reszty ang. rest syntax) wygląda dokładnie jak składnia rozwinięcia, ale jest używana do destrukturyzacji tablic i obiektów. W pewnym sensie składnia reszty jest przeciwieństwem składni rozpakowania: rozwinięcie „rozpakowuje” elementy tablicy, natomiast składnia reszty „zbiera” wiele elementów i „pakuje” je do pojedynczego elementu. Zobacz: rest parameters.
Specification | Status | Comment |
---|---|---|
{{SpecName('ES2015', '#sec-array-initializer')}} | {{Spec2('ES2015')}} | Defined in several sections of the specification: Array Initializer, Argument Lists |
{{SpecName('ES2018', '#sec-object-initializer')}} | {{Spec2('ES2018')}} | Defined in Object Initializer |
{{SpecName('ESDraft', '#sec-array-initializer')}} | {{Spec2('ESDraft')}} | No changes. |
{{SpecName('ESDraft', '#sec-object-initializer')}} | {{Spec2('ESDraft')}} | No changes. |
{{Compat("javascript.operators.spread")}}
...
’)...
’)