Skip to content

Commit

Permalink
feat: support setting values
Browse files Browse the repository at this point in the history
  • Loading branch information
remy committed Apr 13, 2016
1 parent 0dca1f4 commit aab63c2
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 4 deletions.
21 changes: 19 additions & 2 deletions README.md
@@ -1,8 +1,9 @@
undefsafe
=========
# undefsafe

Simple *function* for retrieving deep object properties without getting "Cannot read property 'X' of undefined"

Can also be used to safely set deep values.

## Usage

```js
Expand All @@ -21,3 +22,19 @@ console.log(undefsafe(object, 'a.b.not.found')); // undefined
```

Demo: [https://jsbin.com/eroqame/3/edit?js,console](https://jsbin.com/eroqame/3/edit?js,console)

## Setting

```js
var object = {
a: {
b: [1,2,3]
}
};

// modified object
var res = undefsafe(object, 'a.b.0', 10);

console.log(object); // { a: { b: [10, 2, 3] } }
console.log(res); // 1 - previous value
```
9 changes: 7 additions & 2 deletions lib/undefsafe.js
@@ -1,9 +1,10 @@
'use strict';

function undefsafe(obj, path) {
function undefsafe(obj, path, value) {
var parts = path.split('.');
var key = null;
var type = typeof obj;
var parent = obj;

// we're dealing with a primative
if (type !== 'object' && type !== 'function') {
Expand All @@ -13,6 +14,7 @@ function undefsafe(obj, path) {
}

while ((key = parts.shift())) {
parent = obj;
obj = obj[key];
if (obj === undefined || obj === null) {
break;
Expand All @@ -23,11 +25,14 @@ function undefsafe(obj, path) {
// if it's not (i.e. parts has a length) then give undefined back.
if (obj === null && parts.length !== 0) {
obj = undefined;
} else if (value) {
key = path.split('.').pop();
parent[key] = value;
}

return obj;
}

if (typeof module !== 'undefined') {
module.exports = undefsafe;
}
}
24 changes: 24 additions & 0 deletions test/array.test.js
@@ -0,0 +1,24 @@
'use strict';
var test = require('tap').test;
var undefsafe = require('../lib/undefsafe');

test('get specific array index', function (t) {
var fixture = {
a: [1,2,3,4]
};

var res = undefsafe(fixture, 'a.2');
t.equal(res, 3);
t.end();
});

test('set specific array index', function (t) {
var fixture = {
a: [1,2,3,4]
};

undefsafe(fixture, 'a.2', 30);
t.deepEqual(fixture, { a: [1,2,30,4] });
t.end();
});

68 changes: 68 additions & 0 deletions test/set.test.js
@@ -0,0 +1,68 @@
'use strict';
var test = require('tap').test;
var undefsafe = require('../lib/undefsafe');

test('setting deep object values', function (t) {
var fixture = {
a: {
b: {
c: {
d: 10
}
}
}
};

undefsafe(fixture, 'a.b.c.d', 20);
t.equal(fixture.a.b.c.d, 20, 'deep primative changed');
t.end();
});

test('setting shallow object values', function (t) {
var fixture = {
a: {
b: {
c: {
d: 10
}
}
}
};

undefsafe(fixture, 'a.b', 20);
t.equal(fixture.a.b, 20, 'shallow object changed');
t.end();
});

test('undef value', function (t) {
var fixture = {
a: {
b: {
c: {
d: undefined
}
}
}
};

undefsafe(fixture, 'a.b', 20);
t.deepEqual(fixture.a.b, 20, 'swapped undefined');
t.end();
});

test('missing value', function (t) {
var fixture = {
a: {
b: {
c: {
d: 10
}
}
}
};

var res = undefsafe(fixture, 'a.c', 20);
t.equal(res, undefined, 'target was not found');
t.deepEqual(fixture.a.b, { c: { d: 10 } }, 'shallow object changed');
t.end();
});

0 comments on commit aab63c2

Please sign in to comment.