+39 3662317539/+34 620899163
info@simonecosci.com

structuredClone al posto di JSON.parse(JSON.stringify(x))

Sviluppo Siti Web a Tenerife

structuredClone al posto di JSON.parse(JSON.stringify(x))

Per anni il modo più veloce per fare una copia profonda di un oggetto in JavaScript è stato:

const copia = JSON.parse(JSON.stringify(originale));

Funziona, ma è un trucco che sfrutta un side-effect di due funzioni pensate per altro. E i side-effect si pagano: alcuni tipi di dato passano indenni per la serializzazione JSON, altri escono rotti senza nessun errore. Dal 2022 c’è un modo nativo per farlo bene: structuredClone().

Cosa rompe il vecchio trucco

JSON.stringify sa rappresentare solo quello che il formato JSON prevede: oggetti, array, stringhe, numeri, booleani, null. Tutto il resto viene silenziosamente trasformato o perso.

const originale = {
  quando: new Date(),
  mappa: new Map([["a", 1]]),
  insieme: new Set([1, 2, 3]),
  indefinito: undefined,
  numeroGrande: 10n,
};

const copia = JSON.parse(JSON.stringify(originale));
console.log(copia);
// {
//   quando: "2026-09-06T10:00:00.000Z",   <- diventata una stringa, non più un Date
//   mappa: {},                            <- Map svuotata: JSON non sa serializzarla
//   insieme: {},                          <- stessa sorte per Set
//   indefinito viene rimosso del tutto
//   numeroGrande: lancia TypeError, JSON non sa gestire i BigInt
// }

Il caso più insidioso è Date: il codice non si rompe, continua a girare, ma copia.quando non è più un oggetto Date. Se più avanti chiami copia.quando.getMonth(), l’errore arriva lontano dal punto in cui la copia è stata fatta, e ci vuole tempo a risalire alla causa.

C’è poi un caso che il trucco JSON non gestisce proprio: i riferimenti circolari.

const nodo = { valore: 1 };
nodo.self = nodo;

JSON.stringify(nodo); // TypeError: Converting circular structure to JSON

Cosa fa structuredClone

structuredClone() è una funzione globale, disponibile nei browser moderni e in Node.js dalla versione 17. Usa lo stesso algoritmo di serializzazione con cui il browser passa dati tra postMessage, worker e IndexedDB, quindi conosce molti più tipi:

const originale = {
  quando: new Date(),
  mappa: new Map([["a", 1]]),
  insieme: new Set([1, 2, 3]),
};

const copia = structuredClone(originale);
copia.quando instanceof Date;   // true
copia.mappa instanceof Map;     // true
copia.insieme instanceof Set;   // true

E gestisce anche i cicli, senza bisogno di librerie:

const nodo = { valore: 1 };
nodo.self = nodo;

const copia = structuredClone(nodo);
copia.self === copia; // true, il ciclo è stato ricreato correttamente

È anche più veloce: non passa da una rappresentazione testuale intermedia, lavora direttamente sulla struttura in memoria.

Cosa non copia

structuredClone() non è magia, e i suoi limiti sono precisi:

  • Funzioni: non sono clonabili. Se un oggetto ha un metodo o una callback tra le sue proprietà, structuredClone() lancia DataCloneError.
  • Prototipi: la copia è sempre un oggetto semplice (Object.prototype), le istanze di classi personalizzate perdono i metodi.
  • Symbol: le proprietà con chiave Symbol vengono ignorate.
  • DOM nodes: non clonabili (per quello c’è Node.cloneNode()).
class Prodotto {
  constructor(nome) { this.nome = nome; }
  saluta() { return `Ciao, sono ${this.nome}`; }
}

const p = new Prodotto("tavolo");
const copia = structuredClone(p);
copia.nome;     // "tavolo", il dato c'è
copia.saluta;   // undefined, il metodo no

Se serve preservare il prototipo, o clonare oggetti con funzioni al loro interno, structuredClone() non basta: lì restano utili librerie come lodash.cloneDeep, pensate apposta per quel caso.

Quando serve ancora una libreria

Per il caso comune — copiare uno stato, un oggetto di configurazione, dati arrivati da un’API prima di modificarli — structuredClone() è la scelta giusta: nativo, corretto sui tipi che JSON rompe, senza dipendenze. Se invece nell’oggetto ci sono istanze di classi di cui contano i metodi, o funzioni da preservare, va usata una libreria dedicata: non è un problema che una copia strutturale possa risolvere.