我有一个示例对象:
var test = {obj: check, oi: "5" }
var lord = {sol: "5"};
var holand = {vol: "try", mice: lord}
var second = {bol: "true"};
var check = { fol: holand}
我的问题是如何检索对象“test”是否具有“sol”属性,该属性在另一个对象中有几层深。它应该是一个有点递归的功能吗?如果函数返回true(属性存在),是否可以检索属性的某种路径。在这种情况下,路径应该是test [“obj”] [“fol”] [“mice”]
答案 0 :(得分:2)
自从最初回答这个问题以来,我受到了启发,想要在图书馆工作:koalaesce。
它的作用类似于:
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);
}
&#13;
这里的算法从base
对象开始,向下工作,遍历表示每个步骤的属性名称的字符串数组。它会检查以确保当前对象具有自己的属性(不是继承的属性),并使用适当的名称,然后向下遍历该级别。如果对象没有,则抛出缺少的名称。
在许多情况下,您可能希望删除hasOwnProperty
检查,因为继承/原型属性和方法可能有用(并且它不会伤害任何东西)。在您的情况下,使用简单的对象,行为不会发生变化。在大多数情况下, not 检查将允许您访问更多属性。
对于更聪明的ES6解决方案,您还可以使用reduce
和:
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"));
答案 1 :(得分:0)
您可以通过检查对象的属性来执行递归循环。该线程描述了如何检查该属性是否存在。
How do I check if an object has a property in JavaScript?
是的,如果你想知道路径,你必须跟踪你的追踪。
答案 2 :(得分:0)
您必须正确了解要检查的内容。即对象层次结构中的路径。因为如果你刚开始以递归的方式迭代所有属性(键),那么它在第一时间就不会有效,并且很有可能进入循环引用。
尽管如此,您可以在层次结构中查询对象属性和属性的属性:
/**
* Get a property defined under given object's hierarchy, matching given path.
* @param obj Object to look into.
* @param path filesystem style path for properties. E.g '/prop1/prop2/prop3'
* @returns {*} Property under object hierarchy, or undefined.
*/
function getProp(obj,path){
var props = path.split('/').reverse();
var p;
var o = obj;
while( p = props.pop()){
o = o[p]; // you can use your preferred scope. i.e own property only
if(o == undefined){
return o;
}
}
return o;
}
/**
* Utility function to check if a property is defined under given object's hierarchy, matching given path.
* @param obj Object to look into.
* @param path filesystem style path for properties. E.g '/prop1/prop2/prop3'
* @returns {boolean} true if property is defined, false if property is undefined.
*/
function hasProp(obj, path){
return getProp(obj,path) != undefined;
}
// Test object
var testObj = {
a:{
b:{
c:'hello',
d:{
e:'world'
}
}
}
};
// valid property paths
console.log(hasProp(testObj,'a/b/c/'));
console.log(hasProp(testObj,'a/b/d/e'));
console.log(getProp(testObj,'a/b/c/'));
console.log(getProp(testObj,'a/b/d/e'));
// invalid property paths
console.log(hasProp(testObj,'a/d/c/'));
console.log(hasProp(testObj,'a/b/d/e/f'));
console.log(getProp(testObj,'a/d/c/'));
console.log(getProp(testObj,'a/b/d/e/f'));