2

Consider an object, user:

user = {
    profile: {
        first_name: "Arthur",
        last_name:  "Dent"
    },
    planet: "Earth"
}

What is the best way to check for existence of user.profile.first_name?

I'd normally use (!!user && !!user.profile && !!user.profile.first_name) but that can't possibly be the best way (especially in longer cases, where there's deeper nesting of attributes).

Curious how this is customarily done!

[EDIT] Consider, for the sake of argument, that you need to check the existence of users.jordan.profile.favorites.color (intentionally long and ungainly), where you cannot be sure of the existence of any individual attribute (so perhaps users.jordan exists but users.jordan.profile does not.)

Granted, this is perhaps a sign of more pervasive problems in your code (e.g. you shouldn't create objects unless all possible attributes are populated) but at times, this can't be helped.

j6m8
  • 2,261
  • 2
  • 26
  • 34
  • i don't like this question, and it's hard to express why, curious if anyone else knows why? – WhiteHat Aug 08 '15 at 01:22
  • I don't particularly like asking it, because it seems like a very subjective question... But it's something I use almost every day, and something I've talked to coworkers and friends about as well. – j6m8 Aug 08 '15 at 02:00
  • right, so it depends on the situation, do you care if it exists or not. how confident are you that it's there, etc.. we should all know how to check it, so it's hard to verify and answer. move it to meta or somewhere. – WhiteHat Aug 08 '15 at 02:08

2 Answers2

3

You can use in to check for a property in an if statement.

if ('profile' in user) {
    alert('I have a profile!');
}

If you need to check a nested value, look on that property:

if ('first_name' in user.profile) {
    alert('I have a first name!');
}

You can also use .hasOwnProperty() as well.

if (user.hasOwnProperty('profile') {
    alert('I have a profile!');
}
aredzko
  • 1,690
  • 14
  • 14
  • you have to touch it, to check it. – WhiteHat Aug 08 '15 at 01:33
  • In order to check for `user.profile.first_name`, you'd still have to check for `profile` and then `first_name` independently, no..? This is probably a better way of checking than the `!!` boolean-coerce method (i.e. `!!` breaks on falsy but extant values) but it's definitely quite verbose. Consider the edge-case of four or five levels of nesting! – j6m8 Aug 08 '15 at 02:07
  • 2
    There's an answer that goes into more depth here: http://stackoverflow.com/questions/2631001/javascript-test-for-existence-of-nested-object-key I just prefer a more verbose method, and usually after 3-4 deep nested values, something can be simplified. – aredzko Aug 08 '15 at 06:21
1

I would use a try catch block:

try { fname = user.profile.first_name } catch(e) { fname = false }
if (fname) ...
Nathan Wilson
  • 856
  • 5
  • 12
  • 1
    i wouldn't, i'd throw an error if it didn't exist. if it's that important. – WhiteHat Aug 08 '15 at 01:30
  • @WhiteHat it depends on the semantic meaning of the attribute not existing. For instance, `user.favorite.color` not existing may not be `Exception`al. (Though probably for the sake of good code-convention, it should be set to *something*...) – j6m8 Aug 08 '15 at 02:08