Spread syntax

Questo contenuto viene visualizzato in inglese perché non è ancora disponibile una versione tradotta nella lingua selezionata. Aiutaci a tradurre questo articolo!

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)..

Sintassi

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 };

Esempi

Spread nelle chiamate delle funzioni

Sostituire apply()

È comune utilizzare 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]);

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"}

Spread in array literals

A more powerful array literal

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 push(), splice(), 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.

Copiare un array

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 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]]

Un modo migliore per concatenare gli array

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]

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.

Spread in object literals

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 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 Object.assign() attiva i setters mentre la spread syntax non lo fa.

Nota che non è possibile sostituire o imitare la funzione 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.

Solo per iterabili

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

Diffusione con molti valori

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 apply() per maggiori dettagli.

Rest syntax (parametri)

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.

Specifications

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

Compatibilità con i browser

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox 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 46Firefox 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 46Firefox 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 49Firefox 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 Full support 47Safari Full support 11.1WebView Android Full support 60Chrome Android Full support 60Firefox Android Full support 55Opera Android ? Safari iOS Full support 11.3Samsung Internet Android Full support 8.2nodejs 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.

Vedi anche