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
It used to be a required part of a package (old, pre-3.3 "regular package", not newer 3.3+ "namespace package").
Here's the documentation.
Python defines two types of packages, regular packages and namespace packages. Regular packages are traditional packages as they existed in Python 3.2 and earlier. A regular package is typically implemented as a directory containing an __init__.py
file. When a regular package is imported, this __init__.py
file is implicitly executed, and the objects it defines are bound to names in the package’s namespace. The __init__.py
file can contain the same Python code that any other module can contain, and Python will add some additional attributes to the module when it is imported.
But just click the link, it contains an example, more information, and an explanation of namespace packages, the kind of packages without __init__.py
.
Best Answer
First I want to note that Hot Module Replacement (HMR) is still an experimental feature.
HMR is a way of exchanging modules in a running application (and adding/removing modules). You basically can update changed modules without a full page reload.
Documentation
Prerequirements:
It's not so much for HMR, but here are the links:
I'll add these answers to the documentation.
How does it work?
From the app view
The app code asks the HMR runtime to check for updates. The HMR runtime downloads the updates (async) and tells the app code that an update is available. The app code asks the HMR runtime to apply updates. The HMR runtime applies the updates (sync). The app code may or may not require user interaction in this process (you decide).
From the compiler (webpack) view
In addition to the normal assets, the compiler needs to emit the "Update" to allow updating from a previous version to this version. The "Update" contains two parts:
The manifest contains the new compilation hash and a list of all update chunks (2).
The update chunks contain code for all updated modules in this chunk (or a flag if a module was removed).
The compiler additionally makes sure that module and chunk ids are consistent between these builds. It uses a "records" json file to store them between builds (or it stores them in memory).
From the module view
HMR is a opt-in feature, so it only affects modules that contains HMR code. The documentation describes the API that is available in modules. In general, the module developer writes handlers that are called when a dependency of this module is updated. They can also write a handler that is called when this module is updated.
In most cases, it's not mandatory to write HMR code in every module. If a module has no HMR handlers, the update bubbles up. This means a single handler can handle updates for a complete module tree. If a single module in this tree is updated, the complete module tree is reloaded (only reloaded, not transferred).
From the HMR runtime view (technical)
Additional code is emitted for the module system runtime to track module
parents
andchildren
.On the management side, the runtime supports two methods:
check
andapply
.A
check
does a HTTP request to the update manifest. When this request fails, there is no update available. Elsewise the list of updated chunks is compared to the list of currently-loaded chunks. For each loaded chunk, the corresponding update chunk is downloaded. All module updates are stored in the runtime as updates. The runtime switches into theready
state, meaning an update has been downloaded and is ready to be applied.For each new chunk request in the ready state, the update chunk is also downloaded.
The
apply
method flags all updated modules as invalid. For each invalid module, there needs to be a update handler in the module or update handlers in every parent. Else the invalid bubbles up and marks all parents as invalid too. This process continues until no more "bubble up" occurs. If it bubbles up to an entry point, the process fails.Now all invalid modules are disposed (dispose handler) and unloaded. Then the current hash is updated and all "accept" handlers are called. The runtime switches back to the
idle
state and everything continues as normal.What can I do with it?
You can use it in development as a LiveReload replacement. Actually the webpack-dev-server supports a hot mode which tries to update with HMR before trying to reload the whole page. You only need to add the
webpack/hot/dev-server
entry point and call the dev-server with--hot
.You can also use it in production as update mechanisms. Here you need to write your own management code that integrates HMR with your app.
Some loaders already generate modules that are hot-updateable. e.g. The
style-loader
can exchange the stylesheet. You don't need to do anything special.Yes
Here is a little example: https://webpack.js.org/guides/hot-module-replacement/
A module can only be updated if you "accept" it. So you need to
module.hot.accept
the module in the parents or the parents of the parents... e.g. A Router is a good place, or a subview.If you only want to use it with the webpack-dev-server, just add
webpack/hot/dev-server
as entry point. Else you need some HMR management code that callscheck
andapply
.Opinion: What makes it so cool?
if(module.hot)
).Caveats
records
).