我有一个要迭代的对象数组,并返回嵌套对象,其中text属性等于给定的字符串参数。 例如,文本属性为“预订内部采访”的对象。要查找的对象可以位于层次结构的任何级别。
我正在尝试类似的操作,但这只允许我查看特定级别的内容:
var txt = "Book an Internal Interview";
var obj = items[0].items[0].items.find(o => o.text === txt);
所以我尝试了一个递归解决方案:
var txt = "Book an Internal Interview";
var obj = customFilter(items, txt)
function customFilter(object, text) {
if (object.hasOwnProperty('text') && object["text"] == text)
return object;
for (var i = 0; i < Object.keys(object).length; i++) {
if (typeof object[Object.keys(object)[i]] == "object") {
var o = customFilter(object[Object.keys(object)[i]],text);
if (o != null)
return o;
}
}
return null;
}
但是我得到一个错误:
超出了最大调用堆栈大小
这是我的对象在控制台中的样子:
0:
action: ""
id: "1"
items: Array(18)
0:
action: "http://localhost:8085/secure/contacts/create.aspx?CandidateID=2256"
id: "20"
label: "Convert to Contact"
leaf: true
level: 1
parent: {id: "1", parentid: "-1", action: "", typeAction: "", text: "Workflow", …}
parentid: "1"
text: "Convert to Contact"
typeAction: "url"
uid: "20"
1:
action: "deleteCandidate(2256);"
id: "2"
label: "Delete"
leaf: true
level: 1
parent: {id: "1", parentid: "-1", action: "", typeAction: "", text: "Workflow", …}
parentid: "1"
text: "Delete"
typeAction: "method"
uid: "2"
2: {id: "21", parentid: "1", action: "ResetModal(); $('#TemplateDialog').dialog('open'); candidateID = 2256", typeAction: "method", text: "Generate Document", …}
3:
action: ""
id: "15"
items: Array(2)
0:
action: "bookClientInterviewSingleCandidate('46','2256')"
id: "16"
label: "Book a Client Interview"
leaf: true
level: 2
parent: {id: "15", parentid: "1", action: "", typeAction: "", text: "Interviews", …}
parentid: "15"
text: "Book a Client Interview"
typeAction: "method"
uid: "16"
1:
action: "bookClientInterviewInternalSingleCandidate('0','2256')"
id: "17"
label: "Book an Internal Interview"
leaf: true
level: 2
parent: {id: "15", parentid: "1", action: "", typeAction: "", text: "Interviews", …}
parentid: "15"
text: "Book an Internal Interview"
typeAction: "method"
uid: "17"
label: "Interviews"
level: 1
parent: {id: "1", parentid: "-1", action: "", typeAction: "", text: "Workflow", …}
parentid: "1"
text: "Interviews"
typeAction: ""
uid: "15"
4:
action: "DisplayLinkToJobForCandidate('modalDisplay', '2256', 'Abigail Hotmail')"
id: "19"
label: "Link To Job"
leaf: true
level: 1
parent: {id: "1", parentid: "-1", action: "", typeAction: "", text: "Workflow", …}
parentid: "1"
text: "Link To Job"
typeAction: "method"
uid: "19"
5: {id: "18", parentid: "1", action: "loadMessageCenterSingleCandidate(2256)", typeAction: "method", text: "Send Email", …}
6: {id: "14", parentid: "1", action: "submitCVSingleCandidate('46','2256')", typeAction: "method", text: "Submit CV", …}
.............
答案 0 :(得分:2)
如注释中所述,您的输入对象具有循环引用,这意味着嵌套的子对象具有对其祖先之一的引用(可能是parent
属性的情况)。因此,您的代码将无休止地遵循这样的“循环”路径。
您可以通过保留Set
个访问过的对象来保护代码。
function customFilter(object, text, visited = new Set) {
if (!object || visited.has(object)) return; // Do not go into loops and ignore nulls
visited.add(object);
if (object.hasOwnProperty('text') && object["text"] == text)
return object;
for (var i = 0; i < Object.keys(object).length; i++) {
if (typeof object[Object.keys(object)[i]] == "object") {
var o = customFilter(object[Object.keys(object)[i]], text, visited);
if (o != null)
return o;
}
}
return null;
}
所以:
Set
参数。您不需要在初始调用中指定它,因为默认情况下它将是一个空Set,但是递归调用应传递第三个参数 Set
将消耗一些内存(与原始输入大小成线性关系)。如果您知道是造成此类反向引用的parent
属性,那么您也可以通过从循环中排除该属性来解决它。