structuredClone with Functions and DOM Nodes

The native JavaScript structuredClone() method creates deep copies of complex data structures, but it has strict limitations regarding non-serializable objects. When either functions or DOM nodes are passed into structuredClone(), the method immediately throws a DataCloneError DOMException. This article explains why the structured clone algorithm rejects these values and outlines the proper alternatives for cloning them.

Passing Functions to structuredClone

JavaScript functions cannot be duplicated by structuredClone(). If you pass a standalone function or an object containing a function property into structuredClone(), execution halts with an error:

// Throws: DOMException: function could not be cloned
structuredClone(() => console.log("hello"));

// Throws: DOMException: function could not be cloned
structuredClone({ name: "Alice", greet: function() {} });

Why It Fails

Functions encapsulate executable code, hidden scopes, closures, and internal execution contexts. These characteristics cannot be safely serialized, transferred, or reconstructed in memory across different environments or threads.

Workarounds for Functions

To clone an object that contains methods: 1. Separate Data from Behavior: Keep data in plain objects and define methods on a shared prototype, class, or module. 2. Manual Copying: Copy the data fields with structuredClone() and reassign the necessary functions afterward: javascript const original = { data: [1, 2, 3], run() { return true; } }; const copy = { ...structuredClone({ data: original.data }), run: original.run };

Passing DOM Nodes to structuredClone

Passing any DOM node—such as an HTMLElement, Document, or TextNode—to structuredClone() also triggers a DataCloneError:

const button = document.createElement("button");

// Throws: DOMException: HTMLButtonElement could not be cloned
structuredClone(button);

Why It Fails

DOM nodes are live references tied to the browser’s rendering engine and the active document tree. They carry event listeners, internal platform pointers, and contextual state that cannot be represented as serializable data within the structured clone algorithm.

Workarounds for DOM Nodes

To duplicate DOM elements, use the dedicated DOM API method Node.cloneNode() instead:

const originalElement = document.querySelector("#my-element");

// Create a deep copy of the DOM element and its children
const clonedElement = originalElement.cloneNode(true);

Note that cloneNode() duplicates the element’s attributes and inline HTML structure, but it does not copy event listeners added via addEventListener(). Those must be attached to the new node manually.