![](/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.