2015-02-09 14 views
9

Was genau ist der Unterschied zwischen:Unterschied zwischen Array.apply (null, Array (x)) und Array (x)

Array(3) 
// and 
Array.apply(null, Array(3)) 

Die ersten kehrt [undefined x 3] während die zweite zurückkehrt [undefined, undefined, undefined]. Die zweite ist durch Array.prototype.functions wie .map kettenfähig, aber die erste ist nicht. Warum?

+0

'Array.apply (null, Array (9))' ist * nicht * 'new Array (9) '. Es verteilt ein 'Array (9)' in 'Array()' als neun Parameter. Auch wenn es funktioniert, ist es ziemlich falsch. Zum Beispiel können Sie 'new Array (1e7)', aber nicht 'Array.apply (null, Array (1e7))'. – Sheepy

+1

Related: http://StackOverflow.com/Questions/22949976/Why-does-Array-Applynull-ARGS-ACT-inConsistently-When-dealing-with-sparse-a – Sheepy

Antwort

13

Es gibt einen Unterschied, einen ziemlich bedeutenden.

Die Array Konstruktor entweder akzeptiert eine einzelne Zahl, die Länge des Arrays zu geben, und ein Array mit „leeren“ Indizes erstellt wird, oder genauer gesagt die Länge festgelegt ist, aber das Array wirklich nicht enthält alles

Array(3); // creates [], with a length of 3 

Wenn sie mit einer Nummer als einziges Argument das Array Konstruktor aufrufen, erstellen Sie ein Array, das leer ist, und das kann nicht mit den üblichen Array Methoden wiederholt werden.

Oder ... der Array-Konstruktor akzeptiert mehrere Argumente, während ein Array erstellt wird, in dem jedes Argument ein Wert im Array ist

Array(1,2,3); // creates an array [1,2,3] etc. 

Wenn Sie nennen diese

Array.apply(null, Array(3)) 

Es wird ein bisschen interessanter.

apply nimmt die this Wert als erstes Argument, und da es hier nicht sinnvoll ist, ist es auf null

Der interessante Teil ist das zweite Argument, wo ein leeres Array übergeben wird.
Als apply ein Array akzeptieren würde es wie

Array(undefined, undefined, undefined); 

Aufruf und das erstellt ein Array mit drei Indizes, die nicht leer sind, aber den Wert tatsächlich auf undefined, weshalb ist es ca n iteriert werden.

TL; DR
Der Hauptunterschied besteht darin, dass Array(3) ein Array mit drei Indizes erzeugt, die leer sind. Tatsächlich existieren sie nicht wirklich, das Array hat nur eine Länge von 3.

Passing in einem solchen Array mit leeren Indizes an den Array-Konstruktor apply Verwendung ist die gleiche wie Array(undefined, undefined, undefined); tun, die mit drei undefined Indizes ein Array erzeugt, und undefined ist tatsächlich ein Wert ist, so dass es leer ist nicht wie in der ersten Beispiel.

Array-Methoden wie map() können nur über tatsächliche Werte iterieren, nicht leere Indizes.

0

Da das erste Array nicht Eigenschaften arr[0] === undefined geordnet hätte und das zweite tut.Array-Funktionen wie forEach und map werden von 0 bis zur Länge des Arrays iterieren - 1 und das Fehlen der Reihenfolge der Eigenschaften des ersten ist ein Problem. Die zweite Version erzeugt ein Array mit der richtigen Reihenfolge, d.h.

arr = Array.apply(null, Array(3)); 
arr[0] === undefined //true 
arr[1] === undefined //true 
//etc. 

Die erste Version, wie Sie bemerkt haben, nicht. Auch das Hinzufügen von new zur ersten Version würde es nicht funktionieren lassen.

11

Die API .map() iteriert nicht vollständig über nicht initialisierte Array-Elemente. Wenn Sie ein neues Array mit dem new Array(n) Konstruktor erstellen, erhalten Sie ein Array mit dem .length, nach dem Sie gefragt haben, aber mit nicht vorhandenen Elementen, die von Methoden wie .map() übersprungen werden.

Der Ausdruck Array.apply(null, Array(9)) füllt die neu erstellte Array-Instanz explizit mit undefined, aber das ist gut genug. Der Trick besteht darin, ob der Operator in meldet, dass das Array ein Element im angegebenen Index enthält. Das heißt:

var a = new Array(9); 
alert(2 in a); // alerts "false" 

Das ist, weil es wirklich kein Element an Position 2 in der Anordnung. Aber:

Der äußere Aufruf des Array-Konstruktors wird die Elemente explizit ausgefüllt haben.

+0

Danke für die Antwort, ich war nicht wirklich sicher Das, was in jedem Slot war, war nicht dasselbe wie der Wert undefined, da die Indizierung in irgendeine gegebene Position undefiniert zurückkehrt. –

+1

@ mb_s88 betrachte '0 in Array (9); // false' –

+0

@ mb_s88 Antwort erweitert ein wenig – Pointy

3

Dies ist ein Artefakt davon, wie gelten funktioniert. Wenn Sie das tun:

new Array(9) 

ein leeres Array ist mit einer Länge von 9 Karte erstellt nicht inexistent Mitglieder nicht besuchen, so gar nichts tut. Allerdings stellt apply das Array in einer Liste unter Verwendung CreateListFromArrayLike so stellt sich das ehemals leere Array in einer Parameterliste wie:

[undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined,undefined]; 

, die Array übergeben wird ein Array mit 9 Mitgliedern zu schaffen, die alle mit einem Wert, von undefined. Jetzt wird die Karte sie alle besuchen.

BTW, ECMAScript 2015 hat Array.prototype.fill für diese (auch MDN sehen), so können Sie dies tun:

Array(9).fill(0); 
Verwandte Themen