JavaScript: Wie entfernt man ein bestimmtes Element aus einem Array?

Es gibt zwei Antworten, und welche du willst, hängt an einer Frage, die niemand laut stellt: Willst du ein neues Array, oder willst du dieses hier verändert?

filter oder splice

const a = ["a", "b", "c", "b"];
a.filter(x => x !== "b");        // neues Array
const i = a.indexOf("b");
if (i > -1) a.splice(i, 1);      // dieses Array
start           : [ 'a', 'b', 'c', 'b' ]
filter !== 'b'  : [ 'a', 'c' ]  <- removes ALL 'b'
indexOf+splice  : [ 'a', 'c', 'b' ]  <- removes the FIRST 'b' only

Gleiche Eingabe, verschiedene Ergebnisse, und keines davon ist falsch. filter prüft jedes Element, also fliegt jeder Treffer raus. indexOf findet eine Position, also fliegt ein Element raus.

Der andere Unterschied:

after filter, original : [ 'a', 'b', 'c', 'b' ]
after splice, original : [ 'a', 'c', 'b' ]  <- changed

splice verändert das Original. Das ist in dem Moment wichtig, in dem noch jemand eine Referenz auf dasselbe Array hält.

Die Prüfung ist nicht optional

Lässt du das if weg, passiert im Fehlschlag-Fall etwas Bestimmtes und Schlechtes:

indexOf('zzz') : -1
splice(-1, 1)  : [ 'a', 'b', 'c' ]  <- removed the LAST item instead of nothing

Ein negativer Index zählt von hinten, -1 heißt also “das letzte”. Die Suche nach etwas, das gar nicht da ist, löscht ein echtes Element — ohne Fehler, ohne Warnung, und zwar eines, das du nie genannt hast. Immer auf > -1 prüfen.

delete ist es nicht

delete d[1];
after delete d[1] : [ 'a', <1 empty item>, 'c', 'b' ]
length            : 4  <- unchanged
1 in d            : false

delete entfernt den Wert, nicht den Platz. Übrig bleiben ein Loch, eine unveränderte length und ein Array, das sich in allem, was darüber iteriert, seltsam verhält.

splice sagt dir, was es genommen hat

splice(1, 2) returned: [ 'b', 'c' ]  leaving [ 'a', 'b' ]

Das zweite Argument ist eine Anzahl, kein End-Index, und der Rückgabewert sind die entfernten Elemente — praktisch, wenn du etwas verschieben statt wegwerfen willst.

Nach Index, ohne zu verändern

t.toSpliced(1, 1) : [ 'a', 'c', 'b' ]  original still [ 'a', 'b', 'c', 'b' ]
typeof Array.prototype.toSpliced : function

toSpliced ist splice, das eine Kopie zurückgibt. ES2023 — in aktuellen Laufzeiten also vorhanden, aber nicht in dem, was du unterstützen sollst.

Objekte vergleichen sich über die Identität

filter(o => o !== {id:2}) : 2 items <- nothing removed
filter(o => o.id !== 2)   : [ { id: 1 } ]

Zwei Objekte mit gleichem Inhalt sind nicht ===. Ein Objekt zu entfernen heißt entweder, ein Feld zu vergleichen, oder die ursprüngliche Referenz zu haben.

Entfernen beim Vorwärtsiterieren überspringt Elemente

forwards  : [ 'a', 'b', 'c' ]  <- one 'b' survived
backwards : [ 'a', 'c' ]

Ein splice an Index i rückt alles dahinter um eins nach vorn, das nächste Element rutscht also genau auf den Platz, den die Schleife gerade verlassen hat. Rückwärts iterieren, oder filter nehmen.

Und für die Enden braucht es nichts von alledem:

pop()   : b  leaving [ 'a', 'b', 'c' ]
shift() : a  leaving [ 'b', 'c' ]

Hinweis zu Netcup (Werbung)

Der deutsche Hoster Netcup bietet unter anderem günstige und zugleich leistungsstarke Webhosting Pakete, KVM-basierte Root Server und dezidierte Server an. Mit unseren Gutscheincodes kannst du noch mehr Geld sparen (6€ bei deiner ersten Bestellung, 30% Rabatt auf alle KVM-basierten Root Server, ...).