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

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 (ECMA-262) Living Standard Nessun cambiamento.
ECMAScript (ECMA-262) Living Standard Nessun cambiamento.

Compatibilità con i browser

BCD tables only load in the browser

Vedi anche