JavaScript でnullチェックしつつ多次元配列にアクセスする

TL;DR

CakePHP の Hash::get
Laravel の array_get
みたいな関数作った

追記
Lodash に同じコンセプトの関数があると教えてもらったので、それを使ったほうが良さそう( @n-oshiro さんありがとうございます )
https://lodash.com/docs/4.17.4#get

背景

javascript で多次元(連想)配列を扱う必要があったが、ネストが深いとエラーチェックが大変。


var hoge = {
  'foo': {
    'bar': 'baz'
  }
};

var val = hoge['foo']['bar']

こんな感じの配列アクセスがしたいのだけれど、実践的には値がなかったりするので、エラーチェックや存在チェックをしたい

var val = hoge['foo']['piyo'] || 'default' // default

または

var val = 'default';
if (hoge['foo']['piyo']) {
  val = hoge['foo']['piyo'];
}

こんな感じになるが、例えばネストが深いところの bar みたいなキーにアクセスしようとするとエラーになることがある。
下記はすべてエラーになる。

var val = hoge['foo2']['bar'] || 'default';

var val = 'default';
if (hoge['foo2']['bar'] != undefined) {
  val = hoge['foo2']['bar'];
}

これを解決するには下記のようなチェックをしないといけない。


var val = 'default';
if (hoge['foo2'] != undefined) {
  if (hoge['foo2']['bar'] != undefined) {
    val = hoge['foo2']['bar'];
  }
}

ネストが深いとチェックがどんどん煩雑になっていく

関数作った


var arrayGet = function(ary, path, _default) {
  if (! (ary instanceof Object)) {
    return _default
  }
  if (path.indexOf('.')) {
    path = path.split('.');
  } else {
    path = [path];
  }

  var cursor = ary;
  for (var i = 0; i < path.length; i++) {
    if (cursor[path[i]] == undefined) {
      return _default;
    }
    cursor = cursor[path[i]];
  }
  return cursor;
};

配列のキーにアクセスし、存在したらその値を、存在しない場合はデフォルト値を返す。
キーは'.'で階層を示すので、'.' を含むキーが存在する場合はうまく動作しない。

使い方


var hoge = {
  'foo': {
    'bar': 'baz'
  },
  'fooo': 'baar'
};

arrayGet(hoge, 'foo.bar', 'default') // baz
arrayGet(hoge, 'fooo', 'default') // baar
arrayGet(hoge, 'foo.foo', 'default') // default
arrayGet(hoge, 'foo2.bar', 'default') // default

// 連想配列でなくてもいける

var ary = [
  'a',
  {
    'foo': 'bar'
  }
];

arrayGet(ary, '0') // a
arrayGet(ary, '1.foo') // bar

既存で似たようなライブラリあったら教えてください

以上