Recentemente ho scoperto il seguente snippet di codice su SO per aiutare a popolare rapidamente un array con valori predefiniti:
Array.apply(null, new Array(3)).map(function() {return 0;});
Dato il comportamento del costruttore Array e del metodo apply, lo snippet precedente può anche essere riscritto come tale:
Array.apply(null, [undefined, undefined, undefined]).map(function() {return 0;});
Questa tecnica è utile anche quando si tratta di array sparsi che si desidera popolare con valori predefiniti:
var sparseArr = [3,,,4,1,,], denseArr = Array.apply(null, sparseArr).map(function(e) { return e === undefined ? 0 : e; }); // denseArr = [3,0,0,4,1,0]
Comunque è in ciò che sorgono due stranezze:
sparseArr
non è definito, tale termine non viene mappato in denseArr
sparseArr
contiene solo un singolo termine (ad es. sparseArr = [1]
) o un singolo termine seguito da un singolo termine finale indefinito (es. sparseArr = [1,]
), il denseArr
risultante equivale a [undefined x 1]
Qualcuno può spiegare questo comportamento?
new Array(3)
[…] può anche essere riscritto come[undefined, undefined, undefined]
No – come appena visto, il costruttore di array crea array sparsi quindi dovrebbe essere riscritto come [,,,]
.
Se il termine finale di sparseArr non è definito
No. Ti stai dimenticando dei commmenti finali, che sono facoltativi poiché EcmaScript 5. In realtà [1]
è solo equivalente a [1,]
(entrambi hanno una lunghezza di 1
).
Per ottenere “slot” sparse, dovrai aggiungere una virgola aggiuntiva:
[] // empty array [,] // empty array [,,] // [undefined x 1] [,,,] // [undefined x 2]
Se
sparseArr
contiene solo un singolo termine, ildenseArr
risultantedenseArr
uguale a[undefined x N]
Considera cosa significa chiamare il metodo apply
:
Array.apply(null, [3,,4,1]) ≡ Array(3, undefined, 4, 1) Array.apply(null, [3,4]) ≡ Array(3, 4) Array.apply(null, [1]) ≡ Array(1)
E sai cosa fa il costruttore Array
quando viene chiamato con un singolo argomento numerico – crea una matrice sparsa di quella lunghezza …
È ansible avere una virgola finale negli array da ECMA 262. La sua presenza non modifica il contenuto dell’array in alcun modo.
Se hai due o più virgole consecutive non consecutive in un array, il loro contenuto viene impostato come indefinito.
Nota: poiché undefined
negli array ha un comportamento non standard in IE <9, eviterei di usarlo lì. Utilizzare invece null
.
Il fatto che tu abbia risultati sorprendenti quando sparseArr contiene un elemento è perché Array ha due diversi costruttori: se passi più argomenti crea una matrice con quella sequenza, se passi un numero singolo crea una matrice di “numero” di lunghezza pieno di indefinito.
new Array(1, 2, 3) => [1, 2, 3] new Array(2) => [undefined, undefined]