Tücken von JavaScript `for...in`-Schleifen
Die 3-Ausdruck-Form der for
-Schleife à la C wird in JavaScript wird oft als altmodisch oder als unbeholfener Anfänger-Stil betrachtet. Manche Entwickler nutzen stattdessen automatisch eine for...of
-, foreach
- oder for...in
-Schleife. Letztere hat jedoch eine Besonderheit, die zu subtilen Fehlern führen kann.
Warum sind meine Listenindizes plötzlich Strings?
Dieser kleine JavaScript-Schnipsel soll eine 0-basierte Liste von Indizes in eine 1-basierte Liste umwandeln:
const zeroBased = ['foo', 'bar', 'baz'];
for (const i in zeroBased) {
console.log(${i + 1});
}
Die Ausgabe ist vielleicht nicht das, was du erwartest:
01
11
21
Das wird klarer, wenn du den Code leicht änderst:
const zeroBased = ['foo', 'bar', 'baz'];
for (const i in zeroBased) {
console.log(${i + 1} (${typeof i}));
}
Ausgabe
01 (string)
11 (string)
21 (string)
Es sieht so aus, als würen alle Indizes in Strings umgewandelt und der Operator +
addiert nicht,, sondern fügt Strings zusammen.
Aber die Erklärung ist nicht ganz korrekt. Tatsächlich werden keine Indizes in Strings konvertiert. Array in JavaScript sind einfach Objekte und Object-Schlüssel sind immer Strings. String-Schlüssel und numerische Schlüssel lassen sich sogar mischen:
const arr = ['foo', 'bar', 'baz'];
arr['four'] = 'huh?';
console.log(arr['four']); // Ausgabe 'huh?'.
console.log(Array.isArray(arr)); // Ausgabe `true`.
console.log(arr); // Ausgabe `[ 'foo', 'bar', 'baz', four: 'huh?' ]`
In Wirklichkeit unterscheiden sich JavaScript-Arrays von allgemeinen Objekten nur darin, dass für sie zusätzliche Methoden wie map()
und filter()
definiert sind. Aber die Unterschiede sehen größer aus, als sie sind, weil Funktionen JSON.stringy()
, console.log()
, console.dir()
und Freunde Arrays und Nicht-Array-Objekte unterschiedlich serialisieren und visualisieren.
Oft bleiben die subtilen Probleme, die sich hieraus ergeben, unbemerkt, weil Code, der das ignoriert, einfach funktioniert. Betrachten wir dieses Beispiel:
const zeroBased = ['foo', 'bar', 'baz'];
for (const i in zeroBased) {
console.log(zeroBased[i]);
}
Ausgabe
foo
bar
baz
Die Variable i ist hier immer noch ein String. Wird sie aber als Array-Index verwendet wird, wird sie automatisch in eine Zahl umgewandelt.
Fazit
Wenn du auf Array-Indizes zugreifen möchtest, nutze die 3-Ausdruck-Form der for
-Schleife! Sie ist vielleicht weniger prägnant, aber sie ist klarer. Und sie ist effizienter, wenn du die Indizes als Zahlen benötigst, da du dir das Umwandeln der Strings zurück in Zahlen mit parseInt()
sparst, was nicht nur hässlich, sondern auch eine Verschwendung von CPU-Zyklen ist.
Leave a comment