我真的很喜欢 Roland Jegorov 的回答,但我有一个非常复杂的对象需要搜索,而这个答案无法解释它。
如果您处于像我这样的情况,您可能需要首先确保您没有循环引用(否则您将遇到无限搜索)。有几种方法可以做到这一点,但我不得不对我的对象进行字符串化以将其复制到其他窗口中,所以我最终使用了这个循环替换器:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
(在此处更新 - 我对 MDN 中的 getCircularReplacer 函数做了一个小改动,因此它不再遗漏函数引用,因为这是我正在寻找的!)
(更新 3 - 我还想检查类的任何实例的方法,但我返回的只是“函数”太早了,所以我已经对其进行了调整以包含实例方法。我认为它终于可以按我的预期工作了! )
const getCircularReplacer = () => {
const seen = new WeakSet();
return (key, value) => {
if (typeof value === "function") {
if (value?.prototype) {
if (seen.has(value.prototype)) {
return;
}
seen.add(value.prototype)
return value.prototype
}
return "function";
}
if (typeof value === "object" && value !== null) {
if (seen.has(value)) {
return;
}
seen.add(value);
}
return value;
};
};
const nonCyclicObject = JSON.parse(JSON.stringify(myComplexObject, getCircularReplacer()));
然后我使用了这个修改版的罗兰回答:
(更新 2:我必须确保在找到密钥后不返回,因为如果对象的第一级具有该密钥,它只会在仅调用一次函数后返回)
function findPathsToKey(options) {
let count = 0;
let results = [];
(function findKey({
key,
obj,
pathToKey,
}) {
count += 1;
if (obj === null) return;
const oldPath = `${pathToKey ? pathToKey + "." : ""}`;
if (Object.hasOwnProperty.call(obj, key)) {
results.push(`${oldPath}${key}`);
}
if (typeof obj === "object" && !Array.isArray(obj)) {
for (const k in obj) {
if (Object.hasOwnProperty.call(obj, k)) {
if (Array.isArray(obj[k])) {
for (let j = 0; j < obj[k].length; j++) {
findKey({
obj: obj[k][j],
key,
pathToKey: `${oldPath}${k}[${j}]`,
});
}
}
if (typeof obj[k] === "object") {
findKey({
obj: obj[k],
key,
pathToKey: `${oldPath}${k}`,
});
}
}
}
}
})(options);
return { count, results };
};
计数只是为了解决一点问题并确保它实际上运行了我认为的键数量。希望这可以帮助任何其他寻找解决方案的人!