![](/img/trans.png)
[英]How do I find objects with a property inside another object in JavaScript
[英]How to loop javascript object of objects and find a property
我有一个样本 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}
我的问题是如何检索 object“测试”是否具有“溶胶”属性,该属性位于另一个 object 几层深处。 它应该是一个有点递归的 function 吗? 如果 function 返回 true(属性存在),是否可以检索属性的某种路径。 在这种情况下,路径应该是 test["obj"]["fol"]["mice"]
自从最初回答这个问题以来,我受到启发去在图书馆工作以做到这一点: 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); }
此处的算法从base
对象开始,一直向下进行,遍历代表每个步骤的属性名称的字符串数组。 它检查以确保当前对象具有其自己的属性( 不是继承的属性)并具有适当的名称,然后向下移动到该级别。 如果对象不存在,则会抛出缺少的名称。
在很多情况下,您可能希望删除hasOwnProperty
检查,因为继承/原型属性和方法可能很有用(并且不会造成任何伤害)。 在您的情况下,使用简单的对象,行为不会改变。 在大多数情况下, 不检查将允许您访问更多属性。
对于更聪明的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"));
您必须有一个正确的想法要检查什么。 即沿着对象层次结构的路径。 因为如果您刚开始递归地迭代所有属性(键),那么它一开始就没有效率,并且很有可能进入循环引用。
不过,您可以查询对象属性,以及属性的属性。
/**
* 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'));
这是一种(大部分)纯函数式方法,可以使用某种“条件”进行递归:
/**
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
如果需要对象的“已找到”子属性值的完整路径,您可以创建一个新键值_parent
以添加到子属性 object。此_parent
将是一个包含完整子属性路径的字符串。 在传递给回调 function 之前,它会在每次递归时更新。然后,可以返回_path
而不是true
条件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.