Underscore equivalent of Lodash _.get and _.has
As far as I know, undercore doesn't perform a deep search, so you'll have to settle for shallow has
and get
(or change to lodash).
You can also try to implement it yourself (you can check lodash's implementation and try to copy it or come up with your own solution).
This is a simple solution to the has
problem (get
would be similar), using recursion and the current underscore has
's implementation.
Hope it helps.
var a = {
a: 1,
b: {
a: { c: { d: 1 }}
}
};
var hasDeep = function(obj, path) {
if(!path) return true;
var paths = path.split('.'),
nPath = _.first(paths);
return _.has(obj, nPath) && hasDeep(obj[nPath], _.rest(paths).join('.'));
}
console.log(hasDeep(a, 'b.a.c.d'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore.js"></script>
You can add an extension to underscore with your custom method via _.mixin
this is the mixin that works like a _.get
of lodash
passing the chain of the object to evaluate i.e.
Usage
_.get(a, 'a[0].b');
"collectionValue1" // you will get
Mixin
_.mixin({
get: function(obj, path) {
if (!obj && !path) {
return undefined;
} else {
var paths;
if (!_.isEmpty(path.match(/^\[\d\]/))) {
paths = path.replace(/^[\[\]]/g, '').split(/\./);
nPath = _.first(paths[0].replace(/\]/, ''));
} else {
paths = path.split(/[\.\[]/);
nPath = _.first(paths);
}
remainingPath = _.reduce(_.rest(paths), function(result, item) {
if (!_.isEmpty(item)) {
if (item.match(/^\d\]/)) {
item = "[" + item;
}
result.push(item);
}
return result;
}, []).join('.');
if (_.isEmpty(remainingPath)) {
return obj[nPath];
} else {
return _.has(obj, nPath) && _.get(obj[nPath], remainingPath);
}
}
}
});
Take a look to the sample
var a = {
a: [
{ b: "collectionValue1" },
{ b: "collectionValue2", list: [ { item: "listValue1" }, { item: [{value: "Working"}] }] }
],
b: {
a: {
c: {
d:"success"
}
}
}
};
_.mixin({
get: function(obj, path) {
if (!obj && !path) {
return undefined;
} else {
var paths;
if (!_.isEmpty(path.match(/^\[\d\]/))) {
paths = path.replace(/^[\[\]]/g, '').split(/\./);
nPath = _.first(paths[0].replace(/\]/, ''));
} else {
paths = path.split(/[\.\[]/);
nPath = _.first(paths);
}
remainingPath = _.reduce(_.rest(paths), function(result, item) {
if (!_.isEmpty(item)) {
if (item.match(/^\d\]/)) {
item = "[" + item;
}
result.push(item);
}
return result;
}, []).join('.');
if (_.isEmpty(remainingPath)) {
return obj[nPath];
} else {
return _.has(obj, nPath) && _.get(obj[nPath], remainingPath);
}
}
}
});
console.log(_.get(a, 'a[0].b'));
console.log(_.get(a, 'b.a.c.d'));
console.log(_.get(a, 'a[1].b'));
console.log(_.get(a, 'a[1].list[0].item'));
console.log(_.get(a, 'a[1].list[1].item[0].value'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
There are some external libraries that provide this:
- underscore-contrib
getPath()
- underscore-keypath
valueForKeyPath()
- underscore.get
get()