npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

qhash

v1.3.0

Published

merge and deep-copy objects, get/set properties by dotted name, taint detect

Downloads

130

Readme

qhash

Build Status Coverage Status

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. Default false.
  • noOverwrite - do not overwrite existing properties. Default false.

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 and qdiff.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!) of own properties, 8.4m/s
  • Object.assign(to, fm) - shallow copy (in order) of own properties, 3.3m/s
  • Object.create(ob) - new object with its inherited properties set to the copied object, 17m/s
  • for (key in ob) - iterate over all enumerable properties, 16m/s copy but only 1m/s if ob has non-empty prototype
  • Object.keys(ob) - list of enumerable own properties, 13m/s for just keys, 8.8m/s copy