qhash
v1.3.0
Published
merge and deep-copy objects, get/set properties by dotted name, taint detect
Downloads
130
Maintainers
Readme
qhash
Hash and object manipulation
Functions to get/set properties by dotted name, deep-copy, merge, taint detect.
qhash Api
const qhash = require('qhash');
qhash.merge( [target,] source [,noOverwrite] )
Deep copy all enumerable properties of the source
hash into the target
hash. No sub-hash
contained in source is reused on target, each is copied recursively. If target
is not specified, the this
object is used. If noOverwrite
is set, existing
properties of target
are not modified. Returns target
.
Hashes are javascript objects that are not instanceof any class (ie, whose
constructor is the same as the constructor of {}
, Object
). Non-hash objects
are assumed to be class instances and are assigned directly; if their properties
are modified in target
, they will also change in source
.
var dst = { };
var src = { a: {b:2}, d: new Date() };
qhash.merge(dst, src);
dst.a // => {b:2}, hash copied
dst.a === src.a; // => false, copied into new hash
assert.deepEqual(dst.a, src.a); // => true, hash contents match
dst.d === src.d; // => true, same Date instance
dst.d.x = 1;
src.d.x === 1; // => true, same Date modified
qhash.mmerge( target, source1 [,source2] [,source3 ...] [,noOverwrite] )
Merge multiple: recursively deep copy all properties from all sources onto target
by repeatedly calling qhash.merge
. Target
must be specified, there is no default.
It is safe to layer multiple read-only hashes, no sub-hash from any source is used
directly. Returns target
.
If noOverwrite
is set it retains the first seen version of each set property (from
the lowest-numered source object), else retains the last seen version.
qhash.get( [source,] name )
Retrieve a property set on the source
hash by dotted name. Returns the property
value. Returns undefined
if the named property or one of its internal hashes is
not set.
qhash.get({ a: {b: 2} }, 'a'); // => {b: 2}
qhash.get({ a: {b: 2} }, 'a.b'); // => 2
qhash.get({ a: {b: 2} }, 'b'); // => undefined
qhash.get({ a: {} }, 'a.b.c'); // => undefined
qhash.set( [target,] name, value )
Set a property on the target
hash by dotted name. Any missing internal hashes
are created as necessary. Returns the value
.
It is possible to set a property to undefined
, making it appear to be unset.
var x;
qhash.set(x = {}, 'a', 1); // x => { a: 1 }
qhash.set(x = {}, 'a.a.a', 1); // x => { a: {a: {a: 1}} }
qhash.set(x = {c:3}, 'a.b', 1); // x => { c: 3, a: {b: 1} }
qhash.selectField( arrayOfHashes, columnName )
Retrieve the named property from every hash in the array. Returns an array of
values in the same order as the hashes, with undefined
for any unset property.
var dataset = [{a:1}, {a:2}, {c:3}];
qhash.selectField(dataset, 'a'); // => [1, 2, undefined]
var dataset = [{a:{b:11}}, {a:{b:22}}];
qhash.selectField(dataset, 'a.b'); // => [11, 22]
qhash.mapById( arrayOfObjects, idName [,intoHash] )
Map the array of objects by their idName
property into the provided hash intoHash
(or into a new hash {}
), and return the mapping.
var dataset = [ { _id: 'one', a: 1 }, { _id: 'two', b: 2 } ];
var hash = qhash.mapById(dataset, '_id');
// => { one: {_id:'one', a:1}, two: {_id:'two', b:2} }
qhash.decorate( target, methods [,options] )
Attach the given properties to the target object. The methods
argument is a
name-value hash of the property names and property values to attach. This call can
be useful for decorating container objects with hidden get/set/merge methods.
Options:
hide
- make the attached methods non-enumerable. Defaultfalse
.noOverwrite
- do not overwrite existing properties. Defaultfalse
.
E.g.,
var qhash = require('qhash');
var hash = { a: 0 };
qhash.decorate(hash, {set: qhash.set, get: qhash.get}, {hide: true});
hash.set === qhash.set; // => true
hash.set('a', 123);
hash.a === 123; // => true
hash.get('a'); // => 123
Object.keys(hash); // => [ 'a' ]
JSON.stringify(hash); // => '{"a":123}'
qhash.optimize( obj )
Convert obj
to a struct for optimized property access.
Node objects can be hashes or structs. A hash is tuned for unpredictable property names; a struct for a fixed set of properties in mapped locations. The difference between hash and struct is invisible, but it is faster to access the properties of a struct.
Node internally will also detect usage and eventually convert: repeatedly accessing the same properties on a hash will optimize it into a struct, and adding new properties to a struct will convert it into a hash.
var obj = new Object(); // once a hash
obj.a = 1;
obj.b = 2;
qhash.optimize(obj); // now a struct
qdiff Api
const qdiff = require('qhash/qdiff');
qdiff.backup( item )
Compute a backup object that captures all details of item
. Any modifications made
to item or any of its properties (ie objects reachable from the item), including
property or object attributes, will be reflected in a subsequent backup.
qdiff.compare( backup1, backup2, [options] )
Compare the two backups and return true
if they are the same, false
if they are not.
This comparison detects added/deleted/changed contents and properties, as well as
changes to property attributes (writable, enumerable, configurable) or state (sealed,
frozen, extensible).
Options:
name
- the top-level object name to use, else the default is'x'
skip
- object whose properties are names of properties to not compare. The names are in hierchical dotted names format, eg{ skip: { 'x.a.b': 1 } }
meaning ignore differences in property a.b of{ a: { b: 1 } }
and{ a: { b: 2 } }
.
Change Log
- 1.3.0 -
qdiff.backup
andqdiff.compare
functions - 1.2.0 -
mmerge
,mapById
functions - 1.1.0 -
optimize
call to convert hash to struct - 1.0.2 - fix null deref in test
- 1.0.1 - faster get/set for longer property names
- 1.0.0 - initial fixed version, 2017-03-27
Related Work
util._extend(to, fm)
- shallow copy (in reverse order!) ofown
properties, 8.4m/sObject.assign(to, fm)
- shallow copy (in order) ofown
properties, 3.3m/sObject.create(ob)
- new object with its inherited properties set to the copied object, 17m/sfor (key in ob)
- iterate over all enumerable properties, 16m/s copy but only 1m/s if ob has non-empty prototypeObject.keys(ob)
- list of enumerableown
properties, 13m/s for just keys, 8.8m/s copy