2014-04-24 2 views
6

erwarte ich bin nur zu lernen, wie JS verwenden Funktionen höherer Ordnung (Karte, forEach, reduzieren, usw.) und haben in Verwirrung gestolpert. Ich versuche eine einfache 'Range'-Funktion zu schreiben, kann aber mein Ausgabe-Array nicht füllen. Dies ist das Ziel:forEach auf einem neuen Array 'tun, ist nicht das, was ich

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

ich diese bekommen:

[undefined × 4] 

Hier ist mein Code:

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

Was ich hier fehlt? Soweit ich das beurteilen kann, scheint das Problem etwas damit zu tun zu haben, wie ich 'neues Array' benutze, aber darüber hinaus bin ich verloren.

Oh, und hier ist der Teil, der mich wirklich verwirrt. Dies funktioniert gut:

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

Dank !!

+0

Ich glaube nicht, dass Sie "(num2 + 1) - num1)" brauchen, da Javascript dynamische Arrays verwendet. – Serdnad

+0

@Serdnad Es ist nicht notwendig, aber es erstellt ein leeres Array dieser Länge: 'Array (4) = [undefined x 4]' – cincodenada

+1

Hinweis zur Verwendung von '.map()', die nicht auf Ihr Problem bezogen ist: in Ihr Callback ist nicht nötig, um 'return arr [i] = num1 + i' zu haben, Sie können einfach' return num1 + i; 'sagen. Es gibt keinen Grund, die Werte in 'arr' zu setzen - das ist das gleiche Array wie 'rangeArr' - weil 'map' ein neues Array erstellt und das ist, was Sie von Ihrer' range() 'Funktion zurückgeben. – nnnnnn

Antwort

4

Die Methode forEach iteriert über die Indizes des Arrays. Interessanterweise, wenn Sie ein neues Array über new Array(n) erstellen, enthält es keine Indizes auf allen. Stattdessen legt es nur seine .length Eigenschaft fest.

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

MDN beschreibt forEach und speziell erklärt:

forEach führt den vorgesehenen Rückruf einmal für jedes Element des Arrays mit einem zugeordneten Wert.Es wird nicht für Indizes aufgerufen, die gelöscht oder gelöscht haben.

Hier ist eine saubere Technik, um ein Array mit leeren, aber vorhandenen Indizes zu erhalten.

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

Das funktioniert, weil .apply „erweitert“ die elided Elemente in der richtigen Argumente und die Ergebnisse enden so etwas wie Array(undefined, undefined, undefined) zu sein.

+0

Sehr cool, arbeitete wie ein Zauber !!! Wird deine Antwort in T-minus 4 Minuten annehmen und zählen;) –

+0

Aus Neugier, warum sollte man ein Array ohne Indizes haben? Widerspricht das nicht dem Zweck? –

+0

@i_made_that: Ich kann nicht wirklich einen Anwendungsfall dafür denken. Es scheint mir nur eine weitere rückwärtskompatible Seepocke für die Standard-API von JavaScript zu sein. :] – voithos

0

Das Problem ist, dass map nicht iterieren nicht undefiniert Einträge (*).

Ich schlage vor, mit einer for Schleife statt:

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

(*) Mit undefinierten Einträge I rangeArr.hasOwnProperty(i) === false bedeuten, nicht mit rangeArr[i] === void 0 zu verwechseln.

+0

[undefined, undefined, undefined] .map() wird eigentlich iterieren –

+0

@CristiMihai Ich meinte diese Art von undefined: '[,,,]. map()' – Oriol

+0

Ich verstehe, dass '.map()' nicht über Indizes, die nie Werte zugewiesen wurden, sondern Warum gibt der OP-Code dann ein Array mit vier undefinierten Elementen und einer Länge von 4 zurück? – nnnnnn

1

Wenn Sie ein erstellen new Array(x) es schafft, was ein spärliche Array genannt wird, die ein bisschen anders verhalten könnten, wie Sie sehen können, werden einige Browser [undefined x 20,"foo", undefined x 5] sagen, wenn Sie nur einen Satz Wert, und ich glaube, es iteriert nicht über diese Werte.

+0

Nicht sicher, ich folge ganz. Meinst du, wenn ich dies unterhalb der 'var rangeArr' Deklaration hinzufügen würde: 'rangeArr [0] = num1'? –

Verwandte Themen