Array.prototype.map()
Baseline
Weitgehend verfügbar
Diese Funktion ist gut etabliert und funktioniert auf vielen Geräten und in vielen Browserversionen. Sie ist seit Juli 2015 browserübergreifend verfügbar.
Die Methode map() von Array-Instanzen erstellt ein neues Array, das mit den Ergebnissen, die durch den Aufruf einer bereitgestellten Funktion für jedes Element im aufrufenden Array entstehen, befüllt ist.
Probieren Sie es aus
const array = [1, 4, 9, 16];
// Pass a function to map
const mapped = array.map((x) => x * 2);
console.log(mapped);
// Expected output: Array [2, 8, 18, 32]
Syntax
map(callbackFn)
map(callbackFn, thisArg)
Parameter
callbackFn-
Eine Funktion, die für jedes Element im Array ausgeführt wird. Der Rückgabewert wird als einzelnes Element im neuen Array hinzugefügt. Die Funktion wird mit den folgenden Argumenten aufgerufen:
thisArgOptional-
Ein Wert, der als
thisverwendet wird, wenncallbackFnausgeführt wird. Siehe iterative Methoden.
Rückgabewert
Ein neues Array, bei dem jedes Element das Ergebnis der Rückruffunktion ist.
Beschreibung
Die Methode map() ist eine iterative Methode. Sie ruft eine bereitgestellte callbackFn-Funktion einmal für jedes Element in einem Array auf und konstruiert ein neues Array aus den Ergebnissen. Lesen Sie den Abschnitt über iterative Methoden, um mehr darüber zu erfahren, wie diese Methoden im Allgemeinen funktionieren.
callbackFn wird nur für Array-Indizes aufgerufen, denen Werte zugewiesen wurden. Es wird nicht für leere Slots in spärlichen Arrays aufgerufen.
Die Methode map() ist generisch. Sie erwartet nur, dass der this-Wert eine length-Eigenschaft und ganzzahlig indizierte Eigenschaften hat.
Da map ein neues Array erstellt, ist es ein Anti-Pattern, es aufzurufen, ohne das zurückgegebene Array zu verwenden. Verwenden Sie stattdessen forEach oder for...of.
Beispiele
>Abbilden eines Arrays von Zahlen zu einem Array von Quadratwurzeln
Der folgende Code nimmt ein Array von Zahlen und erstellt ein neues Array, das die Quadratwurzeln der Zahlen im ersten Array enthält.
const numbers = [1, 4, 9];
const roots = numbers.map((num) => Math.sqrt(num));
// roots is now [1, 2, 3]
// numbers is still [1, 4, 9]
Verwenden von map, um Objekte in einem Array neu zu formatieren
Der folgende Code nimmt ein Array von Objekten und erstellt ein neues Array mit den neu formatierten Objekten.
const kvArray = [
{ key: 1, value: 10 },
{ key: 2, value: 20 },
{ key: 3, value: 30 },
];
const reformattedArray = kvArray.map(({ key, value }) => ({ [key]: value }));
console.log(reformattedArray); // [{ 1: 10 }, { 2: 20 }, { 3: 30 }]
console.log(kvArray);
// [
// { key: 1, value: 10 },
// { key: 2, value: 20 },
// { key: 3, value: 30 }
// ]
Verwenden von parseInt() mit map()
Es ist üblich, den Rückruf mit einem Argument zu verwenden (das durchlaufene Element). Bestimmte Funktionen werden häufig auch mit einem Argument verwendet, selbst wenn sie zusätzliche optionale Argumente haben. Diese Gewohnheiten können zu verwirrendem Verhalten führen. Betrachten Sie:
["1", "2", "3"].map(parseInt);
Während man [1, 2, 3] erwarten könnte, ist das tatsächliche Ergebnis [1, NaN, NaN].
parseInt wird oft mit einem Argument verwendet, nimmt aber zwei. Das erste ist ein Ausdruck und das zweite ist die Basis zur Rückruffunktion, Array.prototype.map übergibt 3 Argumente: das Element, den Index und das Array. Das dritte Argument wird von parseInt ignoriert — aber nicht das zweite! Dies ist die Quelle möglicher Verwirrung.
Hier ist ein prägnantes Beispiel der Iterationsschritte:
/* first iteration (index is 0): */ parseInt("1", 0); // 1
/* second iteration (index is 1): */ parseInt("2", 1); // NaN
/* third iteration (index is 2): */ parseInt("3", 2); // NaN
Um dies zu lösen, definieren Sie eine andere Funktion, die nur ein Argument nimmt:
["1", "2", "3"].map((str) => parseInt(str, 10)); // [1, 2, 3]
Sie können auch die Number-Funktion verwenden, die nur ein Argument nimmt:
["1", "2", "3"].map(Number); // [1, 2, 3]
// But unlike parseInt(), Number() will also return a float or (resolved) exponential notation:
["1.1", "2.2e2", "3e300"].map(Number); // [1.1, 220, 3e+300]
// For comparison, if we use parseInt() on the array above:
["1.1", "2.2e2", "3e300"].map((str) => parseInt(str, 10)); // [1, 2, 3]
Lesen Sie A JavaScript optional argument hazard von Allen Wirfs-Brock für weitere Diskussionen.
Abgebildetes Array enthält undefined
Wenn undefined oder nichts zurückgegeben wird, enthält das resultierende Array undefined. Wenn Sie stattdessen das Element löschen möchten, verketten Sie eine filter()-Methode oder verwenden Sie die flatMap()-Methode und geben Sie ein leeres Array zurück, um die Löschung anzuzeigen.
const numbers = [1, 2, 3, 4];
const filteredNumbers = numbers.map((num, index) => {
if (index < 3) {
return num;
}
});
// index goes from 0, so the filteredNumbers are 1,2,3 and undefined.
// filteredNumbers is [1, 2, 3, undefined]
// numbers is still [1, 2, 3, 4]
Seiteneffektanfälliges Mapping
Der Rückruf kann Seiteneffekte haben.
const cart = [5, 15, 25];
let total = 0;
const withTax = cart.map((cost) => {
total += cost;
return cost * 1.2;
});
console.log(withTax); // [6, 18, 30]
console.log(total); // 45
Dies wird nicht empfohlen, da Kopiermethoden am besten mit reinen Funktionen verwendet werden. In diesem Fall können wir wählen, das Array zweimal zu durchlaufen.
const cart = [5, 15, 25];
const total = cart.reduce((acc, cost) => acc + cost, 0);
const withTax = cart.map((cost) => cost * 1.2);
Manchmal geht dieses Muster bis zum Extrem und die einzige nützliche Sache, die map() tut, ist Nebenwirkungen zu verursachen.
const products = [
{ name: "sports car" },
{ name: "laptop" },
{ name: "phone" },
];
products.map((product) => {
product.price = 100;
});
Wie bereits erwähnt, ist dies ein Anti-Pattern. Wenn Sie den Rückgabewert von map() nicht verwenden, verwenden Sie stattdessen forEach() oder eine for...of-Schleife.
products.forEach((product) => {
product.price = 100;
});
Oder, wenn Sie stattdessen ein neues Array erstellen möchten:
const productsWithPrice = products.map((product) => ({
...product,
price: 100,
}));
Verwenden des dritten Arguments von callbackFn
Das array-Argument ist nützlich, wenn Sie auf ein anderes Element im Array zugreifen möchten, insbesondere wenn Sie keine vorhandene Variable haben, die auf das Array verweist. Das folgende Beispiel verwendet zuerst filter(), um die positiven Werte zu extrahieren, und dann map(), um ein neues Array zu erstellen, wobei jedes Element der Durchschnitt seiner Nachbarn und es selbst ist.
const numbers = [3, -1, 1, 4, 1, 5, 9, 2, 6];
const averaged = numbers
.filter((num) => num > 0)
.map((num, idx, arr) => {
// Without the arr argument, there's no way to easily access the
// intermediate array without saving it to a variable.
const prev = arr[idx - 1];
const next = arr[idx + 1];
let count = 1;
let total = num;
if (prev !== undefined) {
count++;
total += prev;
}
if (next !== undefined) {
count++;
total += next;
}
const average = total / count;
// Keep two decimal places
return Math.round(average * 100) / 100;
});
console.log(averaged); // [2, 2.67, 2, 3.33, 5, 5.33, 5.67, 4]
Das array-Argument ist nicht das Array, das erstellt wird — es gibt keine Möglichkeit, auf das Array zuzugreifen, das gerade aus der Rückruffunktion erstellt wird.
Verwenden von map() bei spärlichen Arrays
Ein spärliches Array bleibt nach map() spärlich. Die Indizes leerer Slots sind im zurückgegebenen Array immer noch leer, und die Rückruffunktion wird nicht für sie aufgerufen.
console.log(
[1, , 3].map((x, index) => {
console.log(`Visit ${index}`);
return x * 2;
}),
);
// Visit 0
// Visit 2
// [2, empty, 6]
Aufrufen von map() bei Nicht-Array-Objekten
Die Methode map() liest die length-Eigenschaft von this und greift dann auf jede Eigenschaft zu, deren Schlüssel eine nichtnegative ganze Zahl kleiner als length ist.
const arrayLike = {
length: 3,
0: 2,
1: 3,
2: 4,
3: 5, // ignored by map() since length is 3
};
console.log(Array.prototype.map.call(arrayLike, (x) => x ** 2));
// [ 4, 9, 16 ]
Dieses Beispiel zeigt, wie man durch eine Sammlung von Objekten iteriert, die von querySelectorAll gesammelt wurden. Dies liegt daran, dass querySelectorAll eine NodeList zurückgibt (was eine Sammlung von Objekten ist). In diesem Fall geben wir alle ausgewählten option-Werte auf dem Bildschirm zurück:
const elems = document.querySelectorAll("select option:checked");
const values = Array.prototype.map.call(elems, ({ value }) => value);
Sie können auch Array.from() verwenden, um elems in ein Array zu transformieren und dann auf die map()-Methode zuzugreifen.
Spezifikationen
| Spezifikation |
|---|
| ECMAScript® 2027 Language Specification> # sec-array.prototype.map> |