javascript - forEach på en 'ny Array' gör inte vad jag förväntar mig


Jag håller precis på att lära mig hur man använder JS högre ordningens funktioner (map, forEach, reduce, etc), och har stött på förvirring. Jag försöker skriva en enkel 'range'-funktion, men kan inte tycks fylla min utmatningsarray. Detta är målet:

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

Jag får detta:

[undefined × 4]

Här är min kod:

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

Vad missar jag här? Så vitt jag kan se verkar problemet ha något att göra med hur jag använder 'new Array', men utöver det är jag vilse.

Åh, och här är delen som verkligen förvirrar mig. Detta fungerar bra:

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

Tack!!

Svar #1

Metoden forEach itererar över arrayens index. Intressant nog, när du skapar en ny array med new Array(n), innehåller den inga index alls. Istället sätter den bara sin .length-egenskap.

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

MDN beskriver forEach och specificerar särskilt:

forEach kör den angivna återuppringningsfunktionen en gång för varje element i arrayen med ett tilldelat värde. Den anropas inte för index som har tagits bort eller uteslutits.

Här är en snygg teknik för att få en array med tomma, men existerande, index.

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

Detta fungerar eftersom .apply "expanderar" de utelämnade elementen till riktiga argument, och resultatet blir något som Array(undefined, undefined, undefined).

Svar #2

Arrayen är definierad med 4 poster, var och en av dem är odefinierad.

Map kommer inte att iterera över odefinierade poster, den hoppar över dem.

callback anropas endast för index i arrayen som har tilldelade värden; det anropas inte för index som är odefinierade, de som har tagits bort eller som aldrig har tilldelats värden.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map