简体   繁体   English

如何循环对象的javascript object并找到一个属性

[英]How to loop javascript object of objects and find a property

I have a sample object:我有一个样本 object:

var test = {obj: check, oi: "5"  }        
var lord = {sol: "5"};
var holand = {vol: "try", mice: lord}
var second = {bol: "true"};
var check = { fol: holand}

my question is how to retrieve if object "test" has a property of "sol" which is in another object several layers deep.我的问题是如何检索 object“测试”是否具有“溶胶”属性,该属性位于另一个 object 几层深处。 Should it be a somewhat recursive function?它应该是一个有点递归的 function 吗? Is it possible to retrieve some kind of path to the property if the function returns true (property exists).如果 function 返回 true(属性存在),是否可以检索属性的某种路径。 In this case the path should be test["obj"]["fol"]["mice"]在这种情况下,路径应该是 test["obj"]["fol"]["mice"]

Since originally answering this question, I was inspired to work on a library to do just this: koalaesce . 自从最初回答这个问题以来,我受到启发去在图书馆工作以做到这一点: 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. 此处的算法从base对象开始,一直向下进行,遍历代表每个步骤的属性名称的字符串数组。 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). 在很多情况下,您可能希望删除hasOwnProperty检查,因为继承/原型属性和方法可能很有用(并且不会造成任何伤害)。 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: 对于更聪明的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"));

you can do a recursive loop by checking against the object's properties. 您可以通过检查对象的属性来进行递归循环。 this thread describes how to check if that property exists. 此线程描述如何检查该属性是否存在。

How do I check if an object has a property in JavaScript? 如何检查对象在JavaScript中是否具有属性?

and yes you will have to keep track as you recurse if you want to know the path. 是的,如果您想知道路径,则在递归时必须保持跟踪。

You must have a proper idea what you want to check. 您必须有一个正确的想法要检查什么。 Ie the path down the object hierarchy. 即沿着对象层次结构的路径。 Because if you just started iterating all properties (keys) recursively, it won't be efficient at first place and there is a good chance of getting into looped references. 因为如果您刚开始递归地迭代所有属性(键),那么它一开始就没有效率,并且很有可能进入循环引用。

Nevertheless, you can query object properties, and property's properties down the hierarchy: 不过,您可以查询对象属性,以及属性的属性。

/**
 * 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'));

Here is a (mostly) pure functional approach to recurse with some sort of 'condition':这是一种(大部分)纯函数式方法,可以使用某种“条件”进行递归:

/**
    Recurse through object until condition is met.
    @param {Array} objs An array of objects
    @return {Boolean} Whether condition is met.
*/
const recurseObjs = (objs, condition) => {
    const _subObjs = []
    for (let obj of objs) {
        for (let val of Object.values(obj)) {
            if (val === condition /*replace with some condition or multiple*/) return true // Stop if your condition is found
            else if (typeof val === 'object' && val !== null && Object.prototype.toString.call(val) !== '[object Array]') _subObjs.push(val) // Else recurse through subobjects that are not array or null
        }
    }
    if (_subObjs.length > 0) return recurseObjs(_subObjs, condition); 
    return false // Default return value if condition not found
}

recurseObjs([{foo:'bar'},{hello:{cruel:'world'}}],'world') // => true
recurseObjs([{foo:'bar'},{hello:{cruel:'world'}}],'test') // => false

If having the full path of the object's "found" subproperty value is needed, you can instead create a new key value _parent to add to the subproperty object. This _parent will be a string which holds the full subproperty path.如果需要对象的“已找到”子属性值的完整路径,您可以创建一个新键值_parent以添加到子属性 object。此_parent将是一个包含完整子属性路径的字符串。 It is updated on each recursion before being passed to the callback function. Then, _path can be returned instead of the true condition.在传递给回调 function 之前,它会在每次递归时更新。然后,可以返回_path而不是true条件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在 JavaScript 中的另一个对象中找到具有属性的对象 - How do I find objects with a property inside another object in JavaScript 如何在对象数组中查找和编辑对象的属性? - How to find and edit property of object in the array of an objects? 循环遍历对象数组以查找具有匹配属性的对象 - Loop through array of objects to find object with matching property 如何将动态对象添加到javascript对象属性 - How to add dynamic objects to javascript object property 如何使用JavaScript函数编程从对象列表中找到属性最低的对象? - How to find the object which has the lowest property from a list of objects using JavaScript functional programming? 如何使用 react 和 javascript 在对象数组中查找某些 object 属性的计数? - How to find the count of some object property in array of objects using react and javascript? 如何在两个嵌套对象中找到属性值匹配的 object? (JavaScript) - How to find the object where property values match in two nested objects? (Javascript) 在另一个数组内的JavaScript对象数组中按属性查找对象 - Find object by property in an array of JavaScript objects inside another array JavaScript 循环遍历所有现有对象以找到 object 密钥 - JavaScript loop through all existing objects to find an object key JavaScript查找对象属性 - JavaScript find Object Property
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM