web-dev-qa-db-ja.com

JavaScript、null / undefinedのネストされたオブジェクトプロパティをチェックするエレガントな方法

私が時々持っている「問題」は、私がオブジェクトを持っているということです。 user = {}そしてアプリを使用する過程で、これが読み込まれます。 AJAX呼び出しまたは何かをした後、どこかで言ってみましょう。

user.loc = {
    lat: 50,
    long: 9
}

別の場所で、user.loc.latが存在するかどうかを確認します。

if (user.loc.lat) {
    // do something
}

存在しない場合、エラーが発生します。 user.loc.latundefinedの場合、もちろんuser.locundefinedです。

"Cannot read property 'lat' of null" - Dev Tools error

つまり、次のように確認する必要があります。

if (user.loc) {
    if (user.loc.lat) {
        // do something
    }
}

または

if (user.loc && user.loc.lat) {
    // do something
}

これはあまりきれいではなく、オブジェクトが大きくなればなるほど悪化します-明らかに(10レベルのネストを想像してください)。 user.locfalseである場合、if(user.loc.lat)undefinedを返すだけではないということはありがたいことです。

このような状況をチェックする理想的な方法は何ですか?

89
ProblemsOfSumit

次のようなユーティリティ関数を使用できます。

get = function(obj, key) {
    return key.split(".").reduce(function(o, x) {
        return (typeof o == "undefined" || o === null) ? o : o[x];
    }, obj);
}

使用法:

 get(user, 'loc.lat')     // 50
 get(user, 'loc.foo.bar') // undefined

または、値を取得せずに、プロパティが存在するかどうかのみを確認するには:

has = function(obj, key) {
    return key.split(".").every(function(x) {
        if(typeof obj != "object" || obj === null || ! x in obj)
            return false;
        obj = obj[x];
        return true;
    });
}

if(has(user, 'loc.lat')) ...
122
georg

さて、javascriptにはtry-catchがあります。実際に何をする必要があるか(つまり、elseの場合、undefinedステートメントはどのように見えるか)に応じて、それが望みどおりになる場合があります。

例:

try {
   user.loc.lat.doSomething();
} catch(error) {
   //report
}
19
MarioDS

遅延andを使用してチェックを結合できます。

if(user.loc && user.loc.lat) { ...

または、CoffeeScriptを使用して記述します

user.loc?.lat ...

locプロパティのチェックを実行し、空のオブジェクトから保護します。

8
punund

これを試してくださいif(user && user.loc && user.loc.lat) {...}

typeof を使用して、nullおよび未定義の値を確認できます。

.locの値がfalseの場合、試すことができます

if(user && user.loc && typeof(user.loc)!=="undefined"){...}

あなたが見ているよりも巨大なネストされたオブジェクトを持っている場合

Source .

function checkNested(obj /*, level1, level2, ... levelN*/) {
  var args = Array.prototype.slice.call(arguments),
      obj = args.shift();

  for (var i = 0; i < args.length; i++) {
    if (!obj.hasOwnProperty(args[i])) {
      return false;
    }
    obj = obj[args[i]];
  }
  return true;
}

var test = {level1:{level2:{level3:'level3'}} };

checkNested(test, 'level1', 'level2', 'level3'); // true
checkNested(test, 'level1', 'level2', 'foo'); // false

更新:試す lodash.get

6
Aamir Afridi