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

deep-key

v0.9.9

Published

Similar to key of object (Object.keys) but deep key. Provides recursive access to object member.

Downloads

4

Readme

deep-key

Build Status Coverage Status Dependency Status NPM MIT

"Deep Key" is single dimentional array of keys that represents full path of object member. Similar to key of object (Object.keys) but "deep" key. Provides recursive access to object member.

const DeepKey = require('deep-key');
var obj = { p1: { p2: { p3: { p4: 0 } } } };
DeepKey.keys(obj);
// [ ['p1'], ['p1', 'p2'], ['p1', 'p2', 'p3'] ... ]

Install

npm install --save deep-key

Functions

keys

Get all deep keys recursively. Many options are available. See Options.

DeepKey.keys(obj);
DeepKey.keys(obj, option);

get

Get value of object member that is pointed by deep key.

DeepKey.get(obj, deepkey);

set

Set value for object member that is pointed by deep key.

DeepKey.set(obj, deepkey, value);

Whether such a member exits or not, member is always overwritten or created. To prevent this, use exists to check its existence.

touch

Create object member that is pointed by deep key if does not exist. Similar to set method, but value never be changed if member already exist.

For initial value of new member, third argument value is used if present, otherwise undefined is used.

DeepKey.touch(obj, deepkey);
DeepKey.touch(obj, deepkey, value);

Returns value of object member.

type

Get type of object member that is pointed by deep key. If member does not exist, return "undefined". Note that typeof(null) returns "object".

DeepKey.type(obj, deepkey);
// equivalent with
// typeof(DeepKey.get(obj, deepkey))

accessor

Get accessor of object member that is pointed by deep key. Accessor has get and set methods.

DeepKey.accessor(obj, deepkey);

Caching accessor may be able to reduce computing cost that relates with object tree traversing.

If there are no member that is pointed by deep key, member is automatically created. (Initial value is undefined).

delete

Remove object member that is pointed by deep key. Equivalent to using delete keyword.

DeepKey.delete(obj, deepkey);

Returns value of object member that is pointed by deep key.

rename

Rename key of object member by using current and new deep keys.

DeepKey.rename(obj, src, dest);

If member that is pointed by src does not exist, undefined is set for one of dest. And, whether one of dest already exists or not, it will be overwritten by one of src. To prevent those, use exists to check their existence.

Returns value of object member that is pointed by deep key.

exists

Check existence of object member that is pointed by deep key.

DeepKey.exists(obj, deepkey);

Options

The following options are available for keys().

all

all option allows to get all member enumeration including unenumerable members.

var obj = { enum: 'e', };
Object.defineProperty(obj, 'unenum', { value: 'u' });
obj.propertyIsEnumerable('unenum');
// false
DeepKeys.keys(obj);
// [ ['enum'] ]
DeepKeys.keys(obj, { all: true });
// [ ['enum'], ['unenum'] ]

depth

depth option allows to limit enumeration by depth.

var obj = { prop1: { prop2: { prop3: { } } } }
console.log(DeepKey.keys(obj, { depth: 2 }));
// [ ['prop1'], ['prop1', 'prop2'] ]

If merely want to specify depth option, can directly pass into second argument in place of option.

DeepKey.keys(obj, depth);

Note that all keys will be enumerated if zero or negative value is specified for depth.

filter

filter option allows to limit enumeration by your custom function.

var obj = {
  prop1: { prop2: {} }
  prop3: { skip1: {} },
  prop4: 'p4',
  skip2: 'e2'
}

console.log(DeepKey.keys(obj, {
  filter: (deepkey, value) => {
    return !/skip\d+/.test(deepkey.join('.'));
  }
});
// [ ['prop1'], ['prop1', 'prop2'], ['prop3'], ['prop4'] ]

For each member, filter function is called back by passing the following three arguments:

  • deepkey : deep key of member
  • value : value of member that is pointed by deepkey
  • enumerable : whether member is enumerable (propertyIsEnumerable)

filter function must return true in order to include in enumeration, false otherwise.

If merely want to specify filter option, can directly pass into second argument in place of option.

DeepKey.keys(obj, filter);

noindex

noindex option allows to suppress index-enumeration of Array.

In JavaScript world, Array is also object-type and its indexes are keys of object.

An Array object is an exotic object that gives special treatment to array index property keys (ES6 9.4.2)

Try the following code:

typeof [];
// 'object'
Object.keys(['one', 'two', 'three']);
// [ '0', '1', '2' ]

Therefore, keys of this package also enumerate keys of Array by default. In most case, this behavior is an undesirable overboundance. noindex option can suppress this.

NOTE: Array is also extensible. Note that its extended member will be always enumerated, regardless of noindex option.

var obj = { array: [1,2,3], val: 4 };
obj.array.five = 5;
DeepKey.keys(obj, { noindex: true });
// [ ['array'], ['array', 'five'], ['val'] ]

leaf

leaf option allows to enumerate only "leafs" that have no descendant keys:

DeepKeys.keys({a: {b: {c: 'd'}}}, {leaf: true});
// [ ['a', 'b', 'c', 'd'] ]

When Array members are present, noindex is recommended in most cases.

DeepKeys.keys({a: ['b', 'c']}, {leaf: true});
// [ ['a', '0'], ['a', '1'] ]
// In most cases, maybe indexes are not expected "leafs".

DeepKeys.keys({a: ['b', 'c']}, {leaf: true, noindex: true});
// [ ['a'] ]

Finally, the behavior both leaf and depth options are specified is cautionable. It will return pseudo-leafs under the restriction of specified depth, therefore returned members might have descendant keys if no depth option. When want to filter "exact" leafs that have no descendant keys, try the following code:

// Filter leaf that depth is 3
DeepKey.keys(obj, { leaf: true }).filter(key => key.length <= 3);

Handling inextensible object

Whether specified member is present or not, DeepKey automatically overwrite or create member recursively, therefore exception handing is not required in most cases.

But, there are an exception that is thrown in special case.

On object tree traversing, if intermediate inextensible object is found (null, number, string, seald object, and so on), an error /^Inextensible object:/ be thrown. Because such an inextensible object cannot have new extended members.

var obj = { prop1: { prop2: 1 } };

DeepKey.set(obj, [ 'prop1', 'prop2' ], 2);
// Of course, success

DeepKey.set(obj, [ 'prop1', 'prop2', 'prop3' ], 3);
// 'Inextensible object: prop1.prop2' is thrown.
// Because value 2 of prop1.prop2 is inextensible.

NOTE: Members of exsisting intermediate sealed object can be readable and writable because "seal" does not prevent to change value of its member.

var obj = { { sealed: { present: false } } };
Object.seal(obj.sealed);
DeepKey.set(obj, ['sealed', 'present'], true);
DeepKey.get(obj, ['sealed', 'present']);
// true

License

MIT license.

(C) 2016-2017 Retorillo