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()