我最近看到有人问这个问题,其中 OP 想要找到对象属性的路径,所以我用伪代码回答了这个问题,说我没有足够的时间来实际编写解决方案。然而,这个问题对我来说太有趣了,以至于我最终还是试图写一个解决方案。到目前为止,这是我想出的:
function isEmpty(obj) {
for (var prop in obj) {
if (Object.prototype.hasOwnProperty.call(obj, prop)) {
return false;
}
}
return true;
}
function Node(obj, parent, searchTarget) {
this.parent = parent;
this.obj = obj;
this.searchTarget = searchTarget;
this.searchNode = function() {
if(this.obj == this.searchTarget) {
//return this.reconstructPathRecursive();
}
if (!isEmpty(this.obj)) {
var children = [];
for (prop in this.obj) {
if (this.obj.hasOwnProperty(prop)) {
children.push(new Node(this.obj[prop], this, searchTarget));
}
}
var path;
for(var i = 0, len = children.length; i < len; i++) {
path = children[i].searchNode();
if(path) return path;
}
}
}
this.reconstructPathRecursive = function() {
var path = [this], curObj = this.parent;
while (curObj != undefined) {
path.push(curObj);
curObj = curObj.parent;
if(curObj == undefined) break;
}
return path;
}
this.findPath = function() {
return this.searchNode();
}
}
var myObj = {
nullRoot: "gotcha!",
path1: {
myFunc: function() {
alert("Success!");
}
}
}
function findFunctionPath(obj, func) {
return new Node(obj, undefined, func).findPath();
}
var thisFunc = myObj.path1.myFunc;
console.log("--");
console.log(findFunctionPath(myObj, thisFunc));
这个想法是我会调用this.searchNode()
代表每个对象属性的 Node 对象。searchNode()
将在每个结果属性节点上调用自身,并将当前对象作为parent
每个子节点上的 传递。如果我找到要搜索的函数,我会调用reconstructPathRecursive()
,这几乎就是这样做的,使用每个节点上的 parent 属性。
但是,我收到“超出最大调用堆栈大小”。运行此实时测试时出错。我认为这意味着我不小心以某种方式编写了一个无限循环。我的逻辑缺陷在哪里,无限循环又在哪里潜入?console.log
表明它searchNode
被一遍又一遍地调用,而我只在对象不为空时调用它,并且我没有在任何地方给对象引用自身(我不认为......),所以我真的有点难住了。
编辑:我稍微更新了代码以isEmpty
从节点函数更改为全局函数,以便我可以this.obj
在searchNode()
函数中调用它。以前,它只会在节点上调用它(它总是至少有两个属性,从而导致无限循环),而不是引用的对象。这已修复,但错误仍然存在。
另一个编辑:发现并更正了另一个错误(见 Satyajit 的回答)。不过,仍然会陷入无限循环。