From aab63c28b2610d4878fa4b74aea6b87d4bca207c Mon Sep 17 00:00:00 2001 From: Remy Sharp Date: Wed, 13 Apr 2016 21:55:52 +0100 Subject: [PATCH] feat: support setting values --- README.md | 21 ++++++++++++-- lib/undefsafe.js | 9 ++++-- test/array.test.js | 24 ++++++++++++++++ test/set.test.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 118 insertions(+), 4 deletions(-) create mode 100644 test/array.test.js create mode 100644 test/set.test.js diff --git a/README.md b/README.md index fb5a5b8..a6c1f10 100644 --- a/README.md +++ b/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 @@ -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 +``` diff --git a/lib/undefsafe.js b/lib/undefsafe.js index 3e42d23..6df2a45 100644 --- a/lib/undefsafe.js +++ b/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') { @@ -13,6 +14,7 @@ function undefsafe(obj, path) { } while ((key = parts.shift())) { + parent = obj; obj = obj[key]; if (obj === undefined || obj === null) { break; @@ -23,6 +25,9 @@ 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; @@ -30,4 +35,4 @@ function undefsafe(obj, path) { if (typeof module !== 'undefined') { module.exports = undefsafe; -} \ No newline at end of file +} diff --git a/test/array.test.js b/test/array.test.js new file mode 100644 index 0000000..5abed19 --- /dev/null +++ b/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(); +}); + diff --git a/test/set.test.js b/test/set.test.js new file mode 100644 index 0000000..893ac21 --- /dev/null +++ b/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(); +});