What is the most efficient way to deep clone an object in JavaScript? Ask Question

What is the most efficient way to deep clone an object in JavaScript? Ask Question

What is the most efficient way to clone a JavaScript object? I've seen obj = eval(uneval(o)); being used, but that's non-standard and only supported by Firefox.

I've done things like obj = JSON.parse(JSON.stringify(o)); but question the efficiency.

I've also seen recursive copying functions with various flaws.
I'm surprised no canonical solution exists.

ベストアンサー1

Native deep cloning

There's now a structuredClone(value) function supported in all major browsers and node >= 17. It has polyfills for older systems.

structuredClone(value)

If needed, loading the polyfill first:

import structuredClone from '@ungap/structured-clone';

See this answer for more details, but note these limitations:

  • Function objects cannot be duplicated by the structured clone algorithm; attempting to throws a DataCloneError exception.
  • Cloning DOM nodes likewise throws a DataCloneError exception.
  • Certain object properties are not preserved:
    • The lastIndex property of RegExp objects is not preserved.
    • Property descriptors, setters, getters, and similar metadata-like features are not duplicated. For example, if an object is marked readonly with a property descriptor, it will be read/write in the duplicate, since that's the default.
    • The prototype chain is not walked or duplicated.

Older answers

Fast cloning with data loss - JSON.parse/stringify

If you do not use Dates, functions, undefined, Infinity, RegExps, Maps, Sets, Blobs, FileLists, ImageDatas, sparse Arrays, Typed Arrays or other complex types within your object, a very simple one liner to deep clone an object is:

JSON.parse(JSON.stringify(object))

const a = {
  string: 'string',
  number: 123,
  bool: false,
  nul: null,
  date: new Date(),  // stringified
  undef: undefined,  // lost
  inf: Infinity,  // forced to 'null'
  re: /.*/,  // lost
}
console.log(a);
console.log(typeof a.date);  // Date object
const clone = JSON.parse(JSON.stringify(a));
console.log(clone);
console.log(typeof clone.date);  // result of .toISOString()

See Corban's answer for benchmarks.

Reliable cloning using a library

Since cloning objects is not trivial (complex types, circular references, function etc.), most major libraries provide function to clone objects. Don't reinvent the wheel - if you're already using a library, check if it has an object cloning function. For example,

  • lodash - cloneDeep; can be imported separately via the lodash.clonedeep module and is probably your best choice if you're not already using a library that provides a deep cloning function
  • Ramda - clone
  • AngularJS - angular.copy
  • jQuery - jQuery.extend(true, { }, oldObject); .clone() only clones DOM elements
  • just library - just-clone; Part of a library of zero-dependency npm modules that do just do one thing. Guilt-free utilities for every occasion.

おすすめ記事