1

I always face a situation where I need to check the existence of a specific property before doing something with it, like :

if (this.foo & this.foo.bar){ //first to make sure the `this.foo` is not undefined or null, then read the property `bar`
   // do something with the `this.foo.bar`
}

This kind of checking is used quite often in ReactJS when we need to generate a list of data, like :

{
   this.state.list && this.state.list.map(element => ... )
}

However, if the target property is nested deep inside four or five level, like :

this.foo.bar.baz.qux

And the checking process will be quite verbose :

if(this.foo && this.foo.bar && this.foo.bar.baz && this.foo.bar.baz.qux){
   // do something with `this.foo.bar.baz.qux`
}

I know the main purpose of checking is to make sure that we do not get the error:

Cannot read property qux of undefined (or null)

Is there another approach? I'm looking for a shorter way, like :

qux in this.foo

Any thoughts would be appreciated.

Thanks in advance.

1 Answers1

0

No need for a library, you can make a simple function to which you can pass the object and a list of properties, which will return the nested value if it exists, or undefined:

const getProps = (obj, props) => (
  props.reduce((a, prop) => a !== undefined ? a[prop] : undefined, obj)
);

const obj1 = {
  foo: {
    bar: {
      baz: {
        buzz: {
          value: 'thevalue'
        }
      }
    }
  }
};
const obj2 = {
  foo: {
    bar: {
    }
  }
};
console.log(getProps(obj1, ['foo', 'bar', 'baz', 'buzz', 'value']));
console.log(getProps(obj2, ['foo', 'bar', 'baz', 'buzz', 'value']));

There is also a proposal for optional chaining, which is in Stage 1 at the moment. The proposed syntax to achieve something equivalent to the above is:

obj?.foo?.bar?.baz?.buzz?.value

which will evaluate to the nested property value if it exists, and undefined otherwise.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320