deep-key v0.9.9
deep-key
"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-keyFunctions
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 membervalue: value of member that is pointed bydeepkeyenumerable: 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']);
// trueLicense
MIT license.
(C) 2016-2017 Retorillo