Since originally answering this question, I was inspired to work on a library to do just this: koalaesce.
It works something like:
var test = {
obj: check,
oi: "5"
}
var lord = {
sol: "5"
};
var holand = {
vol: "try",
mice: lord
}
var second = {
bol: "true"
};
var check = {
fol: holand
}
function getDescendent(base, steps) {
var step = base;
for (var i = 0; i < steps.length; ++i) {
if (step.hasOwnProperty(steps[i])) {
step = step[steps[i]];
} else {
throw new Error("Missing link at " + steps[i]);
}
}
return step;
}
document.write(getDescendent(check, ["fol", "mice", "sol"]));
try {
document.write(getDescendent(check, ["fol", "tofu", "sol"]));
} catch (e) {
document.write(e);
}
The algorithm here starts from a base
object and works its way down, going through an array of strings representing the property name of each step. It checks to make sure the current object has its own property (not an inherited one) with the appropriate name, then walks down to that level. If the object does not, it throws with the missing name.
There are a number of occasions where you may want to remove the hasOwnProperty
check, as inherited/prototype properties and methods may be useful (and it won't hurt anything). In your case, with simple objects, the behavior won't change. In most cases, not checking will allow you to access more properties.
For a more clever, ES6 solution, you can also use reduce
and:
let test = {
obj: check,
oi: "5"
}
let lord = {
sol: "5"
};
let holand = {
vol: "try",
mice: lord
}
let second = {
bol: "true"
};
let check = {
fol: holand
}
function getDescendent(base, ...steps) {
return steps.reduce((prev, cur) => {
if (prev && prev.hasOwnProperty(cur)) {
return prev[cur];
} else {
throw new Error("Missing link at " + cur);
}
}, base);
}
document.write(getDescendent(check, "fol", "mice", "sol"));
document.write(getDescendent(check, "fol", "tofu", "sol"));