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
.
Какой идеальный способ проверить подобные ситуации?
Ответы
Ответ 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