Native deep cloning
It's called "structured cloning", works experimentally in Node 11 and later, and hopefully will land in browsers. See this answer for more details.
Fast cloning with data loss - JSON.parse/stringify
If you do not use Date
s, 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
- 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.
ES6 (shallow copy)
For completeness, note that ES6 offers two shallow copy mechanisms: Object.assign()
and the spread syntax.
which copies values of all enumerable own properties from one object to another. For example:
var A1 = {a: "2"};
var A2 = Object.assign({}, A1);
var A3 = {...A1}; // Spread Syntax
Best Answer
Depending on which browsers you have to support, this can be done in a number of ways. The overwhelming majority of browsers in the wild support ECMAScript 5 (ES5), but be warned that many of the examples below use
Object.keys
, which is not available in IE < 9. See the compatibility table.ECMAScript 3+
If you have to support older versions of IE, then this is the option for you:
The nested
if
makes sure that you don't enumerate over properties in the prototype chain of the object (which is the behaviour you almost certainly want). You must userather than
because ECMAScript 5+ allows you to create prototypeless objects with
Object.create(null)
, and these objects will not have thehasOwnProperty
method. Naughty code might also produce objects which override thehasOwnProperty
method.ECMAScript 5+
You can use these methods in any browser that supports ECMAScript 5 and above. These get values from an object and avoid enumerating over the prototype chain. Where
obj
is your object:If you want something a little more compact or you want to be careful with functions in loops, then
Array.prototype.forEach
is your friend:The next method builds an array containing the values of an object. This is convenient for looping over.
If you want to make those using
Object.keys
safe againstnull
(asfor-in
is), then you can doObject.keys(obj || {})...
.Object.keys
returns enumerable properties. For iterating over simple objects, this is usually sufficient. If you have something with non-enumerable properties that you need to work with, you may useObject.getOwnPropertyNames
in place ofObject.keys
.ECMAScript 2015+ (A.K.A. ES6)
Arrays are easier to iterate with ECMAScript 2015. You can use this to your advantage when working with values one-by–one in a loop:
Using ECMAScript 2015 fat-arrow functions, mapping the object to an array of values becomes a one-liner:
ECMAScript 2015 introduces
Symbol
, instances of which may be used as property names. To get the symbols of an object to enumerate over, useObject.getOwnPropertySymbols
(this function is whySymbol
can't be used to make private properties). The newReflect
API from ECMAScript 2015 providesReflect.ownKeys
, which returns a list of property names (including non-enumerable ones) and symbols.Array comprehensions (do not attempt to use)
Array comprehensions were removed from ECMAScript 6 before publication. Prior to their removal, a solution would have looked like:
ECMAScript 2017+
ECMAScript 2016 adds features which do not impact this subject. The ECMAScript 2017 specification adds
Object.values
andObject.entries
. Both return arrays (which will be surprising to some given the analogy withArray.entries
).Object.values
can be used as is or with afor-of
loop.If you want to use both the key and the value, then
Object.entries
is for you. It produces an array filled with[key, value]
pairs. You can use this as is, or (note also the ECMAScript 2015 destructuring assignment) in afor-of
loop:Object.values
shimFinally, as noted in the comments and by teh_senaus in another answer, it may be worth using one of these as a shim. Don't worry, the following does not change the prototype, it just adds a method to
Object
(which is much less dangerous). Using fat-arrow functions, this can be done in one line too:which you can now use like
If you want to avoid shimming when a native
Object.values
exists, then you can do:Finally...
Be aware of the browsers/versions you need to support. The above are correct where the methods or language features are implemented. For example, support for ECMAScript 2015 was switched off by default in V8 until recently, which powered browsers such as Chrome. Features from ECMAScript 2015 should be be avoided until the browsers you intend to support implement the features that you need. If you use babel to compile your code to ECMAScript 5, then you have access to all the features in this answer.