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
The difference is that functionOne
is a function expression and so only defined when that line is reached, whereas functionTwo
is a function declaration and is defined as soon as its surrounding function or script is executed (due to hoisting).
For example, a function expression:
// TypeError: functionOne is not a function
functionOne();
var functionOne = function() {
console.log("Hello!");
};
And, a function declaration:
// Outputs: "Hello!"
functionTwo();
function functionTwo() {
console.log("Hello!");
}
Historically, function declarations defined within blocks were handled inconsistently between browsers. Strict mode (introduced in ES5) resolved this by scoping function declarations to their enclosing block.
'use strict';
{ // note this block!
function functionThree() {
console.log("Hello!");
}
}
functionThree(); // ReferenceError
Best Solution
What does
void 0
mean?void
[MDN] is a prefix keyword that takes one argument and always returnsundefined
.Examples
What's the point of that?
It seems pretty useless, doesn't it? If it always returns
undefined
, what's wrong with just usingundefined
itself?In a perfect world we would be able to safely just use
undefined
: it's much simpler and easier to understand thanvoid 0
. But in case you've never noticed before, this isn't a perfect world, especially when it comes to Javascript.The problem with using
undefined
was thatundefined
is not a reserved word (it is actually a property of the global object [wtfjs]). That is,undefined
is a permissible variable name, so you could assign a new value to it at your own caprice.Note: This is no longer a problem in any environment that supports ECMAScript 5 or newer (i.e. in practice everywhere but IE 8), which defines the
undefined
property of the global object as read-only (so it is only possible to shadow the variable in your own local scope). However, this information is still useful for backwards-compatibility purposes.void
, on the other hand, cannot be overidden.void 0
will always returnundefined
.undefined
, on the other hand, can be whatever Mr. Javascript decides he wants it to be.Why
void 0
, specifically?Why should we use
void 0
? What's so special about0
? Couldn't we just as easily use1
, or42
, or1000000
or"Hello, world!"
?And the answer is, yes, we could, and it would work just as well. The only benefit of passing in
0
instead of some other argument is that0
is short and idiomatic.Why is this still relevant?
Although
undefined
can generally be trusted in modern JavaScript environments, there is one trivial advantage ofvoid 0
: it's shorter. The difference is not enough to worry about when writing code but it can add up enough over large code bases that most code minifiers replaceundefined
withvoid 0
to reduce the number of bytes sent to the browser.