10. Destrutturazione

10. Destrutturazione #

  • 10.1. Panoramica
    • 10.1.1. Destrutturazione degli oggetti
    • 10.1.2. Destrutturazione dell’array
    • 10.1.3. Dove si può usare la destrutturazione?
  • 10.2. Background: costruire dati contro estrarre dati
  • 10.3. Modelli per la destrutturazione
    • 10.3.1. Scegli quello che ti serve
  • 10.4. In che modo i modelli accedono alle interiora dei valori?
    • 10.4.1. I modelli oggetto costringono i valori agli oggetti
    • 10.4.2. I modelli di array funzionano con iterabili
  • 10.5. Valori predefiniti
    • 10.5.1. undefined attiva i valori predefiniti
    • 10.5.2. I valori predefiniti vengono calcolati su richiesta
    • 10.5.3. I valori predefiniti possono riferirsi ad altre variabili nel modello
    • 10.5.4. Valori predefiniti per i modelli
    • 10.5.5. Valori predefiniti più complessi
  • 10.6. Altre funzioni di destrutturazione degli oggetti
    • 10.6.1. Proprietà valore stenografie
    • 10.6.2. Chiavi di proprietà calcolate
  • 10.7. Altre funzionalità di destrutturazione dell’array
    • 10.7.1. Elision
    • 10.7.2. Operatore di riposo (...)
  • 10.8. È possibile assegnare a più di semplici variabili
  • 10.9. Insidie di destrutturazione
    • 10.9.1. Non iniziare una dichiarazione con una parentesi graffa
  • 10.10. Esempi di destrutturazione
    • 10.10.1. Destrutturazione degli array restituiti
    • 10.10.2. Destrutturazione degli oggetti restituiti
    • 10.10.3. Array-destrutturazione dei valori iterabili
    • 10.10.4. Valori di ritorno multipli
  • 10.11. L’algoritmo di destrutturazione
    • 10.11.1. L’algoritmo
    • 10.11.2. Applicazione dell’algoritmo

10.1 Panoramica #

La destrutturazione è un modo conveniente per estrarre più valori dai dati memorizzati in oggetti e array (eventualmente nidificati). Può essere utilizzato in posizioni che ricevono dati (come il lato sinistro di un’assegnazione). Come estrarre i valori è specificato tramite pattern (continua a leggere per gli esempi).

10.1.1 Destrutturazione degli oggetti #

Destrutturazione degli oggetti:

const obj = { first: 'Jane', last: 'Doe' };const {first: f, last: l} = obj; // f = 'Jane'; l = 'Doe'// {prop} is short for {prop: prop}const {first, last} = obj; // first = 'Jane'; last = 'Doe'

Destrutturazione aiuta con l’elaborazione dei valori di ritorno:

const obj = { foo: 123 };const {writable, configurable} = Object.getOwnPropertyDescriptor(obj, 'foo');console.log(writable, configurable); // true true

10.1.2 Array destrutturazione #

Array destrutturazione (funziona per tutti iterable valori):

const iterable = ;const  = iterable; // x = 'a'; y = 'b'

Destrutturazione aiuta con l’elaborazione dei valori di ritorno:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec('2999-12-31');

10.1.3 Dove è possibile destrutturazione essere utilizzato? #

La destrutturazione può essere utilizzata nelle seguenti posizioni (sto mostrando modelli di array per dimostrare; i modelli di oggetti funzionano altrettanto bene):

// Variable declarations:const  = ;let  = ;var  = ;// Assignments: = ;// Parameter definitions:function f() { ··· }f();

Puoi anche destrutturare in un ciclo for-of :

const arr = ;for (const  of arr.entries()) { console.log(index, element);}// Output:// 0 a// 1 b

10.2 Background: Costruire dati contro estrarre dati #

Per comprendere appieno cos’è la destrutturazione, esaminiamo prima il suo contesto più ampio.

JavaScript ha operazioni per la costruzione di dati, una proprietà alla volta:

const obj = {};obj.first = 'Jane';obj.last = 'Doe';

La stessa sintassi può essere utilizzata per estrarre i dati. Ancora una volta, una proprietà alla volta:

const f = obj.first;const l = obj.last;

Inoltre, esiste una sintassi per costruire più proprietà contemporaneamente, tramite un oggetto letterale:

const obj = { first: 'Jane', last: 'Doe' };

Prima di ES6, non esisteva un meccanismo corrispondente per l’estrazione dei dati. Questo è ciò che è la destrutturazione: consente di estrarre più proprietà da un oggetto tramite un modello di oggetto. Ad esempio, sul lato sinistro di un incarico:

const { first: f, last: l } = obj;

È anche possibile destrutturare gli array tramite modelli:

const  = ; // x = 'a'; y = 'b'

10.3 Modelli per destrutturazione #

Le seguenti due parti sono coinvolte nella destrutturazione:

  • Fonte di destrutturazione: i dati da destrutturare. Ad esempio, il lato destro di un’assegnazione destrutturazione.
  • Destinazione destrutturazione: il modello utilizzato per la destrutturazione. Ad esempio, il lato sinistro di un’assegnazione destrutturante.

L’obiettivo di destrutturazione è uno dei tre pattern:

  • Obiettivo assegnazione. Ad esempio: x
    • Un obiettivo di assegnazione è di solito una variabile. Ma nel destrutturare l’assegnazione, hai più opzioni, come spiegherò più tardi.
  • Modello oggetto. Ad esempio: { first: "pattern", last: "pattern" }
    • Le parti di un modello di oggetto sono proprietà, i valori delle proprietà sono di nuovo modelli (ricorsivamente).
  • Modello di matrice. Ad esempio:
    • Le parti di un modello di matrice sono elementi, gli elementi sono di nuovo modelli (ricorsivamente).

Ciò significa che è possibile nidificare modelli, arbitrariamente profondamente:

const obj = { a: , b: true };const { a:  } = obj; // f = 123

10.3.1 Scegliere ciò che è necessario #

Se si destructure un oggetto, si menziona solo le proprietà che si sono interessati:

const { x: x } = { x: 7, y: 3 }; // x = 7

Se si destructure un Array, è possibile scegliere di estrarre un prefisso:

const  = ; // x='a'; y='b';

10.4 Come fare modelli di accesso le interiora di valori? #

In un’assegnazione pattern = someValue, in che modo patternaccede a cosa c’è dentro someValue?

10.4.1 I pattern oggetto costringono i valori agli oggetti #

Il pattern oggetto costringe le sorgenti di destrutturazione agli oggetti prima di accedere alle proprietà. Ciò significa che funziona con valori primitivi:

const {length : len} = 'abc'; // len = 3const {toString: s} = 123; // s = Number.prototype.toString
10.4.1.1 Non riuscendo a object-destructure un valore #

La coercizione all’oggetto non viene eseguita tramite Object(), ma tramite l’operazione interna ToObject(). Le due operazioni gestiscono undefined e null in modo diverso.

Object() converte i valori primitivi in oggetti wrapper e lascia gli oggetti intatti:

> typeof Object('abc')'object'> var obj = {};> Object(obj) === objtrue

It also converts undefined and null to empty objects:

> Object(undefined){}> Object(null){}

In contrast, ToObject() throws a TypeError if it encounters undefined or null. Therefore, the following destructurings fail, even before destructuring accesses any properties:

const { prop: x } = undefined; // TypeErrorconst { prop: y } = null; // TypeError

Di conseguenza, è possibile utilizzare il modello di oggetto vuoto {} per verificare se un valore è coercibile a un oggetto. Come abbiamo visto, solo undefined e null non lo sono:

({} = ); // OK, Arrays are coercible to objects({} = 'abc'); // OK, strings are coercible to objects({} = undefined); // TypeError({} = null); // TypeError

Le parentesi attorno alle espressioni sono necessarie perché le istruzioni non devono iniziare con parentesi graffe in JavaScript (i dettagli sono spiegati in seguito).

10.4.2 I pattern Array funzionano con iterables #

La destrutturazione dell’array utilizza un iteratore per raggiungere gli elementi di una sorgente. Pertanto, è possibile destrutturare qualsiasi valore iterabile. Diamo un’occhiata ad esempi di valori iterabili.

Le stringhe sono iterabili:

const  = 'abc'; // x='a'; y=

Non dimenticare che l’iteratore su stringhe restituisce punti di codice (“caratteri Unicode”, 21 bit), non unità di codice (“caratteri JavaScript”, 16 bit). (Per ulteriori informazioni su Unicode, consultare il capitolo ” Capitolo 24. Unicode e JavaScript ” in “Parlando JavaScript”.) Per esempio:

const  = 'a\uD83D\uDCA9c'; // x='a'; y='\uD83D\uDCA9'; z='c'

Non è possibile accedere agli elementi di un set tramite indici, ma è possibile farlo tramite un iteratore. Pertanto, la destrutturazione dell’array funziona per gli insiemi:

const  = new Set(); // x='a'; y='b';

L’iteratore Set restituisce sempre gli elementi nell’ordine in cui sono stati inseriti, motivo per cui il risultato della precedente destrutturazione è sempre lo stesso.

10.4.2.1 Non riuscire a destrutturare un valore #

Un valore è iterabile se ha un metodo la cui chiave è Symbol.iterator che restituisce un oggetto. Array-destrutturazione genera un TypeError se il valore da destrutturare non è iterabile:

let x; = ; // OK, Arrays are iterable = 'abc'; // OK, strings are iterable = { * () { yield 1 } }; // OK, iterable = {}; // TypeError, empty objects are not iterable = undefined; // TypeError, not iterable = null; // TypeError, not iterable

Il TypeError viene generata anche prima di accedere a elementi di iterable, il che significa che è possibile utilizzare l’Array vuoto pattern per verificare se un valore è iterable:

 = {}; // TypeError, empty objects are not iterable = undefined; // TypeError, not iterable = null; // TypeError, not iterable

10.5 i valori di Default #

valori di Default sono una funzione opzionale di modelli. Forniscono un fallback se non viene trovato nulla nella fonte. Se una parte (una proprietà dell’oggetto o un elemento dell’array) non ha corrispondenza nell’origine, viene confrontata con:

  • il suo valore predefinito (se specificato; è facoltativo)
  • undefined (altrimenti)

Diamo un’occhiata a un esempio. Nella seguente destrutturazione, l’elemento all’indice 0 non ha corrispondenza sul lato destro. Pertanto, la destrutturazione continua facendo corrispondere x a 3, il che porta a x impostato su 3.

const  = ; // x = 3; y = undefined

È inoltre possibile utilizzare i valori predefiniti nei modelli di oggetti:

const {foo: x=3, bar: y} = {}; // x = 3; y = undefined

10.5.1 undefined attiva i valori predefiniti #

I valori predefiniti vengono utilizzati anche se una parte ha una corrispondenza e tale corrispondenza è undefined:

const  = ; // x = 1const {prop: y=2} = {prop: undefined}; // y = 2

La logica di questo comportamento è spiegata nel prossimo capitolo, nella sezione sui valori predefiniti dei parametri.

10.5.2 I valori predefiniti vengono calcolati su richiesta #

I valori predefiniti vengono calcolati solo quando sono necessari. In altre parole, questa destrutturazione:

const {prop: y=someFunc()} = someValue;

è equivalente a:

let y;if (someValue.prop === undefined) { y = someFunc();} else { y = someValue.prop;}

Si può osservare che, se si utilizza console.log():

> function log(x) { console.log(x); return 'YES' }> const = ;> a'YES'> const = ;> b123

In the second destructuring, the default value is not triggered and log() is not called.

10.5.3 Default values can refer to other variables in the pattern #

A default value can refer to any variable, including other variables in the same pattern:

const  = ; // x=3; y=3const  = ; // x=7; y=7const  = ; // x=7; y=2

Tuttavia, l’ordine è importante: le variabili x e y sono dichiarati da sinistra a destra e produrre un ReferenceError se sono visitati prima che le loro dichiarazioni:

const  = ; // ReferenceError

10.5.4 i valori di Default per i modelli di #

finora abbiamo visto solo i valori di default per le variabili, ma si può anche associare con modelli:

const  = ;

che Cosa significa questo? Richiamare la regola per i valori predefiniti: se una parte non ha corrispondenza nell’origine, la destrutturazione continua con il valore predefinito.

L’elemento con indice 0 non ha corrispondenza, che è il motivo per cui destrutturazione continua con:

const { prop: x } = {}; // x = undefined

Si può vedere più facilmente perché le cose funzionano in questo modo, se si sostituisce il modello { prop: x } con la variabile pattern:

const  = ;

10.5.5 Più complessi i valori di default #

andiamo a esplorare ulteriormente i valori di default per i modelli. Nell’esempio seguente, assegniamo un valore a x tramite il valore predefinito { prop: 123 }:

const  = ;

Poiché l’elemento dell’array all’indice 0 non ha corrispondenza sul lato destro, la destrutturazione continua come segue e x è impostato su 123.

const { prop: x } = { prop: 123 }; // x = 123

Tuttavia, x non viene assegnato un valore in questo modo se il lato destro ha un elemento all’indice 0, perché il valore predefinito non viene attivato.

const  = ;

In questo caso, la destrutturazione continua con:

const { prop: x } = {}; // x = undefined

Quindi, se vuoi x da 123 se l’oggetto o la proprietà non è presente, è necessario specificare un valore predefinito per x stesso:

const  = ;

Qui, destrutturazione continua come segue, indipendentemente dal fatto che la destra è o .

const { prop: x=123 } = {}; // x = 123

10.6 Altre caratteristiche di destrutturazione degli oggetti #

10.6.1 Proprietà valore stenografie #

Proprietà valore stenografie sono una caratteristica di oggetti letterali: Se il valore della proprietà è una variabile che ha lo stesso nome della chiave di proprietà, è possibile omettere la chiave. Questo funziona anche per la destrutturazione:

const { x, y } = { x: 11, y: 8 }; // x = 11; y = 8// Same as:const { x: x, y: y } = { x: 11, y: 8 };

È inoltre possibile combinare proprietà valore abbreviazioni con valori predefiniti:

const { x, y = 1 } = {}; // x = undefined; y = 1

10.6.2 Le chiavi di proprietà calcolate #

Le chiavi di proprietà calcolate sono un’altra caratteristica letterale dell’oggetto che funziona anche per la destrutturazione. È possibile specificare la chiave di una proprietà tramite un’espressione, se la si mette tra parentesi quadre:

const FOO = 'foo';const { : f } = { foo: 123 }; // f = 123

Calcolate proprietà dei tasti consente di destructure proprietà le cui chiavi sono i simboli:

// Create and destructure a property whose key is a symbolconst KEY = Symbol();const obj = { : 'abc' };const { : x } = obj; // x = 'abc'// Extract Array.prototypeconst { : func } = ;console.log(typeof func); // function

10.7 Più Array destrutturazione caratteristiche #

10.7.1 Elisione #

Elisione consente di utilizzare la sintassi di una Matrice di “buchi” per ignorare gli elementi durante la destrutturazione:

const  = ; // x = 'c'; y = 'd'

10.7.2 Resto dell’operatore (...) #

Il resto dell’operatore, consente di estrarre i restanti elementi di un iterable in un Array. Se questo operatore viene utilizzato all’interno di un modello di matrice, deve venire ultimo:

const  = ; // x='a'; y=

Se l’operatore non riesce a trovare alcun elemento, corrisponde al suo operando contro l’array vuoto. Cioè, non produce mai undefined o null. Per esempio:

const  = ; // x='a'; y=undefined; z=

L’operando di tutto il resto operatore non deve essere una variabile, è possibile utilizzare i modelli, troppo:

const ] = ; // x = 'a'; y = 'b'; z = 'c'

Il resto operatore attiva il seguente destrutturazione:

 = 

10.8 È possibile assegnare a più di semplici variabili #

Se si assegna tramite destrutturazione, ogni destinazione di assegnazione può essere tutto ciò che è consentito sul lato sinistro di un’assegnazione normale.

Ad esempio, un riferimento a una proprietà (obj.prop):

const obj = {};({ foo: obj.prop } = { foo: 123 });console.log(obj); // {prop:123}

O un riferimento a un elemento di matrice(arr):

const arr = ;({ bar: arr } = { bar: true });console.log(arr); // 

È inoltre possibile assegnare alle proprietà dell’oggetto e agli elementi dell’array tramite l’operatore rest (...):

const obj = {}; = ; // first = 'a'; obj.prop = 

Se si dichiarano variabili o si definiscono parametri tramite destrutturazione, è necessario utilizzare identificatori semplici, non è possibile fare riferimento alle proprietà dell’oggetto e agli elementi dell’array.

10.9 Insidie di destrutturazione #

Ci sono due cose da tenere a mente quando si utilizza destrutturazione:

  • Non puoi iniziare una dichiarazione con una parentesi graffa.
  • Durante la destrutturazione, puoi dichiarare variabili o assegnarle, ma non entrambe.

Le prossime due sezioni contengono i dettagli.

10.9.1 Non avviare un’istruzione con una parentesi graffa #

Poiché i blocchi di codice iniziano con una parentesi graffa, le istruzioni non devono iniziare con una. Questo è un peccato quando si utilizza l’oggetto destrutturazione in un’assegnazione:

{ a, b } = someObject; // SyntaxError

La soluzione è mettere la completa espressione in parentesi:

({ a, b } = someObject); // OK

La seguente sintassi non funziona:

({ a, b }) = someObject; // SyntaxError

Con let, var e const, le parentesi graffe non causare problemi:

const { a, b } = someObject; // OK

10.10 Esempi di destrutturazione #

Iniziamo con alcuni esempi più piccoli.

Il ciclo for-of supporta la destrutturazione:

const map = new Map().set(false, 'no').set(true, 'yes');for (const  of map) { console.log(key + ' is ' + value);}

È possibile utilizzare la destrutturazione per scambiare i valori. Questo è qualcosa che i motori potrebbero ottimizzare, in modo che non venga creato alcun Array.

 = ;

È possibile utilizzare la destrutturazione per dividere un array:

const  = ; // first = 'a'; rest = 

10.10.1 Destrutturazione degli array restituiti #

Alcune operazioni JavaScript integrate restituiscono gli array. Destrutturazione aiuta con l’elaborazione di loro:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec('2999-12-31');

Se si è interessati solo a gruppi (e non per l’intero match, all), è possibile utilizzare elisione di saltare l’elemento dell’array con indice 0:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec('2999-12-31');

exec() restituisce null se l’espressione regolare non corrisponde. Sfortunatamente, non è possibile gestire null tramite i valori predefiniti, motivo per cui è necessario utilizzare l’operatore Or (||) in questo caso:

const  = /^(\d\d\d\d)-(\d\d)-(\d\d)$/ .exec(someStr) || ;

Array.prototype.split() restituisce un Array. Pertanto, la destrutturazione è utile se sei interessato agli elementi, non all’Array:

const cells = 'Jane\tDoe\tCTO'const  = cells.split('\t');console.log(firstName, lastName, title);

10.10.2 Destrutturazione oggetti restituiti #

Destrutturazione è utile anche per l’estrazione di dati da oggetti che vengono restituiti da funzioni o metodi. Ad esempio, il metodo iteratore next() restituisce un oggetto con due proprietà, done e value. Il codice seguente registra tutti gli elementi dell’Array arr tramite l’iteratore iter. La destrutturazione è utilizzata nella linea A.

const arr = ;const iter = arr();while (true) { const {done,value} = iter.next(); // (A) if (done) break; console.log(value);}

10.10.3 Array-destrutturazione valori iterabili #

Array-destrutturazione funziona con qualsiasi valore iterabile. Questo è occasionalmente utile:

const  = new Set().add('a').add('b'); // x = 'a'; y = 'b'const  = 'foo'; // a = 'f'; b = 'o'

10.10.4 Valori di ritorno multipli #

Per vedere l’utilità di valori di ritorno multipli, implementiamo una funzione findElement(a, p) che cerca il primo elemento nell’Array a per il quale la funzione prestituisce true. La domanda è: cosa dovrebbe restituire findElement()? A volte uno è interessato all’elemento stesso, a volte nel suo indice, a volte in entrambi. La seguente implementazione restituisce entrambi.

function findElement(array, predicate) { for (const  of array.entries()) { // (A) if (predicate(element, index, array)) { // We found an element: return { element, index }; // Same as (property value shorthands): // { element: element, index: index } } } // We couldn't find anything; return failure values: return { element: undefined, index: -1 };}

La funzione itera su tutti gli elementi di array, tramite il metodo Array entries(), che restituisce un iterabile su coppie (riga A). Le parti delle coppie sono accessibili tramite destrutturazione.

Usiamo findElement():

const arr = ;const {element, index} = findElement(arr, x => x % 2 === 0); // element = 8, index = 1

Diverse funzionalità di ECMAScript 6 ci hanno permesso di scrivere codice più conciso: Il callback è una funzione a freccia; il valore restituito viene destrutturato tramite un modello di oggetto con stenografie di valore di proprietà.

A causa di index e element che si riferiscono anche alle chiavi di proprietà, l’ordine in cui le menzioniamo non ha importanza. Possiamo scambiarli e non cambia nulla:

const {index, element} = findElement(···);

Abbiamo gestito con successo il caso di aver bisogno sia di index che di element. Cosa succede se siamo interessati solo a uno di loro? Si scopre che, grazie a ECMAScript 6, la nostra implementazione può occuparsi anche di questo. E il sovraccarico sintattico rispetto alle funzioni con singoli valori di ritorno è minimo.

const a = ;const {element} = findElement(a, x => x % 2 === 0); // element = 8const {index} = findElement(a, x => x % 2 === 0); // index = 1

Ogni volta, estraiamo solo il valore dell’unica proprietà di cui abbiamo bisogno.

10.11 L’algoritmo di destrutturazione #

Questa sezione esamina la destrutturazione da una diversa angolazione: come algoritmo di pattern matching ricorsivo.

Alla fine, userò l’algoritmo per spiegare la differenza tra le seguenti due dichiarazioni di funzione.

function move({x=0, y=0} = {}) { ··· }function move({x, y} = { x: 0, y: 0 }) { ··· }

10.11.1 L’algoritmo #

Un’assegnazione di destrutturazione è simile a questa:

"pattern" = "value"

Vogliamo usare pattern per estrarre i dati da value. Descriverò ora un algoritmo per farlo, che è noto nella programmazione funzionale come pattern matching (short: matching). L’algoritmo specifica l’operatore (“match against”) per l’assegnazione di destrutturazione che corrisponde a pattern contro a value e assegna alle variabili mentre lo fa:

"pattern"  "value"

L’algoritmo viene specificato tramite regole ricorsive che smontano entrambi gli operandi dell’operatore . La notazione dichiarativa potrebbe richiedere un po ‘ di tempo per abituarsi, ma rende la specifica dell’algoritmo più concisa. Ogni regola ha due parti:

  • La testa (prima riga) descrive la condizione che attiva la regola.
  • Il corpo (linee rimanenti) descrive cosa succede se la regola viene attivata.

Diamo un’occhiata ad un esempio:

  • (2c) {key: "pattern", "properties"} ← obj
     "pattern"  obj.key {"properties"}  obj
  • (2e) {} ← obj (nessuna proprietà di sinistra)
     // Nothing to do

In regola (2c), la testa significa che questa regola viene eseguita se c’è un oggetto modello con almeno una proprietà e zero o più proprietà rimanenti. Questo modello è abbinato a un valore obj. L’effetto di questa regola è che l’esecuzione continua con il modello di valore della proprietà che viene confrontato con obj.keye le proprietà rimanenti con obj.

Nella regola (2e), l’head significa che questa regola viene eseguita se il modello di oggetto vuoto {}è abbinato a un valore obj. Allora non c’è niente da fare.

Ogni volta che viene richiamato l’algoritmo, le regole vengono controllate dall’alto verso il basso e viene eseguita solo la prima regola applicabile.

Mostro solo l’algoritmo per l’assegnazione di destrutturazione. Destrutturazione dichiarazioni variabili e destrutturazione definizioni dei parametri funzionano allo stesso modo.

Non copro le funzionalità avanzate (chiavi di proprietà calcolate; abbreviazioni del valore della proprietà; proprietà dell’oggetto e gli elementi dell’array come obiettivi di assegnazione), sia. Solo le basi.

10.11.1.1 Patterns #

Un pattern è:

  • Una variabile: x
  • Un modello di oggetto: {"properties"}
  • Un modello di matrice:

Ciascuna delle sezioni seguenti descrive uno di questi tre casi.

Le tre sezioni seguenti specificano come gestire questi tre casi. Ogni sezione contiene una o più regole numerate.

10.11.1.2 Variabile #
  • (1) x ← value (compreso undefined e null)
     x = value
10.11.1.3 Oggetto modello #
  • (2a) {"properties"} ← undefined
     throw new TypeError();
  • (2b) {"properties"} ← null
     throw new TypeError();
  • (2c) {key: "pattern", "properties"} ← obj
     "pattern"  obj.key {"properties"}  obj
  • (2d) {key: "pattern" = default_value, "properties"} ← obj
     const tmp = obj.key; if (tmp !== undefined) { "pattern"  tmp } else { "pattern"  default_value } {"properties"}  obj
  • (2e) {} ← obj (nessuna proprietà di sinistra)
     // Nothing to do
10.11.1.4 Matrice #

Array modello e iterable. L’algoritmo per la Matrice di destrutturazione inizia con una Matrice e un iterable:

  • (3a) ← non_iterable
    assert(!isIterable(non_iterable))
     throw new TypeError();
  • (3b) ← iterable
    assert(isIterable(iterable))
     const iterator = iterable(); "elements"  iterator

funzione di supporto:

function isIterable(value) { return (value !== null && typeof value === 'object' && typeof value === 'function');}

gli elementi dell’Array e iteratore. L’algoritmo continua con gli elementi del modello (lato sinistro della freccia) e l’iteratore che è stato ottenuto dall’iterabile (lato destro della freccia).

  • (3c) "pattern", "elements" ← iterator
     "pattern"  getNext(iterator) // undefined after last item "elements"  iterator
  • (3d) "pattern" = default_value, "elements" ← iterator
     const tmp = getNext(iterator); // undefined after last item if (tmp !== undefined) { "pattern"  tmp } else { "pattern"  default_value } "elements"  iterator
  • (3e) , "elements" ← iterator (foro, elisione)
     getNext(iterator); // skip "elements"  iterator
  • (3f) ..."pattern" ← iterator (sempre ultima parte!)
     const tmp = ; for (const elem of iterator) { tmp.push(elem); } "pattern"  tmp
  • (3g) ← iterator (senza elementi di sinistra)
     // Nothing to do

funzione di supporto:

function getNext(iterator) { const {done,value} = iterator.next(); return (done ? undefined : value);}

10.11.2 Applicando l’algoritmo #

In ECMAScript 6, è possibile simulare i parametri con nome se il chiamante utilizza un oggetto letterale e il chiamato utilizza destrutturazione. Questa simulazione è spiegata in dettaglio nel capitolo sulla gestione dei parametri. Il seguente codice mostra un esempio: la funzione move1() ha due parametri denominati, x e y:

function move1({x=0, y=0} = {}) { // (A) return ;}move1({x: 3, y: 8}); // move1({x: 3}); // move1({}); // move1(); // 

Ci sono tre valori predefiniti nella riga A:

  • I primi due valori predefiniti consentono di omettere xe y.
  • Il terzo valore predefinito consente di chiamare move1() senza parametri (come nell’ultima riga).

Ma perché definire i parametri come nel frammento di codice precedente? Perché non come segue-che è anche il codice ES6 completamente legale?

function move2({x, y} = { x: 0, y: 0 }) { return ;}

Per capire perché move1() è corretto, usiamo entrambe le funzioni per due esempi. Prima di farlo, vediamo come il passaggio dei parametri può essere spiegato tramite la corrispondenza.

10.11.2.1 Background: passando i parametri tramite matching #

Per le chiamate di funzione, i parametri formali (all’interno delle definizioni delle funzioni) vengono confrontati con i parametri effettivi (all’interno delle chiamate di funzione). Ad esempio, prendere la seguente definizione di funzione e la seguente chiamata di funzione.

function func(a=0, b=0) { ··· }func(1, 2);

I parametri a e b sono impostati in modo simile alla seguente destrutturazione.

  
10.11.2.2 Usando move2() #

Esaminiamo come funziona la destrutturazione per move2().

Esempio 1. move2() porta a questa destrutturazione:

  

L’elemento del singolo Array sul lato sinistro non ha una corrispondenza sul lato destro, motivo per cui {x,y} è abbinato al valore predefinito e non ai dati dal lato destro (regole 3b, 3d):

{x, y}  { x: 0, y: 0 }

La parte sinistra contiene il valore della proprietà scorciatoie, è un’abbreviazione per la:

{x: x, y: y}  { x: 0, y: 0 }

Questa destrutturazione conduce alle due seguenti incarichi (regole 2c, 1):

x = 0;y = 0;

Esempio 2. Esaminiamo la chiamata di funzione move2({z:3}) che porta alla seguente destrutturazione:

  

C’è un elemento di matrice all’indice 0 sul lato destro. Pertanto, il valore predefinito viene ignorato e il passo successivo è (regola 3d):

{x, y}  { z: 3 }

Ciò porta a impostare sia x che y su undefined, che non è ciò che vogliamo.

10.11.2.3 Utilizzo move1() #

Proviamo move1().

Esempio 1: move1()

  

non Abbiamo un elemento di un Array con indice 0 sul lato destro e utilizzare il valore predefinito (regola 3d):

{x=0, y=0}  {}

La parte sinistra contiene il valore della proprietà scorciatoie, il che significa che questa destrutturazione è equivalente a:

{x: x=0, y: y=0}  {}

Né la proprietà x né la proprietà y hanno una corrispondenza sul lato destro. Pertanto, vengono utilizzati i valori predefiniti e seguenti destructurings vengono eseguite successivo (regola 2d):

x  0y  0

Che conduce alle seguenti assegnazioni (regola 1):

x = 0y = 0

Esempio 2: move1({z:3})

  

Il primo elemento della Matrice è una partita sulla destra e quella partita è utilizzato per continuare la destrutturazione (regola 3d):

{x=0, y=0}  {z:3}

Come nell’esempio 1, non ci sono immobili x e y sul lato destro e vengono utilizzati i valori predefiniti:

x = 0y = 0
10.11.2.4 Conclusione #

Gli esempi dimostrano che i valori di default sono una funzionalità di parti del modello (oggetto di proprietà o di elementi di un Array). Se una parte non ha corrispondenza o è confrontata con undefined, viene utilizzato il valore predefinito. Cioè, il modello è abbinato al valore predefinito, invece.