2014-04-24 13 views
6

Sto solo imparando come utilizzare le funzioni di ordine superiore di JS (mappa, perOgni, riduci, ecc.) E sono incappato in confusione. Sto cercando di scrivere una semplice funzione 'intervallo', ma non riesco a popolare la mia matrice di output. Questo è l'obiettivo:forEach su un 'nuovo array' non sta facendo quello che mi aspetto

range(1, 4) // [1, 2, 3, 4] 

sto ottenendo questo:

[undefined × 4] 

Qui è il mio codice:

function range(num1, num2) { 
     var rangeArr = new Array((num2 + 1) - num1); 
     return rangeArr.map(function(e, i, arr) {return arr[i] = num1 + i}); 
    } 

Che cosa mi manca qui? Per quanto posso dire, il problema sembra avere qualcosa a che fare con il modo in cui sto usando il "nuovo array", ma oltre a ciò sono perso.

Oh, ed ecco la parte che mi confonde davvero. Funziona bene:

function bleck() { 
    var blah = [1, 2, 3, 4]; 
    var x = 'wtf'; 
    return blah.map(function(e, i, arr) {return arr[i] = x}) 
} 

["wtf", "wtf", "wtf", "wtf"] 

Grazie !!

+0

Non pensare di aver bisogno "(num2 + 1) - num1)", poiché javascript usa matrici dinamiche. – Serdnad

+0

@Serdnad Non è necessario, ma costruisce una matrice vuota di quella lunghezza: 'Array (4) = [indefinito x 4]' – cincodenada

+1

Nota sull'uso di '.map()' che non è correlato al tuo problema: in il tuo callback non ha bisogno di avere 'return arr [i] = num1 + i', puoi semplicemente dire' return num1 + i; '. Non ha senso impostare i valori in 'arr' - che è lo stesso array di' rangeArr' - perché 'map' costruisce un nuovo array ed è ciò che si sta restituendo dalla funzione' range() '. – nnnnnn

risposta

4

Il metodo forEach itera su gli indici dell'array. È interessante notare che quando si crea un nuovo array tramite new Array(n), esso contiene senza indici per tutto. Invece, imposta semplicemente la proprietà .length.

> var a = new Array(3); 
> console.info(a) 
[] 
> console.info([undefined, undefined, undefined]) 
[undefined, undefined, undefined] 

MDN descrive forEach, e afferma specificamente:

forEach esegue la richiamata prevista una volta per ogni elemento della matrice con un valore assegnato.È non invocato per gli indici che hanno eliminato o eliminato.

Ecco una tecnica accurata per ottenere un array con indici vuoti, ma esistenti.

var a = Array.apply(null, Array(3)); 

Questo funziona perché .apply "espande" gli elementi elise in argomenti corretti, ed i risultati finisce per essere qualcosa di simile Array(undefined, undefined, undefined).

+0

Molto bello, ha funzionato come un fascino !!! Accetterà la tua risposta in meno di 4 minuti e contando;) –

+0

Per curiosità, nessuna idea perché uno vorrebbe un array senza indici? Non è questo che sconfigge lo scopo? –

+0

@i_made_that: Non riesco davvero a pensare a un caso d'uso per questo. Mi sembra un altro barnacle compatibile con le versioni precedenti per l'API standard di JavaScript. :] – voithos

0

Il problema è che map non itera le voci non definite (*).

Io suggerisco di usare un ciclo for invece:

var rangeArr = new Array((num2 + 1) - num1); 
for(var i=0; i<=num2-num1; ++i) 
    rangeArr[i] = num1 + i; 
return rangeArr; 

(*) Con voci indefinite Voglio dire rangeArr.hasOwnProperty(i) === false, da non confondere con rangeArr[i] === void 0.

+0

[indefinito, indefinito, non definito] .map() itererà effettivamente –

+0

@CristiMihai intendevo questo tipo di indefinito: '[,,,] .map()' – Oriol

+0

Capisco che '.map()' non dovrebbe iterare su indici a cui non sono mai stati assegnati valori, ma allora perché il codice dell'OP restituisce un array con quattro elementi non definiti e un '.length' di 4? – nnnnnn

1

Quando si crea un new Array(x) sta creando quello che viene chiamato un sparse matrice, che potrebbe comportarsi in modo un po 'diverso, come si può vedere, alcuni browser diranno [undefined x 20,"foo", undefined x 5] se appena impostato uno valore, e credo che non iterare su quei valori.

+0

Non sono sicuro di seguirlo. Vuoi dire se ho aggiunto questo sotto la dichiarazione 'var rangeArr':' rangeArr [0] = num1'? –

Problemi correlati