function optionalAccess(obj, path, def) { const propNames = path.replace(/\]|\)/, "").split(/\.|\[|\(/); return propNames.reduce((acc, prop) => acc[prop] || def, obj); } function proxyOptional(obj, evalFunc, def) { const handler = { get: function(target, prop, receiver) { const res = Reflect.get(...arguments); return typeof res === "object" ? proxify(res) : res != null ? res : def; } }; const proxify = target => { return new Proxy(target, handler); }; return evalFunc(proxify(obj, handler)); } const obj = { items: [{ hello: "Hello" }] }; console.log(optionalAccess(obj, "items[0].hello", "def")); // Prints Hello console.log(optionalAccess(obj, "items[0].he", "def")); // Prints def console.log(proxyOptional(obj, target => target.items[0].hello, "def")); // Prints Hello console.log(proxyOptional(obj, target => target.items[0].hell, { a: 1 })); // Prinst { a: 1 } console.log((obj && obj.items && obj.items[0] && obj.items[0].hello) || "def"); // Prints Hello console.log((obj && obj.items && obj.items[0] && obj.items[0].hel) || "def"); // Prints def