如何循环对象的javascript对象并查找属性

时间:2015-02-27 15:03:00

标签: javascript loops recursion

我有一个示例对象:

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”]

3 个答案:

答案 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;
&#13;
&#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'));