# I nuovi metodi di Set in JavaScript: union, intersection, difference e gli altri

> Le operazioni insiemistiche native arrivate nei motori moderni — union, intersection, difference, symmetricDifference, isSubsetOf, isSupersetOf, isDisjointFrom — con esempi prima/dopo.

- Autore / Author: Diego Betto (https://diegobetto.com/about/)
- Pubblicato / Published: 2026-09-19
- URL: https://diegobetto.com/javascript-set-methods-union-intersection/
- Tag: javascript, set, 2026

Per anni, fare teoria degli insiemi di base in JavaScript — unione, intersezione, "cosa c'è in A ma non in B" — significava ricorrere a `Array.filter()`/`includes()` a mano, o importare una piccola libreria di utility. Non serve più: i motori JavaScript moderni ora offrono queste operazioni nativamente su `Set`.

> **Disponibilità**
>
> Questi metodi sono arrivati nelle versioni recenti di Chrome, Firefox, Safari e Node.js. Verifica
> i tuoi runtime target prima di affidartici senza polyfill — il supporto è ampio nel 2026 ma non
> universale sugli ambienti più vecchi che potresti dover ancora supportare.

## Il vecchio modo: operazioni insiemistiche basate su array

Prima che esistessero questi metodi, un'unione o un'intersezione significava scrivere questo a mano ogni volta:

```js
function union(a, b) {
  return new Set([...a, ...b]);
}

function intersection(a, b) {
  return new Set([...a].filter((x) => b.has(x)));
}

function difference(a, b) {
  return new Set([...a].filter((x) => !b.has(x)));
}
```

Corretto, ma verboso, e facile da sbagliare in modo sottile (unione senza deduplicazione, intersezione con complessità `O(n²)` quando entrambi gli input sono grandi). I nuovi metodi sono sia più concisi sia meglio ottimizzati internamente.

## I nuovi metodi

```js
const admin = new Set(["alice", "bob", "carol"]);
const editor = new Set(["bob", "carol", "dave"]);

admin.union(editor);
// Set(4) { 'alice', 'bob', 'carol', 'dave' }

admin.intersection(editor);
// Set(2) { 'bob', 'carol' }

admin.difference(editor);
// Set(1) { 'alice' } — in admin ma non in editor

admin.symmetricDifference(editor);
// Set(2) { 'alice', 'dave' } — in esattamente uno dei due set

admin.isSubsetOf(editor); // false
admin.isSupersetOf(new Set(["bob"])); // true
admin.isDisjointFrom(new Set(["zara"])); // true — nessun elemento in comune
```

Ognuno di questi si legge esattamente per quello che fa — nessuna callback di filter da interpretare, nessun rischio di modificare accidentalmente uno dei set di input (`union`, `intersection`, `difference` e `symmetricDifference` restituiscono tutti un **nuovo** `Set`, lasciando gli originali intatti).

## Un esempio pratico: confrontare set di permessi

Questo è il tipo di codice che prima richiedeva gli helper manuali sopra, e ora si legge quasi come il requisito stesso:

```js
function getPermissionChanges(currentPermissions, requestedPermissions) {
  return {
    added: requestedPermissions.difference(currentPermissions),
    removed: currentPermissions.difference(requestedPermissions),
    unchanged: currentPermissions.intersection(requestedPermissions),
  };
}

const current = new Set(["read", "write"]);
const requested = new Set(["write", "delete"]);

getPermissionChanges(current, requested);
// { added: Set {'delete'}, removed: Set {'read'}, unchanged: Set {'write'} }
```

## Riferimento dei metodi

| Metodo                     | Restituisce                                  |
| -------------------------- | -------------------------------------------- |
| `a.union(b)`               | Elementi in `a` o `b` (o entrambi)           |
| `a.intersection(b)`        | Elementi sia in `a` sia in `b`               |
| `a.difference(b)`          | Elementi in `a` ma non in `b`                |
| `a.symmetricDifference(b)` | Elementi in esattamente uno tra `a` e `b`    |
| `a.isSubsetOf(b)`          | `true` se ogni elemento di `a` è in `b`      |
| `a.isSupersetOf(b)`        | `true` se ogni elemento di `b` è in `a`      |
| `a.isDisjointFrom(b)`      | `true` se `a` e `b` non condividono elementi |

> Tutti e sette i metodi accettano come argomento qualsiasi oggetto "set-like", non solo un vero
> `Set` — un oggetto con una proprietà `size` e metodi `has()`/`keys()` funziona altrettanto bene,
> utile se stai interagendo con una libreria che modella un proprio tipo di collezione.

## FAQ

> **Questi metodi modificano i set originali?**
>
> No — `union`, `intersection`, `difference` e `symmetricDifference` restituiscono tutti un `Set`
> nuovo di zecca. I tre metodi predicato (`isSubsetOf`, `isSupersetOf`, `isDisjointFrom`)
> restituiscono un booleano e non toccano affatto nessuno dei due set.

> **È più veloce della versione manuale basata su array?**
>
> Generalmente sì — i motori possono implementare queste operazioni con una complessità migliore
> della `O(n × m)` che una combinazione `filter`+`includes` spesso ha, specialmente per set grandi.
> Non micro-ottimizzare attorno a questo, ma ora è un default ragionevole invece di loop scritti a
> mano.

> **Serve ancora una libreria come le utility set di lodash?**
>
> Per queste operazioni specifiche, no — i metodi nativi di `Set` coprono direttamente i casi
> comuni. Le librerie restano utili per cose non supportate nativamente, come operazioni
> insiemistiche ordinate che preservano un ordinamento specifico nel risultato.

## Conclusione

Le operazioni native di `Set` sostituiscono una classe di funzioni di utility scritte a mano che praticamente ogni codebase JavaScript finisce per accumulare. `union`, `intersection`, `difference`, `symmetricDifference`, e i tre predicati subset/superset/disjoint coprono la stragrande maggioranza dei confronti insiemistici reali — usali direttamente invece di scrivere helper `filter`+`includes` da zero.

**Riferimenti**

- [Set.prototype.union() – MDN](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Set/union)
- [Set.prototype.intersection() – MDN](https://developer.mozilla.org/it/docs/Web/JavaScript/Reference/Global_Objects/Set/intersection)
