Ich habe dies in Firefox-3.5.7 / Firebug-1.5.3 und Firefox-3.6.16 / Firebug-1.6.2 beobachtet
Wenn ich Firebug starte:
var x = new Array(3)
console.log(x)
// [undefined, undefined, undefined]
var y = [undefined, undefined, undefined]
console.log(y)
// [undefined, undefined, undefined]
console.log( x.constructor == y.constructor) // true
console.log(
x.map(function() { return 0; })
)
// [undefined, undefined, undefined]
console.log(
y.map(function() { return 0; })
)
// [0, 0, 0]
Was ist denn hier los? Ist das ein Fehler oder verstehe ich die Verwendung falsch new Array(3)
?
javascript
arrays
map-function
Rampion
quelle
quelle
var y = x.map(function(){return 0; });
, und ich erhalte dies sowohl für die neue Array () -Methode als auch für das Array-Literal. Ich habe in Firefox 4 und Chrome getestet.Antworten:
Es scheint, dass das erste Beispiel
Erstellt ein Array mit undefinierten Zeigern.
Und die zweite erstellt ein Array mit Zeigern auf 3 undefinierte Objekte. In diesem Fall sind die Zeiger selbst NICHT undefiniert, sondern nur die Objekte, auf die sie zeigen.
Da die Map im Kontext der Objekte im Array ausgeführt wird, kann die erste Map meiner Meinung nach die Funktion überhaupt nicht ausführen, während die zweite ausgeführt werden kann.
quelle
map
Ruft eine bereitgestellte Rückruffunktion einmal für jedes Element in einem Array in der angegebenen Reihenfolge auf und erstellt aus den Ergebnissen ein neues Array.callback
Wird nur für Indizes des Arrays aufgerufen, denen Werte zugewiesen wurden . Es wird nicht aufgerufen." für Indizes, die gelöscht wurden oder denen nie Werte zugewiesen wurden. " In diesem Fall wurdenx
den Werten nicht explizit Werte zugewiesen, wohingegen die Wertey
zugewiesen wurden, selbst wenn es sich um den Wert handelteundefined
.(new Array(1))[0] === [undefined][0]
.hasOwnProperty
sei denn , eshasOwnProperty
selbst hat einen Fehler:(new Array(1)).hasOwnProperty(0) === false
und[undefined].hasOwnProperty(0) === true
. In der Tat können Sie genau das Gleiche tun mitin
:0 in [undefined] === true
und0 in new Array(0) === false
.x = new Array(3);
ist gleichbedeutend mitx = [,,,];
nichtx = [undefined, undefined, undefined]
.Ich hatte eine Aufgabe, bei der ich nur die Länge des Arrays kannte und die Elemente transformieren musste. Ich wollte so etwas machen:
So erstellen Sie schnell ein Array wie folgt:
Aber es hat nicht funktioniert, weil: (siehe Jonathan Lonowskis Antwort einige Antworten oben)
Die Lösung könnte darin bestehen, die Array-Elemente mit Array.prototype.fill () mit einem beliebigen Wert (auch mit undefinierten) zu füllen.
Code-Snippet anzeigen
Aktualisieren
Eine andere Lösung könnte sein:
quelle
undefined
in der.fill()
Methode nicht angeben müssen , wodurch der Code geringfügig vereinfacht wirdlet arr = new Array(10).fill().map((val,idx) => idx);
Array.from(Array(10))
Mit ES6 können Sie dies
[...Array(10)].map((a, b) => a)
schnell und einfach tun !quelle
new Array(10).fill()
. Gleiches Ergebnis wie[...Array(10)]
[...Array(10).keys()]
ES6-Lösung:
Funktioniert jedoch nicht mit Typoskript (2.3)
quelle
Array(10).fill("").map( ...
hat bei Typescript 2.9Die Arrays sind unterschiedlich. Der Unterschied besteht darin, dass
new Array(3)
ein Array mit einer Länge von drei, aber keinen Eigenschaften erstellt wird, während[undefined, undefined, undefined]
ein Array mit einer Länge von drei und drei Eigenschaften mit den Namen "0", "1" und "2" mit dem Wert "0" erstellt wirdundefined
. Sie können den Unterschied mit demin
Operator sehen:Dies ist auf die etwas verwirrende Tatsache zurückzuführen, dass beim Versuch, den Wert einer nicht vorhandenen Eigenschaft eines nativen Objekts in JavaScript abzurufen, dieser zurückgegeben wird
undefined
(anstatt einen Fehler auszulösen, wie dies der Fall ist, wenn Sie versuchen, auf eine nicht vorhandene Variable zu verweisen ), was dem entspricht, was Sie erhalten, wenn die Eigenschaft zuvor explizit festgelegt wurdeundefined
.quelle
Von der MDC-Seite für
map
:[undefined]
Wendet den Setter tatsächlich auf die Indizes an, sodass diesemap
iteriert werden, währendnew Array(1)
die Indizes nur mit dem Standardwert initialisiert werden,undefined
sodass siemap
übersprungen werden.Ich glaube, dass dies für alle Iterationsmethoden gleich ist .
quelle
In der Spezifikation der 6. Ausgabe von ECMAScript.
new Array(3)
Definieren Sie nur Eigenschaftenlength
und definieren Sie keine Indexeigenschaften wie{length: 3}
. Siehe https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array-len Schritt 9.[undefined, undefined, undefined]
definiert Indexeigenschaften und Längeneigenschaften wie{0: undefined, 1: undefined, 2: undefined, length: 3}
. Siehe https://www.ecma-international.org/ecma-262/6.0/index.html#sec-runtime-semantics-arrayaccumulationElementList
Schritt 5.Methoden
map
,every
,some
,forEach
,slice
,reduce
,reduceRight
,filter
der den Index Array Durch prüfenHasProperty
interne Methode, sonew Array(3).map(v => 1)
wird nicht invoke den Rückruf.Weitere Informationen finden Sie unter https://www.ecma-international.org/ecma-262/6.0/index.html#sec-array.prototype.map
Wie repariert man?
quelle
Ich denke, der beste Weg, dies zu erklären, besteht darin, sich anzusehen, wie Chrome damit umgeht.
Was also tatsächlich passiert, ist, dass new Array () ein leeres Array zurückgibt, das eine Länge von 3, aber keine Werte hat. Wenn Sie also
x.map
auf einem technisch leeren Array ausgeführt werden, muss nichts festgelegt werden.Firefox "füllt" nur diese leeren Slots mit
undefined
, obwohl es keine Werte hat.Ich denke nicht, dass dies explizit ein Fehler ist, sondern nur eine schlechte Art, das darzustellen, was vor sich geht. Ich nehme an, Chrome ist "korrekter", weil es zeigt, dass das Array eigentlich nichts enthält.
quelle
Bin gerade darauf gestoßen. Es wäre sicher bequem, verwenden zu können
Array(n).map
.Array(3)
ergibt ungefähr{length: 3}
[undefined, undefined, undefined]
erstellt die nummerierten Eigenschaften :{0: undefined, 1: undefined, 2: undefined, length: 3}
.Die map () - Implementierung wirkt sich nur auf definierte Eigenschaften aus.
quelle
Kein Fehler. So wird der Array-Konstruktor so definiert, dass er funktioniert.
Von MDC:
Die
.map()
Methode enthält nur Elemente in dem Iterationsbereich des Arrays, denen explizit Werte zugewiesen wurden. Selbst eine explizite Zuweisung vonundefined
führt dazu, dass ein Wert als für die Aufnahme in die Iteration geeignet angesehen wird. Das scheint seltsam, aber es ist im Wesentlichen der Unterschied zwischen einer explizitenundefined
Eigenschaft für ein Objekt und einer fehlenden Eigenschaft:Das Objekt
x
hat keine Eigenschaft namens "z", und das Objekty
hat eine. In beiden Fällen scheint jedoch der "Wert" der Eigenschaft zu seinundefined
. In einem Array ist die Situation ähnlich: Der Wert vonlength
führt implizit eine Wertzuweisung für alle Elemente von Null bis durchlength - 1
. Die.map()
Funktion führt daher nichts aus (ruft den Rückruf nicht auf), wenn sie für ein Array aufgerufen wird, das mit dem Array-Konstruktor und einem numerischen Argument neu erstellt wurde.quelle
undefined
für immer sein werden?x = []
anstelle vonx = new Array()
Wenn Sie dies tun, um ein Array einfach mit Werten zu füllen, aus Gründen der Browserunterstützung keine Füllung verwenden können und wirklich keine for-Schleife ausführen möchten, können Sie dies auch tun,
x = new Array(3).join(".").split(".").map(...
wodurch Sie ein leeres Array erhalten Saiten.Ziemlich hässlich muss ich sagen, aber zumindest das Problem und die Absicht werden ganz klar kommuniziert.
quelle
Da die Frage ist, warum, hat dies damit zu tun, wie JS entworfen wurde.
Es gibt zwei Hauptgründe, warum ich mir dieses Verhalten erklären kann:
Leistung: Gegeben
x = 10000
undnew Array(x)
es ist ratsam, dass der Konstruktor eine Schleife von 0 bis 10000 vermeidet, um das Array mitundefined
Werten zu füllen .Implizit „undefined“: give
a = [undefined, undefined]
undb = new Array(2)
,a[1]
undb[1]
werden beide Rückkehrundefined
, sonderna[8]
undb[8]
auch zurückkehren ,undefined
selbst wenn sie von Bereich unterwegs sind.Letztendlich ist die Notation
empty x 3
eine Verknüpfung, um zu vermeiden, dass eine lange Liste vonundefined
Werten festgelegt und angezeigt wird , dieundefined
ohnehin nicht explizit deklariert sind.Hinweis: Bei Array
a = [0]
unda[9] = 9
,console.log(a)
kehrt(10) [0, empty x 8, 9]
, füllt die Lücke automatisch , indem die Differenz zwischen den beiden Werten Rückkehr ausdrücklich erklärt.quelle
Aus Gründen, die in anderen Antworten ausführlich erläutert wurden,
Array(n).map
funktioniert dies nicht. In ES2015 wird jedochArray.from
eine Kartenfunktion akzeptiert:quelle
Hier ist eine einfache Dienstprogrammmethode als Problemumgehung:
Einfache mapFor
Vollständiges Beispiel
Hier ist ein vollständigeres Beispiel (mit Sanity Checks), mit dem auch ein optionaler Startindex angegeben werden kann:
Runterzählen
Durch Manipulieren des an den Rückruf übergebenen Index kann rückwärts gezählt werden:
quelle