This question already has an answer here:
-
Test for existence of nested JavaScript object key
48 answers
a "problem" which i have every now and then is that i have an object e.g. user = {}
and through the course of using the app this gets populated. Let's say somwhere, after an AJAX call or something i do this:
user.loc = {
lat: 50,
long: 9
}
At another place i want to check if user.loc.lat
exists.
if(user.loc.lat) {
// do something
}
If it does not exists, this will cause an error. If user.loc.lat
is undefined
, user.loc
of course is undefined
as well.
"Cannot read property 'lat' of null" - Dev Tools error
That means I need to check it like this:
if(user.loc) {
if(user.loc.lat) {
// do something
}
}
or
if(user.loc && user.loc.lat) {
// do something
}
This isn't really pretty and the bigger my objects are the worse it gets - obviously (imagine 10 levels of nesting).
It kind bums me that if(user.loc.lat)
isn't just returning false
if user.loc
is undefined
as well.
What's the ideal way to check situations like this?
You can use an utility function like this:
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
Or, to check only if a property exists, without getting its value:
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')) ...
Well, javascript has try-catch. Depending on what you actually need to do (i.e. what your else
statement would look like if it's undefined
), that may be what you want.
example:
try {
user.loc.lat.doSomething();
} catch(error) {
//report
}
You can combine the checks using lazy and
:
if(user.loc && user.loc.lat) { ...
Or, you use CoffeeScript and write
user.loc?.lat ...
which would run the checks for loc
property and safeguard against empty objects.
Try this if(user && user.loc && user.loc.lat) {...}
You can check value of null and undefined using typeof
If .loc
has value false
than you can try
if(user && user.loc && typeof(user.loc)!=="undefined"){...}
If you have a huge nested object than have a look at
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
Update:
Try lodash.get