Skip to content

Commit 6d4ea13

Browse files
committed
Merge branch 'billneff79-Issue-2-DefaultWhenNotFound'
2 parents 8861035 + 4bf7b04 commit 6d4ea13

File tree

3 files changed

+69
-16
lines changed

3 files changed

+69
-16
lines changed

README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
11
# `dlv(obj, keypath)` [![NPM](https://img.shields.io/npm/v/dlv.svg)](https://npmjs.com/package/dlv) [![Build](https://travis-ci.org/developit/dlv.svg?branch=master)](https://travis-ci.org/developit/dlv)
22

3-
> Safely get a dot-notated path within a nested object.
3+
> Safely get a dot-notated path within a nested object, with ability to return a default if the full key path does not exist or the value is undefined
44
55
### Why?
66

7-
Smallest possible implementation: only **120 bytes.**
7+
Smallest possible implementation: only **165 bytes.**
88

99
You could write this yourself, but then you'd have to write [tests].
1010

11-
Implementation is ripped directly from [preact].
12-
1311
Supports ES Modules, CommonJS and globals.
1412

1513
### Installation
@@ -19,22 +17,45 @@ Supports ES Modules, CommonJS and globals.
1917

2018
### Usage
2119

20+
`delve(object, keypath, [default])`
21+
2222
```js
2323
import delve from 'dlv';
2424

2525
let obj = {
2626
a: {
2727
b: {
2828
c: 1
29+
d: undefined
30+
e: null
2931
}
3032
}
3133
};
3234

35+
//use string dot notation for keys
3336
delve(obj, 'a.b.c') === 1;
3437

38+
//or use an array key
39+
delve(obj, ['a', 'b', 'c']) === 1;
40+
3541
delve(obj, 'a.b') === obj.a.b;
3642

37-
delve(obj, 'a.b.c.d') === undefined;
43+
//returns undefined if the full key path does not exist and no default is specified
44+
delve(obj, 'a.b.c.f') === undefined;
45+
46+
//optional third parameter for default if the full key in path is missing
47+
delve(obj, 'a.b.c.f', 'foo') === 'foo';
48+
49+
//or if the key exists but the value is undefined
50+
delve(obj, 'a.b.c.d', 'foo') === 'foo';
51+
52+
//Non-truthy defined values are still returned if they exist at the full keypath
53+
delve(obj, 'a.b.c.e', 'foo') === null;
54+
55+
//undefined obj or key returns undefined, unless a default is supplied
56+
delve(undefined, 'a.b.c') === undefined;
57+
delve(undefined, 'a.b.c', 'foo') === 'foo';
58+
delve(obj, undefined, 'foo') === 'foo';
3859
```
3960

4061
### License

index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
export default function dlv(obj, key) {
2-
if (key.split) key = key.split('.');
3-
for (var i=0; i<key.length && obj; i++) obj = obj[key[i]];
4-
return obj;
5-
}
1+
export default function dlv(obj, key, def, p) {
2+
p = 0;
3+
key = key.split ? key.split('.') : key;
4+
while (obj && p<key.length) obj = obj[key[p++]];
5+
return obj===undefined ? def : obj;
6+
}

test.js

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ var assert = require('assert');
22
var delve = require('.');
33

44
var obj = {
5+
undef: undefined,
6+
zero: 0,
57
one: 1,
8+
n: null,
69
a: {
710
two: 2,
811
b: {
@@ -15,15 +18,22 @@ var obj = {
1518
};
1619

1720
// assert equality of a given path, as dot notation and array.
18-
function check(path, value) {
19-
assert.equal(delve(obj, path), value);
20-
console.log(' ✓ delve(obj, "'+path+'")');
21+
//optional third argument is for default when object is not found
22+
function check(path, value, def) {
2123

22-
var arr = path.split('.');
23-
assert.equal(delve(obj, arr), value);
24-
console.log(' ✓ delve(obj, '+JSON.stringify(arr)+')');
24+
var out = delve(obj, path, def);
25+
assert.strictEqual(out, value, 'delve(obj, "'+path+'") should be '+value+', got '+out);
26+
console.log(' ✓ delve(obj, "'+path+'"'+ (def ? ', "'+def+'"' : '') + ')');
27+
28+
if (path) {
29+
var arr = path.split('.');
30+
assert.strictEqual(delve(obj, arr, def), value);
31+
console.log(' ✓ delve(obj, ' + JSON.stringify(arr) + (def ? ', "'+def+'"' : '') + ')');
32+
console.log(' ✓ delve(obj, '+JSON.stringify(arr)+')');
33+
}
2534
}
2635

36+
console.log("> No Defaults");
2737
check('', undefined);
2838
check('one', obj.one);
2939
check('one.two', undefined);
@@ -34,5 +44,26 @@ check('a.b.three', obj.a.b.three);
3444
check('a.b.c', obj.a.b.c);
3545
check('a.b.c.four', obj.a.b.c.four);
3646

47+
//test defaults
48+
console.log("\n> With Defaults");
49+
check('', 'foo', 'foo');
50+
check('undef', 'foo', 'foo');
51+
check('n', null, 'foo');
52+
check('zero', 0, 'foo');
53+
check('a.badkey', 'foo', 'foo');
54+
check('a.badkey.anotherbadkey', 'foo', 'foo');
55+
56+
//check undefined key throws an error
57+
assert.throws(delve.bind(this, obj, undefined));
58+
assert.throws(delve.bind(this, obj, undefined, 'foo'));
59+
60+
//check undefined obj doesn't throw errors and uses default
61+
var backupObj = obj;
62+
obj = undefined;
63+
check('one', undefined);
64+
check('one', 'foo', 'foo');
65+
obj = backupObj;
66+
67+
3768
console.log('✅ Success!');
3869
process.exit(0);

0 commit comments

Comments
 (0)