web-dev-qa-db-fra.com

JavaScript, une manière élégante de vérifier les propriétés d'objet imbriquées pour null / undefined

un "problème" que j’ai de temps en temps est que j’ai un objet, par exemple. user = {} Et au cours de l'utilisation de l'application, ceci est rempli. Disons quelque part, après un appel AJAX ou quelque chose comme ça:

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

À un autre endroit, je veux vérifier si user.loc.lat Existe.

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

S'il n'existe pas, cela provoquera une erreur. Si user.loc.lat Est undefined, user.loc Est bien sûr aussi undefined.

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

Cela signifie que je dois vérifier comme ça:

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

ou

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

Ce n'est pas vraiment joli et plus mes objets sont gros, plus ça empire - évidemment (imaginez 10 niveaux de nidification). Cela m'ennuie que if(user.loc.lat) ne retourne pas simplement false si user.loc Est également undefined.

Quel est le moyen idéal de vérifier de telles situations?

89
ProblemsOfSumit

Vous pouvez utiliser une fonction utilitaire comme ceci:

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

Usage:

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

Ou, pour vérifier uniquement si une propriété existe sans obtenir sa valeur:

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

Eh bien, javascript a try-catch. Selon ce que vous devez réellement faire (c’est-à-dire à quoi ressemblerait votre déclaration else si c’était undefined, cela pourrait être ce que vous souhaitiez.

exemple:

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

Vous pouvez combiner les contrôles en utilisant lazy and:

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

Ou, vous utilisez CoffeeScript et écrivez

user.loc?.lat ...

qui exécuterait les vérifications de la propriété loc et se protégerait contre les objets vides.

8
punund

Essayez ceci if(user && user.loc && user.loc.lat) {...}

Vous pouvez vérifier les valeurs null et indéfinie en utilisant typeof

Si .loc A la valeur false que vous ne pouvez essayer

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

Si vous avez un objet imbriqué énorme que regarder

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

Mise à jour: Essayez lodash.get

6
Aamir Afridi