An alternative approach is:
((acquaintances.types || {}).friends || {}).others
which is shorter than other solutions, but may or may not thrill you.
You can also build a little helper to make the same idea a tiny bit more palatable:
function maybe(o) { return o || {}; }
Now you can do
maybe(maybe(acquaintances.types).friends).others
If you don't mind writing property names as strings, you could make a little helper:
function maybe(obj) {
return Object.defineProperty(
obj || {},
'get',
{ value: function(prop) { return maybe(obj[prop]); }
);
}
Now you can write
maybe(acquaintances.types').get('friends').others
In ES6, you can do this, albeit clumsily, using destructuring assignment with defaults:
var { types: { friends: { others } = {} } = {} } = acquaintances;
If you want to use this in an expression context, instead of assigning to a variable, in theory you could use argument destructuring:
(({ types: { friends: { others } = {} } = {} }) => others)(acquaintances)
After all is said and done, the standard approach remains
acquaintances.types &&
acquaintances.types.friends &&
acquaintances.types.friends.others
This is why there is an active (?) discussion in the ES6 design groups about a CoffeeScript-like existential operator, but it does not seem to be converging very rapidly.