La sintassi Spread permette di dividere un oggetto iterabile come un'array o una stringa nei suoi singoli elementi dove sono richiesti zero o più argomenti (chiamate di funzione) o elementi (definizione con notazione letterale di un array); oppure di dividere le coppie di un oggetto dove sono richiesti zero o più coppie chiave-valore.

Sintassi

Per le chiamate alle funzioni:

myFunction(...iterableObj);

Per la definizione di array o stringhe con notazione letterale:

[...iterableObj, '4', 'five', 6];

Per la definizione di oggetti con notazione letterale (nuovi in ECMAScript 2018):

let objClone = { ...obj };

Esempi

Spread nelle chiamate alle funzioni

Rimpiazzare apply

E' prassi comune usare Function.prototype.apply quando si vogliono usare 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 sintassi spread questo può essere riscritto così:

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

Qualsiasi argomento nella lista degli argomenti può usare la sintassi spread e la sintassi spread può essere usata più volte.

function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

Apply per new

Quando si chiama un costruttore con  new, non è possibile usare direttamente un array con apply (apply fa una [[Call]] e non un [[Construct]]). Tuttavia un array può essere facilmente usato con new grazie alla sintassi spread: 

var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);

Per usare new con un array di parametri senza la sintassi spread si sarebbe dovuto farlo indirettamente costruendo una funzione ad hoc: 

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);
// (log interno di myConstructor):            arguments.length: 6
// (log interno di myConstructor):            ["hi", "how", "are", "you", "mr", null]
// (log di "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}

Spread nella definizione di array con notazione letterale

Una migliore notazione letterale per la definizione di array

Senza la sintassi spread, per creare un nuovo array usando un array esistente come parte di esso, la notazione letterale non è più sufficiente e deve essere sostituita con codice contenente una combinazione di push, splice, concat, etc. Con la sintassi spread tutto diventa molto più succinto: 

var parts = ['shoulders', 'knees']; 
var lyrics = ['head', ...parts, 'and', 'toes']; 
// ["head", "shoulders", "knees", "and", "toes"]

Porprio come spread in una lista di argomenti, ... può essere usato ovunque nella definizione di un array con notazione letterale, e può essere usato più volte.

Copiare un array

var arr = [1, 2, 3];
var arr2 = [...arr]; // come arr.slice()
arr2.push(4); 

// arr2 diventa [1, 2, 3, 4]
// arr rimane non influenzato

Note: La sintassi spread effettivamente va a un livello più in profondità mentre copia un array. Quindi può non essere adatta quando si copiano array multidimensionali come mostra l'esempio qui sotto (è lo stesso tra Object.assign() e la sintassi Spread).

var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// Anche l'array a viene modificato: [[], [2], [3]]

Un modo migliore per concatenare gli array

Array.concat è spesso usato per concatenare un array alla fine di un array esistente. Senza la sintassi spread si farebbe così:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Appendiamo tutti gli elementi di arr2 in arr1
arr1 = arr1.concat(arr2);

Con la sintassi spread diventa:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

Array.unshift è spesso usato per inserire un array di valori all'inizio di un array esistente. Senza la sintassi spread si farebbe così:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Inserisce tutti gli elementi dall'arr2 all'inizio dell'arr1
Array.prototype.unshift.apply(arr1, arr2) // arr1 adesso è [3, 4, 5, 0, 1, 2]

Con la sintassi spread questo diventa [Si noti, tuttavia, che questo crea un nuovo array arr1. Diversamente da Array.unshift, non modifica l'array originale arr1]:

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 adesso e' [3, 4, 5, 0, 1, 2]

Spread nella definizione di oggetti con notazione letterale

Le Proprietà Rest/Spread per i propositi di ECMAScript (stage 4) aggiungono le proprietà spread anche alla definizione di ggetti con notazione letterale. Copiano le proprietà enumerabili proprie (own) di un oggetto dato in un nuovo oggetto. 

Copie superficiali (escludendo il prototype) o fusioni di oggetti sono ora possibili usando una sintassi più breve rispetto a Object.assign().

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Oggetto { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Oggetto { foo: "baz", x: 42, y: 13 }

Si noti che Object.assign() attiva i setters mentre la sintassi spread no.

 

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 sopra, l'operatore spread non funziona come ci si potrebbe attendere: separa un array di argomenti nella definizione di un oggetto con notazione letterale, per la presenza del rest parameter.

 

Solo per gli iterabili

La sintassi spread (a parte nel caso delle proprietà spread) può essere applicata solo su oggetti iterabili:

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj non è iterabile

Spread con tanti valori

Quando si usa la sintassi spread nelle chiamate di funzioni, bisogna essere consapevoli della possibilità di eccedere il limite della lunghezza degli argomenti previsto dal motore JavaScript. Si veda apply() per maggiori dettagli.

Sintassi Rest (parametri)

La sintassi spread appare esattamente come la sintassi rest, ma è usata per destrutturare gli array e gli oggetti. In un certo senso, la sintassi rest è l'opposto della sintassi spread: spread 'divide' un array nei suoi elementi, mentre rest colleziona molteplici elementi e li 'aggrega' in un singolo elemento. Si veda parametri rest.

Specifiche

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262) Standard Definito in diverse sezioni delle specifiche: Array Initializer, Argument Lists
ECMAScript Latest Draft (ECMA-262) Draft Nessun cambiamento.
ECMAScript Latest Draft (ECMA-262) Draft Definito in Object Initializer

Compatibilità nei browser

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Spread in array literalsChrome Full support 46Edge Full support 12Firefox Full support 16IE No support NoOpera Full support 37Safari Full support 8WebView Android Full support 46Chrome Android Full support 46Edge Mobile Full support 12Firefox Android Full support 16Opera Android Full support 37Safari iOS Full support 8Samsung Internet Android Full support 5.0nodejs Full support 5.0.0
Full support 5.0.0
Full support 4.0.0
Disabled
Disabled From version 4.0.0: this feature is behind the --harmony runtime flag.
Spread in function callsChrome Full support 46Edge Full support 12Firefox Full support 27IE No support NoOpera Full support 37Safari Full support 8WebView Android Full support 46Chrome Android Full support 46Edge Mobile Full support 12Firefox Android Full support 27Opera Android Full support 37Safari iOS Full support 8Samsung Internet Android Full support 5.0nodejs Full support 5.0.0
Full support 5.0.0
Full support 4.0.0
Disabled
Disabled From version 4.0.0: this feature is behind the --harmony runtime flag.
Spread in destructuringChrome Full support 49Edge No support NoFirefox Full support 34IE No support NoOpera Full support 37Safari ? WebView Android Full support 49Chrome Android Full support 49Edge Mobile No support NoFirefox Android Full support 34Opera Android Full support 37Safari iOS ? Samsung Internet Android Full support 5.0nodejs Full support Yes
Spread in object literals
Experimental
Chrome Full support 60Edge No support NoFirefox Full support 55IE No support NoOpera ? Safari No support NoWebView Android Full support 60Chrome Android Full support 60Edge Mobile No support NoFirefox Android Full support 55Opera Android ? Safari iOS No support NoSamsung Internet Android No support Nonodejs Full support 8.3.0
Full support 8.3.0
Full support 8.0.0
Disabled
Disabled From version 8.0.0: this feature is behind the --harmony runtime flag.

Legend

Full support  
Full support
No support  
No support
Compatibility unknown  
Compatibility unknown
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.
User must explicitly enable this feature.
User must explicitly enable this feature.

Si veda anche

Tag del documento e collaboratori

Hanno collaborato alla realizzazione di questa pagina: quackmore, adrisimo74
Ultima modifica di: quackmore,