1

For example, in iOS Swift, I can do something like this:

if (self.user?.company?.pic?.phoneNumber != null) { doSomething() }

Without the need to:

if (self.user != null && self.user!.company != null && self.user!.company!.pic != null && self.user!.company!.pic!.phoneNumber != null) { doSomething() }

In ReactNative (or Javascript), I found out that if an object is undefined, I can't check for the existence of the variable inside of it, so I have to check first whether the object is undefined or not, only then I can safely check whether the variable inside of it undefined or not.

if (typeof this.state.user !== "undefined" && typeof this.state.user.company !== "undefined" && typeof this.state.user.company.pic !== "undefined" && typeof this.state.user.company.pic.phoneNumber !== undefined) { this.doSomething() }

How can I turn this into just:

if (typeof this.state.user.company.pic.phoneNumber !== "undefined") { this.doSomething() }

or something similar?

Thanks.

Chen Li Yong
  • 3,904
  • 5
  • 39
  • 83
  • You can read this for some information: https://stackoverflow.com/questions/26183944/optional-chaining-in-javascript. Optional chaining is currently a stage 3 proposal for JS: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining – Nick Parsons Oct 09 '19 at 04:27

2 Answers2

1

If you can’t use optional chaining which is still a proposal but available via babel plugin you could use a recursive utility function to test for the presence of each path segment:

const pluck = (item, path) => {
  const [, part, rest] = /^([^.]+)\.*(.*)/.exec(path) || [];
  if (!part) {
    return null;
  }
  const o = (item || {})[part];
  if (o == null) {
    return null;
  }

  return rest.length ? pluck(o, rest) : o;
};

if (pluck(this.state, ‘user.company.pic.phoneNumber’)) {
  doSomething();
}
ray hatfield
  • 16,302
  • 4
  • 25
  • 21
  • Thank you for responding. This opened up some topics I never knew was there in Javascript to research. But on the practicality, I prefer Nick Parsons answer because it's simpler and more understandable. Thanks! – Chen Li Yong Oct 09 '19 at 09:43
1

Currently, optional chaining is a stage 3 draft, and so, you may be able to do it in the future.

EDIT: Optional chaining will now be part of ES2020, and so you'll be able to do the following:

if (self.user?.company?.pic?.phoneNumber !== undefined) { 
  doSomething(); // phoneNumber exists
}

With that being said, it still has very limited browser support.

So, for the time being, you could instead create a function which recursively finds each object from a list of properties like so:

const optional_chain = (obj, [key, ...props]) =>
  obj !== undefined && key ? optional_chain(obj[key], props) : obj;

const user = {
  company: {
    pic: {
      phoneNumber: 1
    }
  }
}

console.log(optional_chain(user, ['company', 'pic', 'phoneNumber'])); // 1
console.log(optional_chain(user, ['company', 'pic', 'phoneNumber', 'x'])); // undefined
console.log(optional_chain(user, ['company', 'picture', 'phoneNumber'])); // undefined
console.log(optional_chain(user, ['x', 'picture', 'phoneNumber'])); // undefined

In your case, the usage would be as so:

if (optional_chain(self.user, ['company', 'pic', 'phoneNumber']) !== undefined) { 
  doSomething(); 
}
Nick Parsons
  • 31,322
  • 6
  • 25
  • 44
  • 1
    Both solution (yours) and the previous one are interesting. But yours doesn't need additional plugin and also more understandable. Thanks! – Chen Li Yong Oct 09 '19 at 09:39
  • Btw, I think we can make it to becomes like: `optional_chain(self.user, "company.pic.phoneNumber")` if we add string `split(".")` on the code. Therefore the code is even more practical. – Chen Li Yong Oct 09 '19 at 09:41
  • @ChenLiYong yep, that's definitely possible if you wish to use a string instead of an array – Nick Parsons Oct 09 '19 at 10:26
  • For the record, my solution doesn’t require a plugin. I was merely suggesting that if you’re using babel, you can enable this functionality and avoid having to write anything yourself to solve it. – ray hatfield Oct 09 '19 at 16:32