Die moderne Art eine Radiobutton-Gruppe abzufragen

Die Abfrage von Radiobutton-Gruppen war schon immer etwas aufwendig, weil man nur den Status eines einzelnen Radiobuttons und nicht die ganze Gruppe abfragen kann.

Banana
Apple
Cherry

const fruits = document.getElementsByName('fruits');
var selectedFruit = '';
for (var i = 0; i < fruits.length; ++i) {
if (fruits[i].checked) {
selectedFruit = fruits[i].id;
}
}

Das sieht sehr archaisch aus. Da muss es doch einen besseren Weg mit den neuen ES6-Features geben. Den gibt es! Seit ES2015 enthält NodeList die Methode forEach, das die Sache schon mal einfacher macht:

var fruits = document.getElementsByName('fruits');
let selectedFruit = '';
fruits.forEach((fruit) => {
if (fruit.checked) {
selectedFruit = fruit.id;
}
});

Immer noch ziemlich viel Codezeilen. Man kann das Ganze aber viel kompakter, aber auch unleserlicher machen:

[…document.getElementsByName('fruits')].some(
(fruit) => (selectedFruit = fruit.id) && fruit.checked
);

Hier ist ein wenig Erklärung notwendig, denn wir müssen ganz tief in die Trickkiste greifen.

Als erste wandeln wir mit dem Spread-Operator die NodeList in ein Array() um, damit wir die coolen neuen Array()-Methoden nutzen können. Die Array()-Methode die nutzen ist some. Diese Methode durchläuft das Array bis die Callback-Methode true zurück gibt. In unserem Fall verlassen wir den Schleife indem wir auf „fruit.checked“ überprüfen, das true ist, wenn der Radiobutton aktiv ist.

Der zweite Trick ist es, die Zuweisung der Schleifenvariablen fruit an die Variable selectedFruit mit in die Abbruchlogik aufzunehmen. Die Zuweisung ergibt immer true und beeinflusst somit das Ergebnis der gesamten Anweisung nicht, wenn es mit der && Anweisung mit dem Vergleich verbunden wird.

Nebenbei, wir benötigen keine Deklaration der Variablen selectedFruit in übergeordneten Scope mehr, da wir in der Callback-Funktion keinen neuen Scope eröffnen. Ein neuer Scope erfordert geschwungene Klammern und die werden in diesem Fall nicht benötigt, weil die Callback-Funktion nur eine Anweisung enthält.
Man könnte jetzt pingelig sein und anmerken, dass selectedFruit nicht ordentlich deklariert sind, aber der Code funktioniert. Also egal!

Edit:
Ich habe diesen Artikel auf dev.to veröffentlicht und Jon Randy hat einen interessanten Kommentar gegeben:

Shorter:

let selectedFruit = […document.getElementsByName('fruits')].find(({checked}) => checked).id

Shorter still:

let selectedFruit = document.querySelector('[name=fruits][checked]')?.id