Skip to Content
Course content

250: The structuredClone Global Function

Click on the "Edit" button in the top corner of the screen to edit your slide content.

Why can't I just use the spread operator for this?

You've probably used ... to copy an object or array a thousand times. It's fast and clean, but there's a catch: it only does a "shallow" copy. If your object has another object or array nested inside it, the spread operator just copies the reference to that nested object, not the actual data.

I've seen so many bugs where a developer thinks they've cloned a state object, but they accidentally mutate the original because they changed a nested property. Look at this:

const user = {
  name: 'Alex',
  settings: { theme: 'dark', notifications: true }
};

const shallowCopy = { ...user };
shallowCopy.settings.theme = 'light';

console.log(user.settings.theme); // 'light' - Oops! The original changed too.

This is where structuredClone() saves you. It performs a "deep" copy, meaning it recursively clones every single level of the object. If you use structuredClone(user) in the example above, changing the theme in the copy won't touch the original.

Is this actually better than the JSON.parse(JSON.stringify()) trick?

For years, the "industry standard" hack for deep cloning was JSON.parse(JSON.stringify(obj)). Honestly, it's fine for simple data, but it's fragile. It completely strips out things that aren't valid JSON, like Map, Set, Date objects, or undefined values.

If you try to use the JSON trick on a Date object, it gets turned into a string. You lose the Date methods. structuredClone handles these natively. It also handles circular references—where an object refers to itself—which would normally cause the JSON method to throw a TypeError and crash your app.

const session = {
  startTime: new Date(),
  tags: new Set(['javascript', 'webdev']),
};

// The old way
const badCopy = JSON.parse(JSON.stringify(session));
console.log(badCopy.startTime); // Now a string, not a Date object!
console.log(badCopy.tags);      // Now an empty object {}, not a Set!

// The right way
const goodCopy = structuredClone(session);
console.log(goodCopy.startTime instanceof Date); // true
console.log(goodCopy.tags instanceof Set);       // true

Can I clone literally any object with this?

Not quite. There are a few things structuredClone refuses to touch. The biggest one is functions. Since functions are executable code and often rely on a specific scope (closures), they can't be "cloned" in a meaningful way. If you try to clone an object containing a function, JavaScript will throw a DataCloneError.

You'll also run into issues with DOM elements. You can't structuredClone(document.body). For those, you're still stuck using element.cloneNode(true).

I usually tell people: use structuredClone for data. If your object is a "class instance" with methods or a complex DOM node, this isn't the tool for the job. But for API responses, configuration objects, and application state? It's a lifesaver.




📋 Practical Task

Exercise: Implementing an Undo Snapshot for a Game State

You are building a simple strategy game. The gameState object contains a playerScore, a startTime (Date object), and a capturedTerritories (Set object). To implement an "Undo" feature, you need to save a snapshot of the current state before the player makes a move.

Your Task:

  • Create a gameState object with: score: 100, startTime: new Date(), and capturedTerritories: new Set(['North', 'South']).
  • Use structuredClone to create a variable called snapshot.
  • Modify the gameState object by increasing the score to 200 and adding 'East' to the capturedTerritories Set.
  • Log both gameState and snapshot to the console to verify that the snapshot remains unchanged while the gameState was updated.
Rating
0 0

There are no comments for now.

to be the first to leave a comment.