1.0.0 • Published 4 years ago

true-clone v1.0.0

Weekly downloads
2
License
ISC
Repository
github
Last release
4 years ago

js-true-clone

The goal of this package is to get as close as possible to a perfect JS value clone.

Usage

npm i true-clone

then

const { clone } = require('true-clone');
// later ...
const cloned = clone(myObject);

Behaviour

The cloning algorithm is pretty smart and is aware of:

  • Native JS types! This includes primitives, Array, Set, Map, boxed primitives, typed arrays, etc.
  • Prototypes! Finally, you can clone custom classes!
  • Getters! These will be replicated on the result as getters, not as the computed value.
  • Setters! These will be replicated on the result.
  • Custom properties on native types! For instance: const ar = []; ar.my = 'prop'; console.assert(clone(ar).my === 'prop').
  • (Non-)enumerability, (non-)configurability, and/or (non-)writability of object properties! These will be respected.
  • etc.

Details

  • Mostly works as one would expect!
  • However, the following may be notable:
  • Prototypes: are referenced rather than copied; Object.is(clone(Object.create(someProto)).prototype, someProto)
  • Proxy objects: do not return other proxies. Additonally, all traps are ignored besides the following:
    • getPrototypeOf: given prototype is assigned to new object
    • ownKeys: these are the keys that will appear on the clone
    • getOwnPropertyDescriptor: is used to define properties on the clone
  • Due to JS limitations, objects of the type Function, WeakSet, and WeakMap will not be cloned and will instead be returned as-is.

Comparison

Suite in tests.js run on different packages using node v14.2.0. See compare.sh.

package \ featureprimitivesnative typesprototypesmonkeypatchingrelationsrich properites
true-clone 1.0.0ssssss
clone 2.1.2sp 1sp 1su
lodash.clonedeep 4.5.0sp 2sp 3p 4u
rfdc 1.1.4sp 5uup 6u

s: all tests passing; u: no tests passing; p: some tests passing

  • primitives: supports primitive values
  • native types: supports certain native types such as Array and Set
  • prototypes: supports objects with prototypes
  • monkeypatching: copies over monkeypatched attributes
    • e.g. const ar = []; ar.my = 'prop'; console.assert(clone(ar).my === 'prop')
  • relations: preserves relational identity, such as in cyclic and diamond-shaped structures
    • cyclic e.g. e.g. const ar = []; ar.push(ar);
    • diamonds e.g. const child = { i_am: 'child' }; const parent = { child_a: child, child_b: child };
  • rich properties: getters and setters etc.
  • 1: fails for Number, String, ArrayBuffer, DataView, errors types, and typed arrays.
  • 2: fails for sparse arrays, BigInt64Array, BigUint64Array, and error types
  • 3: fails for Array, BigInt64Array, BigUint64Array, and error types
  • 4: fails for cyclic Map and Set objects
  • 5: fails for Number, String, Boolean, RegExp, Map, Set, ArrayBuffer, DataView, typed arrays, and error types.
  • 6: fails for diamond shapes and cyclic non-Object values

Benchmarks

true-clone pays for its correctness with speed. Benchmark is run on my personal machine; they should be considered only in relation to each other. See benchmark.js.

package \ scopeprimitivesnative object typesplain objectsarrays
true-clone 1.0.02.300m ops/s343k440k1.219m
clone 2.1.21.823m96k261k263k
lodash.clonedeep 4.5.05.791m219k734k1.988m
rfdc 1.1.432.823m964k2.420m2.346m
  • primitives: primitive objects; test case primitive
  • native object types: Array, Map, Set, and Boolean; test case obj types
  • plain objects: JSON-able object; test case Object :: plain small
  • arrays: small, dense, non-monkeypatched arrays of primitive values; test case Array :: pure hom dense_ small
1.0.0

4 years ago

0.7.12

4 years ago

0.7.10

4 years ago

0.7.9

4 years ago

0.7.8

4 years ago

0.7.6

4 years ago

0.7.5

4 years ago

0.5.11

4 years ago

0.5.12

4 years ago

0.7.1

4 years ago

0.7.4

4 years ago

0.5.10

4 years ago

0.5.4

4 years ago

0.5.5

4 years ago

0.5.2

4 years ago

0.5.1

4 years ago

0.5.0

4 years ago

0.4.0

4 years ago