Skip to content

Instantly share code, notes, and snippets.

@fzn0x
Last active March 23, 2023 00:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fzn0x/e81f26c416fe297d6fd19e28b2fbbad3 to your computer and use it in GitHub Desktop.
Save fzn0x/e81f26c416fe297d6fd19e28b2fbbad3 to your computer and use it in GitHub Desktop.
Asynchronous Structured Clone (Using The Structured Clone Algorithm) for Deep Copying
// postMessage is using the structured clone algorithm
function structuredClone(obj) {
return new Promise(resolve => {
const {port1, port2} = new MessageChannel();
port2.onmessage = ev => resolve(ev.data);
obj.y.x = "Now I can modify cyclic objects without ";
port1.postMessage(obj);
port1.close();
});
}
const x = {};
const y = {x};
x.y = y;
(async () => {
const clone = await structuredClone(x);
console.log(clone);
})();
@fzn0x
Copy link
Author

fzn0x commented Mar 22, 2023

Now you can modify cyclic objects without hassle

@fzn0x
Copy link
Author

fzn0x commented Mar 22, 2023

JSON.parse(JSON.stringify(x));

turns out to be the fastest for deep copying but it does not supports modifying cyclic objects. The alternative is to use MessageChannel postMessage, it's not as fast as the JSON.parse trick but it returns the correct result as it uses the structured clone algorithm that handles cyclic objects and preserve built-in types well.

@fzn0x
Copy link
Author

fzn0x commented Mar 23, 2023

There is also history API which is the winner on performance test ( you can re-test anytime ), but it is limited in some browser like Safari or no support at all.

@fzn0x
Copy link
Author

fzn0x commented Mar 23, 2023

To sum up, refers to these based on the advantages & disadvantages:

  • Performance, synchronous, environment limited: History API
  • Reliability, cross-browsers solution, asynchronous, slow for large arrays: MessageChannel postMessage
  • Fast but not reliable in cyclic objects and preserve built-in types (Maps, Sets, RegExps, Dates, ArrayBuffers and other built-in types functions won't work after serialization), fastest cross-browsers solution: JSON.parse

@fzn0x
Copy link
Author

fzn0x commented Mar 23, 2023

This gist inspired by surma.dev is also the one who's re-initiated the native structuredClone specification, props to him! 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment