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