Składnia rozwinięcia
Try it
Składnia
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 };
Przykłady
Rozwinięcie w wywołaniach funkcji
Zastąpienie apply
Powszechne jest używanie 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]);
Apply for new
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"}
Rozwinięcie w literałach tablicowych
Potężniejszy literał tablicowy
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.
Kopia tablicy
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 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]]
Lepszy sposób na łączenie tablic
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];
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 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]
Rozwinięcie w literałach tablicowych
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 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 Object.assign()
triggers setters whereas spread syntax doesn't.
Note that you cannot replace nor mimic the 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.
Tylko dla obiektów iterowalnych
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
Rozwinięcie z wieloma wartościami
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 (parametry)
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.
Specyfikacje
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) | Standard | Defined in several sections of the specification: Array Initializer, Argument Lists |
ECMAScript 2018 (ECMA-262) | Standard | Defined in Object Initializer |
ECMAScript (ECMA-262) | Living Standard | No changes. |
ECMAScript (ECMA-262) | Living Standard | No changes. |
Wsparcie przeglądarek
BCD tables only load in the browser
Zobacz też
- Rest parameters (również ‘
...
’) - fn.apply (również ‘
...
’)