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.
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.