我非常喜欢Roland Jegorov的答案,但我有一个非常复杂的对象需要搜索,那个答案无法解决。
如果你像我一样处于这种情况,你可能首先要确保没有循环引用(否则你会遇到无限搜索)。有几种方法可以做到这一点,但我必须将我的对象字符串化以将其复制到其他窗口中,所以最终我使用了这个循环替换器:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
(更新 - 我对来自MDN的getCircularReplacer函数进行了小改动,因此它不再省略函数引用,因为这正是我想要的!)
(更新3 - 我还想检查类的任何实例的方法,但我返回的只是'function'太早了,所以我已经调整它以包括实例方法。我认为它最终按照我想要的方式工作了!)
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()));
然后我使用了Roland答案的修改版本:
(更新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 };
};
这个计数只是为了解决问题并确保它实际上通过了我认为的键量。希望这能帮助其他寻找解决方案的人!