Start · Sprachen · JavaScript · Referenz · Set.prototype.add()

Set.prototype.add()

Methode

Fügt den angegebenen Wert in das <code>Set</code>-Objekt ein, sofern er nicht bereits enthalten ist, und gibt das Set selbst zurück.

seit JavaScript ES2015 Kategorie: method-property

Signatur

Set.prototype.add(value)

Beschreibung

Die Methode add() fügt einen Wert in ein Set ein. Ist der Wert schon vorhanden, bleibt das Set unverändert. Es entsteht also nie ein Duplikat. Damit eignet sich add() gut, um eindeutige Werte zu sammeln, etwa IDs, Tags oder bereits besuchte Knoten beim Durchlaufen eines Graphen.

Ob ein Wert „gleich“ ist, entscheidet der Algorithmus SameValueZero: Er arbeitet wie ===, behandelt aber NaN als gleich zu NaN. Außerdem gelten +0 und -0 als derselbe Wert, und -0 wird als +0 gespeichert. Objekte und Arrays werden nach ihrer Referenz verglichen, nicht nach ihrem Inhalt.

Das Set merkt sich die Reihenfolge, in der Werte eingefügt wurden. Beim Durchlaufen mit for...of, forEach() oder values() kommen die Werte in genau dieser Reihenfolge. Ein erneutes add() mit einem vorhandenen Wert ändert seine Position nicht.

Weil add() das Set selbst zurückgibt, lassen sich mehrere Aufrufe verketten, zum Beispiel set.add(1).add(2).

Parameter

Name Typ Default Beschreibung
$value Pflicht any Der Wert, der eingefügt werden soll. Erlaubt ist jeder Typ: primitive Werte, Objekte, Funktionen, undefined oder NaN. Ohne Argument wird undefined eingefügt.

Rückgabewert

Typ
Set
Beschreibung
Dasselbe Set-Objekt, auf dem add() aufgerufen wurde. Dadurch lassen sich Aufrufe verketten. Ob der Wert neu war, verrät der Rückgabewert nicht.

Beispiele

Einfaches Einfügen und Verketten

const farben = new Set();

farben.add('rot').add('grün').add('blau');
farben.add('rot'); // bereits vorhanden – wird ignoriert

console.log(farben.size);
console.log([...farben]);
3 [ 'rot', 'grün', 'blau' ]

Eindeutige Tags aus Blogartikeln sammeln

const artikel = [
  { titel: 'Async JS', tags: ['javascript', 'async'] },
  { titel: 'Promises', tags: ['javascript', 'promise', 'async'] },
  { titel: 'CSS Grid', tags: ['css', 'layout'] }
];

const alleTags = new Set();
for (const { tags } of artikel) {
  tags.forEach((tag) => alleTags.add(tag));
}

console.log([...alleTags].sort());
[ 'async', 'css', 'javascript', 'layout', 'promise' ]

Prüfen, ob ein Wert neu war (Rückgabewert hilft nicht)

const gesehen = new Set();

const istNeu = (id) => {
  if (gesehen.has(id)) return false;
  gesehen.add(id);
  return true;
};

console.log(istNeu(42)); // true
console.log(istNeu(42)); // false
console.log(istNeu(7));  // true
true false true

Gleichheit: Objekte, NaN und -0

const s = new Set();

s.add({ id: 1 });
s.add({ id: 1 });   // anderes Objekt → wird ebenfalls eingefügt
s.add(NaN);
s.add(NaN);         // NaN gilt als gleich → ignoriert
s.add(0);
s.add(-0);          // gilt als gleich zu 0 → ignoriert

console.log(s.size);
console.log(Object.is([...s].at(-1), -0));
4 false

// Wichtig · Fallstricke

  • Referenzvergleich bei Objekten: set.add({a: 1}) zweimal aufzurufen erzeugt zwei Einträge. Wer Objekte nach ihrem Inhalt entdoppeln will, braucht einen eindeutigen Schlüssel, zum Beispiel set.add(obj.id), oder eine Map mit Schlüssel als Index.
  • Rückgabewert: add() gibt immer das Set zurück, nie true oder false. Ob ein Wert neu war, prüft man vorher mit has() oder vergleicht size vor und nach dem Aufruf.
  • Nur ein Argument: set.add(1, 2, 3) fügt nur 1 ein. Mehrere Werte fügt man mit einer Schleife ein oder erzeugt das Set direkt: new Set([1, 2, 3]).
  • Veränderung während der Iteration: Werte, die während eines for...of- oder forEach()-Durchlaufs hinzukommen, werden in diesem Durchlauf noch besucht. Das kann Endlosschleifen verursachen.
  • Speicher: Ein Set hält starke Referenzen auf seine Werte. Für Objekte, die trotzdem vom Garbage Collector freigegeben werden sollen, ist WeakSet besser geeignet.
  • Kompatibilität: Wird in allen modernen Browsern und seit Node.js 0.12 unterstützt. Der Internet Explorer 11 unterstützt Set nur teilweise: Dort gibt add() undefined zurück, verkettete Aufrufe funktionieren also nicht.