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
Since 1.8.5 it's possible to seal and freeze the object, so define the above as:
const DaysEnum = Object.freeze({"monday":1, "tuesday":2, "wednesday":3, ...})
or
const DaysEnum = {"monday":1, "tuesday":2, "wednesday":3, ...}
Object.freeze(DaysEnum)
and voila! JS enums.
However, this doesn't prevent you from assigning an undesired value to a variable, which is often the main goal of enums:
let day = DaysEnum.tuesday
day = 298832342 // goes through without any errors
One way to ensure a stronger degree of type safety (with enums or otherwise) is to use a tool like TypeScript or Flow.
Quotes aren't needed but I kept them for consistency.
Best Answer
Since nobody has broached the subject of why these are useful:
I use bitwise operations a lot when working with flags. For example, if you want to pass a series of flags to an operation (say,
File.Open()
, with Read mode and Write mode both enabled), you could pass them as a single value. This is accomplished by assigning each possible flag it's own bit in a bitset (byte, short, int, or long). For example:So if you want to pass read AND write, you would pass (READ | WRITE) which then combines the two into
Which then can be decrypted on the other end like:
which checks
which returns
which is not 0, so the flag does specify READ.
You can use XOR to toggle various bits. I've used this when using a flag to specify directional inputs (Up, Down, Left, Right). For example, if a sprite is moving horizontally, and I want it to turn around:
I simply XOR the current value with (LEFT | RIGHT) which will turn LEFT off and RIGHT on, in this case.
Bit Shifting is useful in several cases.
is the same as
if you need to quickly multiply by a power of two, but watch out for shifting a 1-bit into the top bit - this makes the number negative unless it's unsigned. It's also useful when dealing with different sizes of data. For example, reading an integer from four bytes:
Assuming that A is the most-significant byte and D the least. It would end up as:
Colors are often stored this way (with the most significant byte either ignored or used as Alpha):
To find the values again, just shift the bits to the right until it's at the bottom, then mask off the remaining higher-order bits:
0xFF
is the same as11111111
. So essentially, for Red, you would be doing this: