--- title: Spread syntax slug: Web/JavaScript/Reference/Operators/Spread_syntax tags: - ECMAScript 2015 - Iterator - JavaScript - Referenza translation_of: Web/JavaScript/Reference/Operators/Spread_syntax ---
La Spread syntax consente un iterabile come un'espressione di un array o una stringa da espandere in punti in cui sono previsti zero o più argomenti (per chiamate di funzione) o elementi (per letterali di array) o un'espressione di oggetto da espandere in posizioni dove zero o più sono previste coppie di valori (per valori letterali oggetto)..
Per chiamate di funzione:
myFunction(...iterableObj);
Per letterali di un array o stringhe:
[...iterableObj, '4', 'five', 6];
Per gli oggetti letterali (novità in ECMAScript 2018):
let objClone = { ...obj };
apply()
È comune utilizzare {{jsxref("Function.prototype.apply()")}} nei casi in cui vuoi utilizzare gli elementi di un array come argomenti di una funzione.
function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction.apply(null, args);
Con la spread syntax può essere scritto come:
function myFunction(x, y, z) { } var args = [0, 1, 2]; myFunction(...args);
Qualsiasi argomento nell'elenco di argomenti può utilizzare la spread syntax e può essere utilizzato più volte.
function myFunction(v, w, x, y, z) { } var args = [0, 1]; myFunction(-1, ...args, 2, ...[3]);
new
When calling a constructor with {{jsxref("Operators/new", "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"}
Without spread syntax, to create a new array using an existing array as one part of it, the array literal syntax is no longer sufficient and imperative code must be used instead using a combination of {{jsxref("Array.prototype.push", "push()")}}, {{jsxref("Array.prototype.splice", "splice()")}}, {{jsxref("Array.prototype.concat", "concat()")}}, etc. With spread syntax this becomes much more succinct:
var parts = ['shoulders', 'knees']; var lyrics = ['head', ...parts, 'and', 'toes']; // ["head", "shoulders", "knees", "and", "toes"]
Just like spread for argument lists, ...
can be used anywhere in the array literal and it can be used multiple times.
var arr = [1, 2, 3]; var arr2 = [...arr]; // like arr.slice() arr2.push(4); // arr2 becomes [1, 2, 3, 4] // arr remains unaffected
Note: La spread syntax diventa effettivamente un livello profondo durante la copia di un array. Pertanto, potrebbe non essere adatto per copiare arrau multidimensionali come mostra il seguente esempio (è lo stesso con {{jsxref("Object.assign()")}} e spread syntax).
var a = [[1], [2], [3]]; var b = [...a]; b.shift().shift(); // 1 // Adesso anche l'array a è influenzato: [[], [2], [3]]
{{jsxref("Array.prototype.concat()")}} è spesso usato per concatenare un array alla fine di un array esistente. Senza la spread syntax questo è fatto così:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Append all items from arr2 onto arr1 arr1 = arr1.concat(arr2);
Con la spread syntax questo diventa:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr1, ...arr2]; // arr1 is now [0, 1, 2, 3, 4, 5]
{{jsxref("Array.prototype.unshift()")}} è spesso usato per inserire un array di valori all'inizio di un array esistente. Senza la spread syntax questo è fatto così:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; // Spostare all'inizio tutti gli elementi da arr2 a arr1 Array.prototype.unshift.apply(arr1, arr2) // arr1 ora è [3, 4, 5, 0, 1, 2]
Con la spread syntax questo diventa:
var arr1 = [0, 1, 2]; var arr2 = [3, 4, 5]; arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]
Note: A differenza di unshift()
, questo crea un nuovo arr1
, e non modifica l'array originale arr1
.
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.
Lo Shallow-cloning (escluso il prototipo) o fusione di oggetti è ora possibile usando una sintassi più breve di {{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 }
Nota che {{jsxref("Object.assign()")}} attiva i setters mentre la spread syntax non lo fa.
Nota che non è possibile sostituire o imitare la funzione {{jsxref("Object.assign()")}}:
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 } }
Nell'esempio precedente, la spread syntax non funziona come previsto: estende una serie di argomenti nel letterale dell'oggetto, a causa del parametro rest.
La spread syntax (diversa dal caso delle spread properties) può essere applicata solo agli oggetti iterabili:
var obj = {'key1': 'value1'}; var array = [...obj]; // TypeError: obj non è iterabile
Quando si utilizza la sintassi di diffusione per le chiamate di funzione, tenere presente la possibilità di superare il limite di lunghezza dell'argomento del motore JavaScript. Vedi {{jsxref("Function.prototype.apply", "apply()")}} per maggiori dettagli.
La Rest syntax sembra esattamente come la spread syntax, ma è usata per destrutturare array e oggetti. In un certo senso, la Rest syntax è l'opposto della spread syntax: spread 'espande' un array nei suoi elementi, mentre la rest syntax raccoglie più elementi e li 'condensa' in un singolo elemento. Vedi rest parameters.
Specification | Status | Comment |
---|---|---|
{{SpecName('ES2015', '#sec-array-initializer')}} | {{Spec2('ES2015')}} | Definito in diverse sezioni della specifica: Array Initializer, Argument Lists |
{{SpecName('ES2018', '#sec-object-initializer')}} | {{Spec2('ES2018')}} | Definito in Object Initializer |
{{SpecName('ESDraft', '#sec-array-initializer')}} | {{Spec2('ESDraft')}} | Nessun cambiamento. |
{{SpecName('ESDraft', '#sec-object-initializer')}} | {{Spec2('ESDraft')}} | Nessun cambiamento. |
{{Compat("javascript.operators.spread")}}
...
’)...
’)