24

So there are questions on S.O. that answer how to check if a property on an object exists. Example Answer is to use Object.prototype.hasOwnProperty().

However, how would you check the property of a potentially undefined object?

If one were to attempt to just directly check if a property exists on an undefined object then it would be a reference error.

Semantically, it seems better to check code directly if (obj.prop) //dosomething -- it shows clearer intent. Is there any way to achieve this? Preferably, is there a built-in Javascript method to do such a thing or by convention?

Motive: A package adds property user.session.email -- but I'm checking to see if email exists, not the session, though the session could be nonexistent.

Update: Many of the answers say to use the && operator to short-circuit. I'm aware that this is a possible solution, but it is not exactly what is desired as it seems like we're working AROUND the JS object syntax -- that is, though you want to really check for a property on an object, you are being forced to check if the object exists in order to do so.

Note to being marked as closed Why was this marked as closed? The link that presumes this is a duplicate may not yield the same answers. We're looking for a better, more semantic solution and marking this closed makes the assumption that "nested" === "potentially undefined".

This question is disputably closed: Since I can't answer my own question now. As of recently, a proposal was put in Stage 1 here that would solve this very issue. Again, the question wants a more semantic solution as is shown in the proposal.

steviesh
  • 1,740
  • 6
  • 19
  • 33
  • 3
    It wouldn’t be a syntactical error, it would be a ReferenceError. You can check `obj && obj.prop`. – Sebastian Simon Aug 25 '16 at 02:19
  • 2
    Is the `obj` variable definitely going to exist but just might have an `undefined` value? By the way, testing `if (obj.prop)` doesn't test if a property exists, it tests if a property exists *and* has a truthy value. – nnnnnn Aug 25 '16 at 02:19
  • Ah - fixed question description, but the question still remains valid because you're essentially checking to see if both an object and property exist, when I'm only trying to really check if a property exists. – steviesh Aug 25 '16 at 02:20
  • 1
    @pocket Part of defensive programming is accounting for situations that will throw an error. If the object may not exist, you need to make sure it exists before referencing a property of it. – Jecoms Aug 25 '16 at 02:22
  • @nnnnnn admittedly, I have not seen this link before, and I think it's tangentially related and adds to the question - but the answers are not the same. Perhaps I can add detail to the question that I'm specifically looking for JS convention, or built-in ways to write clearer code. – steviesh Aug 25 '16 at 02:34
  • You must check each level for existence. – 4castle Aug 25 '16 at 02:41
  • @4castle thanks. I knew well in advance that that is a possible solution see question above. – steviesh Aug 25 '16 at 02:41
  • You'll notice all the answers contain `&&` because this is convention when checking for object definition and property presence. – Seth Aug 25 '16 at 02:41
  • *"though you want to really check for a property on an object, you are being forced to check if the object exists in order to do so"* - This is exactly the case. There is no shortcut to jump straight to the particular property you want to test (unless you count adding a try/catch as a reasonable "shortcut" - I don't). If you want to abstract away the process then you can write a (recursive or looping) function that does the check for you - the linked duplicate has multiple implementations of that concept. – nnnnnn Aug 25 '16 at 02:42
  • It would be nice to have something like the C# "Elvis" operator `?.` as seen in `foo?.bar` (if foo is null, then the expression chain is escaped and null is returned early), but I don't see something like that being added to JS as it is already a dynamic language and doesn't need a nullable operator. – Jecoms Aug 25 '16 at 15:33
  • @Jecoms I'd like to update this question. That proposal was just put in https://github.com/tc39/proposal-optional-chaining and I've voted to reopen. – steviesh Mar 18 '18 at 05:37

3 Answers3

20

If you're certain the parent object exists, then:

if(obj && obj.key) {
  console.log(obj.key);
}

However, this example will fail miserably if obj doesn't exist.

if (obj && obj.key) {
  console.log(obj.key);
}

... which is why you might want to check if the object is defined when checking for the property. This ensures that you won't get runtime errors if the condition is hit and the property's object hasn't been set.

if(typeof obj != "undefined" && obj.key) { 
  console.log('you will not see this logged')
}

You'll notice that the above example does not throw an exception.

var obj = {key: 1};

if(typeof obj != "undefined" && obj.key) {
  console.log('we have obj! and val is : ' + obj.key)
}

This is a much more defensive approach but it allows for portability. If you wanted to extract your logic into a module for reuse, you may want to check if the object exists as well or risk unwanted errors from an area of the application which you might not necessarily be concerned with.

Seth
  • 10,198
  • 10
  • 45
  • 68
  • If there are no clearer ways to check the property, I will accept this as an answer (as submitted by other people). – steviesh Aug 25 '16 at 02:43
  • 2
    Note that `typeof obj != "undefined"` will give a reference error if `obj` has been defined with `let` or `const` at a point after the `typeof` check. – nnnnnn Aug 25 '16 at 02:48
  • 8
    Note that `var a = { a:false, b:0, c:null}` breaks these tests, since `a.a` and `a.b` and `a.c` all evaluate to not truthy, so `if (a && a.a) { ... }` will not think it's defined, but it is. – artfulrobot Aug 31 '17 at 15:17
13

if you want to check both obj and prop exists (like you mentioned in your comments) you have to do:

if(obj && obj.hasOwnProperty('some')) or if(obj && obj.some)

As mentioned in comments this will throw error if obj is undefined. A better comparison would be would be:

if(typeof obj != "undefined" && obj.hasOwnProperty('some'))
Nishanth Matha
  • 5,993
  • 2
  • 19
  • 28
-2

You could do something like:

if(user.session && 'email' in user.session) //do something...

in case you're sure that user is defined.

adonike
  • 1,038
  • 10
  • 8