Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Avoiding repetition when deciding whether a member exists several layers deep inside an object.

Object Spelunking

This is trouble:

if (foo.bar.baz.woo.yay === 8675309) {
  doStuff();
}

... because foo or foo.bar or foo.bar.baz or foo.bar.baz.woo might not be there, and you'll get this:

ReferenceError: foo.bar is not defined

Instead we engage in calisthenics like this:

if (foo) {
  if (foo.bar) {
    if (foo.bar.baz) {
      if (foo.bar.baz.woo) {
        if (foo.bar.baz.woo.yay === 8675309) {
          doStuff();
        }
      }
    }
  }
}

Thanks to Oliver Steele's 2007 post Monads on the Cheap I: The Maybe Monad we can try this:

if (((((foo || {}).bar || {}).baz || {}).woo || {}).yay === 8675309) {
  doStuff();
}

... and as long as base object foo is defined, we'll get undefined if the chain breaks at any point.

Where is this useful?

Dealing with API returns from potentially-untrustworthy endpoints. Like this:

const renderListLengthThreeOrGreater = output => {
  if (output.data) {
    if (output.data.stuff) {
      if (output.data.stuff.list) {
        if (output.data.stuff.list.length > 2) {
          output.data.stuff.list.filter(item => {
            doStuffWith(item);
          });
        }
      }
    }
  }
}

... which looks better like this, at least to me:

const renderListLengthThreeOrGreater = output => {
  if (((output.data || {}).stuff || {}).list.length > 2) {
    output.data.stuff.list.filter(item => {
      doStuffWith(item);
    });
  }
}

Here are some tests on JSBEN.CH, which seem to indicate it's faster.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.