structuredClone()

structuredClone(value)
Returns: Deep copy of input value · Added in vES2021 · Updated March 17, 2026 · Global Functions
javascript clone deep-copy global structured-clone

The structuredClone() function creates a deep copy of a JavaScript value using the structured clone algorithm. Unlike JSON.parse(JSON.stringify()), it handles complex data types including Maps, Sets, Dates, RegExps, and circular references.

Syntax

structuredClone(value)
structuredClone(value, options)

Parameters

ParameterTypeDescription
valueanyThe object to be cloned. Can be any structured-cloneable type.
optionsobjectOptional. An object with a transfer property containing an array of transferable objects.

Transfer Options

The transfer option moves (rather than clones) specified transferable objects, making the original unusable. This enables zero-copy data transfer between contexts like web workers or IndexedDB:

const buffer = new ArrayBuffer(16);
const cloned = structuredClone({ buffer }, { transfer: [buffer] });
// buffer.byteLength is now 0

Transferable objects include ArrayBuffer, TypedArray, MessagePort, and ImageBitmap.

Return Value

A deep copy of the original value. If the value contains circular references, they are preserved in the clone.

Examples

Basic Clone

const original = {
  name: "Alice",
  data: [1, 2, 3],
  metadata: new Map([["key", "value"]])
};

const clone = structuredClone(original);
clone.name = "Bob";
clone.data.push(4);

console.log(original.name); // "Alice"
console.log(clone.name);    // "Bob"
console.log(original.data); // [1, 2, 3]
console.log(clone.data);    // [1, 2, 3, 4]

Cloning with Circular References

const original = { name: "circular" };
original.self = original;

const clone = structuredClone(original);
console.log(clone.name);      // "circular"
console.log(clone.self === clone); // true

Transferring ArrayBuffers

const uInt8Array = new Uint8Array([1, 2, 3]);
const transferred = structuredClone(uInt8Array, {
  transfer: [uInt8Array.buffer]
});

console.log(uInt8Array.byteLength); // 0
console.log(transferred);            // Uint8Array [1, 2, 3]

Error Handling

structuredClone() throws a DataCloneError when it encounters unclonable data:

const obj = { fn: () => {} };

try {
  structuredClone(obj);
} catch (e) {
  console.log(e.name);    // "DataCloneError"
  console.log(e.message); // "...could not be cloned."
}

Limitations

structuredClone() cannot clone:

  • Functions — throws DataCloneError
  • DOM nodes — throws DataCloneError
  • Property descriptors, setters, and getters — metadata is lost
  • RegExp.lastIndex — the property is not preserved
  • Class private fields
  • Prototype chain — only own enumerable properties are copied
  • WeakMap and WeakSet — throws DataCloneError

Symbol Behavior

  • Primitive Symbol values cannot be cloned (throws DataCloneError)
  • Symbol keys in objects are preserved as property keys
const sym = Symbol("test");
const obj = { [sym]: "value", regularKey: "data" };

const clone = structuredClone(obj);
console.log(Object.getOwnPropertySymbols(clone)); // [Symbol(test)]
console.log(clone[sym]); // "value"

Error Objects

Standard error types (Error, TypeError, RangeError, etc.) are cloned correctly. However, custom Error subclasses lose their constructor name:

class CustomError extends Error {
  constructor(message) {
    super(message);
    this.name = "CustomError";
  }
}

const error = new CustomError("oops");
const cloned = structuredClone(error);
console.log(cloned.name); // "Error" — name is forced to "Error"

See Also