planttheidea / fast-copy
- среда, 23 мая 2018 г. в 00:17:29
JavaScript
A blazing fast deep object copier
A blazing fast deep object copier
import copy from "fast-copy";
import { deepEqual } from "fast-equals";
const object = {
array: [123, { deep: "value" }],
map: new Map([["foo", {}], [{ bar: "baz" }, "quz"]])
};
const copiedObject = copy(object);
console.log(copiedObject === object); // false
console.log(deepEqual(copiedObject, object)); // trueUnder the hood, fast-copy uses instanceof to determine object types, which can cause false negatives when used in combination with iframe-based objects. To handle this edge case, you can pass the optional second parameter of realm to the copy method, which identifies which realm the object comes from and will use that realm to drive both comparisons and constructors for the copies.
<iframe srcdoc="<script>var arr = ['foo', 'bar'];</script>"></iframe>const iframe = document.querySelector("iframe");
const arr = iframe.contentWindow.arr;
console.log(copy(arr, iframe.contentWindow)); // ['foo', 'bar']The following object types are deeply cloned when they are either properties on the object passed, or the object itself:
ArrayArrayBufferBufferDataViewDateFloat32ArrayFloat64ArrayInt8ArrayInt16ArrayInt32ArrayMapObjectRegExpSetUint8ArrayUint8ClampedArrayUint16ArrayUint32ArrayReact componentsThe following object types are copied directly, as they are either primitives, cannot be cloned, or the common use-case implementation does not expect cloning:
AsyncFunctionBooleanErrorFunctionGeneratorFunctionNumberNullPromiseStringSymbolUndefinedWeakMapWeakSetCircular objects are supported out of the box as well. By default a cache based on WeakSet is used, but if WeakSet is not available then a standard Object fallback is used. The benchmarks quoted below are based on use of WeakSet.
Small number of properties, all values are primitives
| Operations / second | Relative margin of error | |
|---|---|---|
| fast-copy | 1,725,552 | 0.89% |
| clone | 1,114,295 | 0.82% |
| lodash.cloneDeep | 904,031 | 0.51% |
| fast-deepclone | 716,908 | 0.87% |
| fast-clone | 497,748 | 0.88% |
| deepclone | 420,962 | 0.59% |
Large number of properties, values are a combination of primitives and complex objects
| Operations / second | Relative margin of error | |
|---|---|---|
| fast-copy | 113,553 | 0.76% |
| fast-deepclone | 101,356 | 0.76% |
| deepclone | 54,401 | 0.80% |
| clone | 51,183 | 0.79% |
| fast-clone | 46,165 | 0.66% |
| lodash.cloneDeep | 39,395 | 0.78% |
Objects that deeply reference themselves
| Operations / second | Relative margin of error | |
|---|---|---|
| fast-copy | 1,011,337 | 0.80% |
| clone | 644,481 | 0.67% |
| lodash.cloneDeep | 577,534 | 0.48% |
| fast-deepclone | 359,288 | 0.79% |
| deepclone | 371,971 | 0.55% |
| fast-clone (not supported) | 0 | 0.00% |
Custom constructors, React components, etc
| Operations / second | Relative margin of error | |
|---|---|---|
| fast-copy | 56,013 | 0.97% |
| clone | 42,107 | 0.87% |
| lodash.cloneDeep | 36,113 | 0.74% |
| fast-deepclone | 25,278 | 1.45% |
| fast-clone | 21,450 | 0.86% |
| deepclone | 12,768 | 0.77% |
Standard practice, clone the repo and npm i to get the dependencies. The following npm scripts are available:
rollupclean:dist, clean:es, and clean:lib scriptsrimraf on the dist folderrimraf on the es folderrimraf on the lib folderbuild and build:minified scriptssrc folder (also runs on dev script)lint script, but with auto-fixerlint, test:coverage, transpile:lib, transpile:es, and dist scriptsdevtest foldertest with code coverage calculation via nyctest but keep persistent watchersrc folder (transpiled to es folder without transpilation of ES2015 export syntax)src folder (transpiled to lib folder)