With optional chaining and nullish coalescing, we can achieve simpler and more shorthand syntax like this:
Before optional chaining and nullish coalescing
function(...params) {
// ...
return (obj1 && obj1.obj2 && obj1.obj2.arrProp &&
obj1.obj2.arrProp[1] && obj1.obj2.arrProp[1].prop) || "fallback";
}
this can be shortened with optional chaining and nullish coalescing to the below, with a small but important difference re falsy vs. nullish values.
With optional chaining and nullish coalescing:
function(...params) {
// ...
return obj1?.obj2?.arrProp?.[1]?.prop ?? "fallback"
}
…but what if you want to reference another property if the first is nullish.
Referencing "fallback properties"
function(...params) {
// ...
return obj1?.obj2?.arrProp?.[1]?.prop1 ?? obj1?.obj2?.arrProp?.[1]?.prop2 ?? obj1?.obj2?.arrProp?.[1]?.prop3 ?? "fallback";
}
Or you may save the higher-level object and compare properties under it to simplify the expression, like this:
function(...params) {
// ...
const obj = obj1?.obj2?.arrProp?.[1];
const { prop1, prop2, prop3 } = obj ?? {};
return prop1 ?? prop2 ?? prop3 ?? "fallback";
}
I propose adding a new syntax for this to allow referencing fallback properties inline.
Fallback property syntax
function(...params) {
// ...
return obj1?.obj2?.arrProp?.[1]?.prop1.|prop2.|prop3 ?? "fallback";
}
Here, the pipe operator would as a sibling-level optional chaining operator. This can be used for the final property in an object path string or anywhere in the middle:
function(...params) {
// ...
return obj1?.subObj1.|subObj2.|subObj3?.arrProp?.[1].|[2].|[3]?.prop1.|prop2.|prop3.desiredValue ?? "fallback";
}
It's important to keep in mind that it should probably only be used mid-string when dealing with properties/elements that have the same structure as the rest of the path will still be used.
While this particular example may look complicated, it's meant to, in the heart of showing how powerfully it can be used. Destructuring an also look ugly in some opinions with enough nested layers and defaults, but used practically, it's a welcome and worthy feature in JavaScript.
To be clear, the above block would nbeed to be written like this (below) with existing syntax AFAIK:
function(...params) {
// ...
const fallback = "fallback";
const { subObj1, subObj2, subObj3 } = obj1 ?? {};
const subObj = subObj1 ?? subObj2 ?? subObj3;
if (subObj == null) return fallback;
const [elem1, elem2, elem3] = subObj.arrProp ?? [];
const elem = elem1 ?? elem2 ?? elem3;
if (elem == null) return fallback;
const { prop1, prop2, prop3 } = elem ?? {};
const prop = prop1 ?? prop2 ?? prop3;
if (prop == null) return fallback;
return prop.desiredValue ?? fallback;
}