Package Exports
- safe-obj
This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (safe-obj) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.
Readme
Safe-obj
Underscore helpers to make object accessors safe
I came (partly) from a Perl background where you could say $obj->{thing}->{another_thing}->{more_things}, and it would not blow up even if $obj was totally empty. Similarly, you could say $obj->{thing}->{foo} = 'bar', even if $obj had no property called 'thing'. I don't miss everything about Perl, but I do miss that. In javascript, you'd have to say:
if (obj && obj.thing && obj.thing.another_thing && obj.thing.another_thing.more_things) {
// I want to die a little bit
}So this module is basically auto-vivification for javascript.
Install
npm install safe-obj --save
Usage
Server
As of v1.0.0, this module works with both lodash and underscore, though it requires using _.safe(obj, path) with lodash since _(obj).safe(path) triggers lodash's chaining.
safe-obj exports an object that can be mixed into underscore/lodash like this:
_.mixin(require('safe-obj'));that let's you access object properties with wild abandon.
Client
Additionally, as of v1.0.0, it works on the client side. If window._ is defined (i.e. lodash or underscore has been loaded), _.safe will add an _safe property to it, which you can mix in with _.mixin(_._safe).
On the client, just include the script after underscore or lodash:
<script src="/underscore.js"></script>
<script src="path/to/safe-obj/dist/safe.js"></script>and then mix it in:
<script>
(function() {
_.mixin(_._safe);
})();
</script>API
Safe
Let's you access object properties (and array indices too!) regardless of whether they exist. If, at any point, a property returns undefined (where calling another object accessor would blow up), safe immediately just returns undefined (or a default, if you provide one).
var obj = {}
// returns undefined
var innerProp = _(obj).safe('foo.bar.baz.0.hello.world');
// returns [] - useful if you want to call array methods but don't want to check the type
var anotherProp = _(obj).safe('a.brave.new.world', []); Expand
Let's you assign to any arbitrarily deep and non-existent property on an object. Any non-existent properties are expanded into objects.
var obj = {}
_(obj).expand('foo.bar.baz', 'hello world');
// obj now equals: {
// foo: {
// bar: {
// baz: 'hello world'
// }
// }
// }Expand is likely to be finnicky (at the moment) with expanding arrays. It's untested, and my guess is that it will create object properties with numbers. Something like
property: {
0: {
// more stuff
}
}I'd like to make that work more as expected in a future release, but for now, don't expect it to work.
Ensure
Sets a path to a given value unless that path already has a value. Also allows an optional list of "disallowed" values.
var obj = {
foo: {
bar: 'baz'
}
};
// This will have no effect on obj since 'foo.bar' already has a value
_(obj).ensure('foo.bar', 'a default value');
obj = {
foo: {}
};
// This will set obj.foo equal to { bar: 'a default value' }
_(obj).ensure('foo.bar', 'a default value');
obj = {
foo: {
bar: 'nope'
}
};
// This says don't allow 'nope' as a value of foo.bar, thus it will use the default
_(obj).ensure('foo.bar', [ 'nope' ], 'a default value');AllOf
Uses safe to return true if all the paths exist in the object or false if any is missing.
var obj = {
foo: {
bar: 'baz'
}
};
_(obj).allOf('foo.bar', 'hello.world'); // returns false
// or
// _(obj).allOf(['foo.bar', 'hello.world']);AnyOf
Like allOf but returns true if any of the paths exist.
var obj = {
foo: {
bar: 'baz'
}
};
_(obj).anyOf('foo.bar', 'hello.world'); // returns trueNoneOf
Like allOf and anyOf but only returns true when none of the paths exist.
var obj = {
foo: {
bar: 'baz'
}
};
_(obj).noneOf('foo.bar', 'hello.world'); // returns false

