Подтвердить что ты не робот

JavaScript, элегантный способ проверить свойства вложенных объектов на null/undefined

"проблема", которая у меня время от времени заключается в том, что у меня есть объект, например, user = {} и в процессе использования приложения это заполняется. Скажем где-нибудь, после AJAX-звонка или чего-то такого, что я делаю так:

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

В другом месте я хочу проверить, существует ли user.loc.lat.

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

Если он не существует, это приведет к ошибке. Если user.loc.lat не undefined, user.loc конечно, также не undefined.

"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 уровней вложенности). Мне кажется, что if(user.loc.lat) не просто возвращает false если user.loc не undefined.

Какой идеальный способ проверить подобные ситуации?

4b9b3361

Ответ 1

Вы можете использовать служебную функцию следующим образом:

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')) ...

Ответ 2

Ну, javascript имеет try-catch. В зависимости от того, что вам действительно нужно делать (например, ваш оператор else будет выглядеть, если он undefined), это может быть то, что вы хотите.

Пример:

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

Ответ 3

Вы можете комбинировать проверки с помощью ленивого and:

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

Или вы используете CoffeeScript и пишете

user.loc?.lat ...

который будет запускать проверки для свойства loc и защищать от пустых объектов.

Ответ 4

Попробуйте if(user && user.loc && user.loc.lat) {...}

Вы можете проверить значение null и undefined с помощью typeof

Если .loc имеет значение false, чем вы можете попробовать

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

Если у вас есть огромный вложенный объект, чем на

Источник.

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

Update: Попробуйте lodash.get